Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

diez compile --watch Option? #138

Open
phil-lgr opened this issue Jul 12, 2020 · 3 comments
Open

diez compile --watch Option? #138

phil-lgr opened this issue Jul 12, 2020 · 3 comments

Comments

@phil-lgr
Copy link

phil-lgr commented Jul 12, 2020

At the cli level, I would like to run diez compile -t web in watch mode, i.e. rebuilding the package when I change design src files.

If this is something that makes sense, I could give this a try and add a --watch option with some guidance over here:

It would be the equivalent of running tsc with something like --build --watch --preserveWatchOutput

@zackbrown
Copy link
Member

We've discussed a --watch option as an alternative to hot mode, and I believe @roperzh made some progress on this, but I don't believe we have a working version. It would be awesome if you want to knock this out, @phil-lgr . Perhaps you and Rob can do a quick sync over a call or on the Diez Slack?

@phil-lgr
Copy link
Author

@roperzh I'd be happy to assist on that, I'll DM you on Slack

@roperzh
Copy link
Member

roperzh commented Jul 17, 2020

Pasting a few bits of what we discussed on Slack for the sake of overcommunication:

I believe a quick tour of how things work under the hood might help (apologies if you already know all of this)
In the grand scheme of things, the compiler does four big steps:

  • It compiles the source TypeScript code to JavaScript:
    private async compile () {
  • Requires the compiled design system:
    try {
    componentModule = await loadComponentModule(this.parser.emitRoot);
    } catch (error) {
    await showStackTracesFromRuntimeError(error);
    process.exit(1);
    }
  • Using the TypeScript API and the runtime values from the compiled code it builds a tree of components:
    for (const componentName of this.parser.rootComponentNames) {
    // Fall back to the camel case variant of the component name. The parser capitalizes component names automatically.
    const {symbolName} = this.parser.getMetadataForTypeOrThrow(componentName);
    const maybeConstructor = componentModule[symbolName];
    if (!maybeConstructor) {
    Log.warning(`Unable to resolve component instance from ${this.parser.projectRoot}: ${componentName}.`);
    continue;
    }
    const componentInstance = isConstructible(maybeConstructor) ? new maybeConstructor() : maybeConstructor;
    await this.processComponentInstance(componentInstance, componentName);
    }
  • Using the tree of components, each target compiler can build source code for the target platform (for example the web compiler: https://github.com/diez/diez/blob/220f76cd06c265e82e6da3adfe04bd744923e9b3/src/compiler/targets/src/targets/web.compiler.ts)
    There's more to the equation, but that is a general idea!
    To make --watch work, we need to:
  • Trigger the TypeScript compiler. hot mode does this, we can borrow/merge some functionality:
    /**
    * Starts a TypeScript server in watch mode, similar to `tsc --watch` but with more control over when sources are emitted.
    */
    watch () {
    const host = createWatchCompilerHost(
    this.program.getRootFileNames() as string[],
    Object.assign(
    this.program.getCompilerOptions(),
    {
    // Write out to the expected directory.
    outDir: this.emitRoot,
    },
    ),
    sys,
    createSemanticDiagnosticsBuilderProgram,
    (diagnostic) => this.printDiagnostics(diagnostic),
    (diagnostic) => this.printDiagnostics(diagnostic),
    );
    // Skip watch status change notifications.
    host.onWatchStatusChange = () => {
    this.hotBuildStartTime = Date.now();
    };
    host.afterProgramCreate = (watchProgram) => {
    this.program = watchProgram.getProgram();
    const changedFiles = watchProgram.getState().changedFilesSet;
    if (changedFiles) {
    for (const file of changedFiles.keys()) {
    const sourceFile = this.project.getSourceFile(file);
    if (sourceFile) {
    sourceFile.refreshFromFileSystemSync();
    }
    }
    }
    this.run(false);
    };
  • Trigger the target compiler

There's a possibility of leveraging some of the work done for hot mode, but copy + pasting some code and writing a new functionality would be OK since hot has its idiosyncrasy and it's a complicated beast.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants