Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
perf: avoid excessive bundle sizes by reusing monacos ts-worker
Browse files Browse the repository at this point in the history
  • Loading branch information
marionebl committed Sep 10, 2018
1 parent f4abf91 commit a00ba8a
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 98 deletions.
30 changes: 25 additions & 5 deletions src/container/pane-development-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,19 @@ export class PaneDevelopmentEditor extends React.Component {

Monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: Monaco.languages.typescript.ScriptTarget.ESNext,
allowNonTsExtensions: true
allowNonTsExtensions: true,
module: Monaco.languages.typescript.ModuleKind.CommonJS
});

Monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
target: Monaco.languages.typescript.ScriptTarget.ESNext,
allowNonTsExtensions: true,
module: Monaco.languages.typescript.ModuleKind.CommonJS
});

this.editor = Monaco.editor.create(this.node, {
language: 'typescript',
value: storeEnhancer.getCode(),
value: storeEnhancer.getTypeScript(),
theme: 'vs-light',
automaticLayout: true
});
Expand All @@ -47,12 +54,25 @@ export class PaneDevelopmentEditor extends React.Component {
}
});

this.editor.onDidChangeModelContent(() => {
storeEnhancer.setCode(this.editor.getValue());
this.editor.onDidChangeModelContent(async () => {
storeEnhancer.setTypeScript(this.editor.getValue());

const model = this.editor.getModel();
const worker = await Monaco.languages.typescript.getTypeScriptWorker();
const client = await worker(model.uri);
const emitOutput = await client.getEmitOutput(model.uri.toString());
const outputFile = emitOutput.outputFiles.find(
file => file.name === `${model.uri.toString()}.js`
);

if (outputFile) {
console.log(outputFile.text);
storeEnhancer.setJavaScript(outputFile.text);
}
});

this.editor.onDidBlurEditor(() => {
storeEnhancer.setCode(this.editor.getValue());
storeEnhancer.setTypeScript(this.editor.getValue());
props.store.commit();
});

Expand Down
5 changes: 3 additions & 2 deletions src/model/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { PatternLibrary, PatternLibraryCreateOptions } from './pattern-library';
import { AnyPatternProperty } from './pattern-property';
import * as Types from '../types';
import { UserStore } from './user-store';
import { UserStoreEnhancer, defaultCode } from './user-store-enhancer';
import { UserStoreEnhancer, defaultCode, defaultJavaScript } from './user-store-enhancer';
import { UserStoreReference } from './user-store-reference';
import * as uuid from 'uuid';

Expand Down Expand Up @@ -188,7 +188,8 @@ export class Project {
id: uuid.v4(),
enhancer: new UserStoreEnhancer({
id: uuid.v4(),
code: defaultCode
typeScript: defaultCode,
javaScript: defaultJavaScript
})
});

Expand Down
127 changes: 39 additions & 88 deletions src/model/user-store-enhancer.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import * as Fs from 'fs';
// import * as Fs from 'fs';
import * as Mobx from 'mobx';
import * as Types from '../types';
import * as TypeScript from 'typescript';
// import * as TypeScript from 'typescript';
import { UserStore } from './user-store';
import { DesignTimeUserStore } from './design-time-user-store';
import * as uuid from 'uuid';
import * as VM from 'vm';

const MemoryFilesystem = require('memory-fs');
// const MemoryFilesystem = require('memory-fs');

export interface UserStoreEnhancerModule {
onStoreCreate(store: DesignTimeUserStore): DesignTimeUserStore;
}

export interface UserStoreEnhancerInit {
id: string;
editedCode?: string;
code: string;
typeScript: string;
javaScript: string;
}

const userStoreApi = (names: string[]) => `
Expand Down Expand Up @@ -83,40 +83,46 @@ export function onStoreCreate(store: Alva.DesignTimeUserStore): Alva.DesignTimeU
}
`;

export const defaultJavaScript =
'exports.onStoreCreate = function onStoreCreate(store) { return store; }';

export class UserStoreEnhancer {
public readonly model = Types.ModelName.UserStoreEnhancer;

@Mobx.observable private id: string;
@Mobx.observable private code: string;

@Mobx.computed
private get js(): string {
const fs = new MemoryFilesystem();
fs.writeFileSync('/file.ts', this.code);
compile('/file.ts', {
compilerOptions: {},
fs,
languageVersion: TypeScript.ScriptTarget.ESNext
});
return String(fs.readFileSync('/file.js'));
}
@Mobx.observable private typeScript: string;
@Mobx.observable private javaScript: string;

// @Mobx.computed
// private get js(): string {
// const fs = new MemoryFilesystem();
// fs.writeFileSync('/file.ts', this.code);
// compile('/file.ts', {
// compilerOptions: {},
// fs,
// languageVersion: TypeScript.ScriptTarget.ESNext
// });
// return String(fs.readFileSync('/file.js'));
// }

@Mobx.computed
private get module(): UserStoreEnhancerModule {
const context = { exports: {}, module: { exports: {} }, console };
VM.runInNewContext(this.getJavaScript(), context);
VM.runInNewContext(this.javaScript, context);
return context.exports as UserStoreEnhancerModule;
}

private usetStore: UserStore;

public constructor(init: UserStoreEnhancerInit) {
this.id = init.id;
this.code = init.code;
this.typeScript = init.typeScript;
this.javaScript = init.javaScript;

if (!init) {
this.id = uuid.v4();
this.code = defaultCode;
this.typeScript = defaultCode;
this.javaScript = defaultJavaScript;
}
}

Expand All @@ -128,25 +134,26 @@ export class UserStoreEnhancer {
return userStoreApi(this.usetStore.getProperties().map(p => JSON.stringify(p.getName())));
}

public getCode(): string {
return this.code;
}

public getId(): string {
return this.id;
}

public getJavaScript(): string {
return this.js;
public getTypeScript(): string {
return this.typeScript;
}

public getModule(): UserStoreEnhancerModule {
return this.module;
}

@Mobx.action
public setCode(code: string): void {
this.code = code;
public setTypeScript(code: string): void {
this.typeScript = code;
}

@Mobx.action
public setJavaScript(javaScript: string): void {
this.javaScript = javaScript;
}

public setUserStore(userStore: UserStore): void {
Expand All @@ -157,68 +164,12 @@ export class UserStoreEnhancer {
return {
model: this.model,
id: this.id,
code: this.code
typeScript: this.typeScript,
javaScript: this.javaScript
};
}

public update(b: this): void {
this.code = b.code;
this.typeScript = b.typeScript;
}
}

export interface CompileOptions {
fs: typeof Fs;
languageVersion: TypeScript.ScriptTarget;
compilerOptions: TypeScript.CompilerOptions;
}

function compile(filename: string, opts: CompileOptions): typeof Fs {
const compilerHost: TypeScript.CompilerHost = {
fileExists(sourceFileName: string): boolean {
return opts.fs.existsSync(`/${sourceFileName}`);
},
getCanonicalFileName(sourceFileName: string): string {
return sourceFileName;
},
getCurrentDirectory(): string {
return '';
},
getDefaultLibFileName(): string {
return 'lib.d.ts';
},
getDirectories(): string[] {
return [];
},
getNewLine(): string {
return '\n';
},
getSourceFile(sourceFileName: string): TypeScript.SourceFile | undefined {
if (!opts.fs.existsSync(`/${sourceFileName}`)) {
return;
}

const source = opts.fs.readFileSync(`/${sourceFileName}`);

if (!source) {
return;
}

return TypeScript.createSourceFile(filename, source.toString(), opts.languageVersion);
},
useCaseSensitiveFileNames(): boolean {
return false;
},
readFile(sourceFileName: string): string | undefined {
const buffer = opts.fs.readFileSync(sourceFileName);
return buffer ? buffer.toString() : undefined;
},
writeFile(sourceFileName: string, text: string): void {
opts.fs.writeFileSync(`/${sourceFileName}`, text);
}
};

const program = TypeScript.createProgram(['file.ts'], opts.compilerOptions, compilerHost);
program.emit();

return opts.fs;
}
4 changes: 2 additions & 2 deletions src/model/user-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class UserStore {
map.set(prop.getId(), prop);
});

/* if (!this.designTimeStore) {
if (!this.designTimeStore) {
return map;
}

Expand All @@ -87,7 +87,7 @@ export class UserStore {

designProperty.setProperty(property);
map.set(property.getId(), property);
}); */
});

return map;
}
Expand Down
3 changes: 2 additions & 1 deletion src/types/user-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,6 @@ export interface SerializedUserStoreReference {
export interface SerializedUserStoreEnhancer {
model: ModelName.UserStoreEnhancer;
id: string;
code: string;
typeScript: string;
javaScript: string;
}

0 comments on commit a00ba8a

Please sign in to comment.