Skip to content

add delayed transpilation#7501

Merged
kellyselden merged 1 commit intoember-cli:masterfrom
kellyselden:delay-transpilation-3
Feb 25, 2018
Merged

add delayed transpilation#7501
kellyselden merged 1 commit intoember-cli:masterfrom
kellyselden:delay-transpilation-3

Conversation

@kellyselden
Copy link
Copy Markdown
Member

@kellyselden kellyselden commented Dec 13, 2017

I would like some feedback. Things to note:

  • we have to detect files that are already AMD because certain addons do their own transpilation.
  • we have to detect addons in legacy 'modules/' dir and undo to transpile correctly.
  • removed treeForAddon/compileModules warning, because it is now the desired behavior.
  • removed compileTemplates no template processor warning, because it is now the desired behavior.

Sample console output:

DEPRECATION: Addon "@html-next/vertical-collection" (found at "C:\Users\kelly\Desktop\my-app\node_modules\@html-next\vertical-collection") is manually placing files in the legacy "modules" folder. Support for this will be removed in a future version.
DEPRECATION: Addon "ember-data" (found at "C:\Users\kelly\Desktop\my-app\node_modules\ember-data") is manually placing files in the legacy "modules" folder. Support for this will be removed in a future version.

Left to do:

@kellyselden kellyselden force-pushed the delay-transpilation-3 branch 2 times, most recently from 6db915c to 283f446 Compare December 21, 2017 05:15
@rtablada
Copy link
Copy Markdown
Contributor

@kellyselden should the AMD Excluder be extracted into broccoli-funnel-amd-excluder? I'm not sure if that could potentially be helpful as a separate package rather than as part of Ember CLI?

Though I know that adds a maintenance cost too.

let source = fs.readFileSync(inputFilePath, 'utf8');

// ember-data and others compile their own source
if (source.indexOf('define(') === 0) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fine, but I'm not 100 about potential edgecases. It would likely not be compatible JS anyway so this should be good enough to figure out if something is AMD.

On the other hand, what if the module is exported for AMD but doesn't define immediately.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a lot of potential edge cases, but in reality we only have to worry about how babel formats the AMD code, which this should cover completely?

@kellyselden
Copy link
Copy Markdown
Member Author

@rtablada I am in favor of extracting it.

@rtablada
Copy link
Copy Markdown
Contributor

I'd like to see what documentation (if any) is needed for addon authors to make sure their addons work with this.

Bonus points for docs on how to utilize these changes in addons.

@kellyselden
Copy link
Copy Markdown
Member Author

@rtablada The only thing addons have to worry about is the first bullet point

addons no longer receive preprocessTree and postprocessTree hooks.

const Funnel = require('broccoli-funnel');
const walkSync = require('walk-sync');

class AmdExcluder extends Funnel {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you use https://github.com/broccolijs/broccoli-test-helper to write a few tests for this class?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a little bit of documentation on this class might also be nice. e.g. answering the question that @rtablada raised about this being specialized to detect AMD modules compiled by Babel (5? 6? 7?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added docs

let files = walkSync(inputPath, {
directories: false,
globs: [`**/*.js`],
});
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does build() have to be sync? otherwise it might make sense to read and process several files in parallel 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't have to be. Which package should I use for async walking?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess walkSync is okay, but the loop afterwards could possibly be concurrent

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to async readFile. Was this what you were thinking?


// ember-data and others compile their own source
if (source.indexOf('define(') === 0) {
this.exclude.push(file);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this fill up this.exclude with duplicate entries on rebuilds? we might have to reset this.exclude = []; at the beginning of build() 🤔

precompiledSource = preprocessJs(precompiledSource, '/', '/', {
annotation: `_compileAddonJs`,
registry: this.registry,
});
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if in terms of performance it would be better to teach preprocessJs() about the AMD exclusion rule 🤔 but then again that is something that can probably be refactored later...

@kellyselden kellyselden force-pushed the delay-transpilation-3 branch 7 times, most recently from 4f09907 to 529d6af Compare January 27, 2018 19:50
@kellyselden
Copy link
Copy Markdown
Member Author

wooo tests finally green.

@kellyselden kellyselden force-pushed the delay-transpilation-3 branch 2 times, most recently from 614ab47 to 4670071 Compare January 28, 2018 00:34
@kellyselden kellyselden force-pushed the delay-transpilation-3 branch 2 times, most recently from f7dc658 to d83a323 Compare January 28, 2018 01:30
@kellyselden kellyselden force-pushed the delay-transpilation-3 branch from d83a323 to 4132594 Compare January 28, 2018 04:31
Copy link
Copy Markdown
Contributor

@twokul twokul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed with @rwjblue (and @kellyselden / @twokul), this seems good with a couple of minor cleanup points...

`(NOT \`devDependencies\`) in \`${addon.name}\`'s \`package.json\`.`
);
});
// it('should throw a useful error if a template compiler is not present -- non-pods', function() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to be deleted

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted

`Please make sure your template precompiler (commonly \`ember-cli-htmlbars\`) is listed in \`dependencies\` ` +
`(NOT \`devDependencies\`) in \`${this.name}\`'s \`package.json\`.`);
}
// if (!registryHasPreprocessor(this.registry, 'template')) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to be deleted

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted

});

this._cachedAddonTree = new Funnel(combinedAddonTree, {
let compiledAddonTree = this._compileAddonTree(combinedAddonTree);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add some broccoli-debug trees for before and after? I'm mostly thinking this will be super useful for seeing where some transpilation issues might be coming from...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I emulated the style from the assembler. @twokul you may want to verify.

}

_compileAddonTemplates(tree) {
if (registryHasPreprocessor(this.registry, 'template')) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we actually get here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember why I added it. Without it we get errors in the styles tests https://travis-ci.org/ember-cli/ember-cli/jobs/337422087#L805-L813 missing template preprocessor. I will add more mocking to the styles tests.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

let inputFilePath = path.join(inputPath, file);
return fs.readFile(inputFilePath, 'utf8').then(source => {
if (source.indexOf('define(') === 0) {
this.exclude.push(file);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets add a warning here...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.exclude needs to be reset here (and we probably need to clear whatever funnel caches have been build up)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exclude is reset and it prints to console. the code has been moved to https://github.com/ember-cli/broccoli-amd-funnel. I also added tests.

}

_compileAddonJs(tree) {
let precompiledSource = new AmdExcluder(tree, {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets add a flag to opt-in or out of this tree as an option to new EmberApp, the default value should be true (e.g. use the amd excluder) but ultimately we should try to change it to false once a good number of popular addons have been updated...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// treeForAddon without calling super
// they need the original params preserved because they call
// babel themselves and expect compilation the old way
this.options[emberCLIBabelConfigKey] = Object.assign({}, original, {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This really should be moved back to the constructor if at all possible, setting it here means that others that depend on it earlier just don't have access to the values when they expect...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember why I placed it here instead of the constructor. Having it in the constructor means I need to handle the legacy /modules using broccoli-module-normalizer. Making that change now.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@kellyselden kellyselden force-pushed the delay-transpilation-3 branch 4 times, most recently from 5f3a5f6 to 3198d21 Compare February 5, 2018 00:28
@twokul
Copy link
Copy Markdown
Contributor

twokul commented Feb 18, 2018

so far, both @kellyselden and I, are seeing anywhere between 15-30% slowdown (depending on the application we run benchmarks against).

I ran tests against travis-web.

here's what a flame chart w/o delayed transpilation looks like:

screen shot 2018-02-17 at 4 20 42 pm

and here's a chart w/ delayed transpilation:

screen shot 2018-02-17 at 4 10 24 pm

Note, that we started running Babel twice (essentially unnecessary work). also, order in which we process add-ons have changed (from active-model-adapter, ember-cli-mirage, ember-data, ember-modal-dialog, ember-moment to ember-data, ember-cli-mirage, ember-moment). A thing to note is that some of the add-ons "disappeared" from flame graph and a wide gap on "unaccounted" work appeared. It's either ember-cli-inline-images or GC kicks in.

We can optimize and don't run Babel twice but there's a gap we're still seeing:

screen shot 2018-02-17 at 4 10 34 pm

@kellyselden kellyselden force-pushed the delay-transpilation-3 branch from 94063b2 to a2bb5e3 Compare February 18, 2018 05:05
@kellyselden kellyselden force-pushed the delay-transpilation-3 branch 4 times, most recently from 16af76f to 1113dc8 Compare February 21, 2018 18:38
@kellyselden kellyselden changed the title WIP: add delayed transpilation add delayed transpilation Feb 21, 2018
@kellyselden kellyselden force-pushed the delay-transpilation-3 branch 6 times, most recently from 0bee743 to 2da17aa Compare February 23, 2018 04:04
@kellyselden kellyselden force-pushed the delay-transpilation-3 branch 4 times, most recently from 2cd5918 to 7801f39 Compare February 25, 2018 02:07
@kellyselden kellyselden force-pushed the delay-transpilation-3 branch from 7801f39 to 0aec861 Compare February 25, 2018 02:14
@kellyselden
Copy link
Copy Markdown
Member Author

All this new code is guarded around the feature flag DELAYED_TRANSPILATION. Because of this, and because @rwjblue and @twokul have reviewed this multiple times with no remaining problems, I think it is safe to merge.

@kellyselden kellyselden merged commit 3a78ec3 into ember-cli:master Feb 25, 2018
@kellyselden kellyselden deleted the delay-transpilation-3 branch February 25, 2018 03:15
@rwjblue rwjblue mentioned this pull request Mar 1, 2018
7 tasks
@stefanpenner
Copy link
Copy Markdown
Contributor

I believe this PR is breaking things, specifically we seem to trying to transpile handlebars templates that exist <addon>/src/<somefolder>/templates/model.hbs

@rwjblue
Copy link
Copy Markdown
Member

rwjblue commented Apr 4, 2018

@stefanpenner - This should have been fixed by #7735, no?

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

Successfully merging this pull request may close these issues.

6 participants