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

Supporting more build environments #748

Merged
merged 28 commits into from
Mar 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
66b93cd
[experimental] an eager mode for importSync
ef4 Feb 21, 2021
ad28a2f
Merge remote-tracking branch 'origin/master' into importSync-eager-mode
ef4 Mar 6, 2021
be25c44
[wip]
ef4 Mar 7, 2021
29453de
[wip]
ef4 Mar 8, 2021
0b3a259
Merge remote-tracking branch 'origin/master' into the-platform
ef4 Mar 8, 2021
37494e2
refactoring template compiler to separate out node-isms
ef4 Mar 8, 2021
36c73e2
more template-compiler refactorings
ef4 Mar 8, 2021
84b4b98
split template compiler into node and common
ef4 Mar 8, 2021
2c0883f
improved template loading
ef4 Mar 9, 2021
bcc3cec
Merge remote-tracking branch 'origin/master' into the-platform
ef4 Mar 9, 2021
05ab33c
not needed in eager mode
ef4 Mar 9, 2021
56db384
make app-js and fastboot-js explicitly list their files
ef4 Mar 9, 2021
ee622da
make whole packagejson more extensible
ef4 Mar 9, 2021
547fb75
fixup
ef4 Mar 10, 2021
71e45cc
cleaning up imports
ef4 Mar 10, 2021
f15cdf2
splitting out browser-safe parts of inilne-hbs plugin
ef4 Mar 10, 2021
d889a36
more file extensions
ef4 Mar 13, 2021
1619275
Merge branch 'master' into the-platform
ef4 Mar 28, 2021
ca63cef
finishing merge
ef4 Mar 28, 2021
a7fc231
keep babel out of the core template compiler
ef4 Mar 28, 2021
fb101aa
don't force eager mode always
ef4 Mar 28, 2021
03cc3c6
post-merge formatting
ef4 Mar 28, 2021
b3bdd70
updating some tests to account for more explicit file extensions
ef4 Mar 28, 2021
5b9c466
use Package's packageJSON
ef4 Mar 28, 2021
ad49d5d
better error for broken app-js entries
ef4 Mar 28, 2021
d72faaf
update compat adapter to also update new app-js
ef4 Mar 28, 2021
e6b5861
updating tests and making implicitModulesStrategy configurable
ef4 Mar 28, 2021
22910a3
updating tests to match new plugin module name
ef4 Mar 28, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"request": "launch",
"name": "Run tests",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"cwd": "${workspaceFolder}/packages/core",
"args": ["--runInBand", "--testPathPattern", "tests/import-adder.test.js"],
"cwd": "${workspaceFolder}/packages/compat",
"args": ["--runInBand", "--testPathPattern", "tests/stage2 .test.js"],
"outputCapture": "std"
},
{
Expand Down
2 changes: 1 addition & 1 deletion packages/compat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"semver": "^7.3.2",
"symlink-or-copy": "^1.2.0",
"tree-sync": "^2.0.0",
"typescript-memoize": "^1.0.0-alpha.3",
"typescript-memoize": "^1.0.0",
"walk-sync": "^1.1.3",
"yargs": "^16.1.0"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/compat/src/compat-adapters/@ember-data/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default class EmberDataModel extends V1Addon {
if (!meta['implicit-modules']) {
meta['implicit-modules'] = [];
}
meta['implicit-modules'].push('./-private');
meta['implicit-modules'].push('./-private.js');
return meta;
}
}
12 changes: 11 additions & 1 deletion packages/compat/src/compat-adapters/ember-asset-loader.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import V1Addon from '../v1-addon';
import Funnel from 'broccoli-funnel';
import cloneDeep from 'lodash/cloneDeep';

// ember-asset-loader's ManifestGenerator (which is used as the Addon base class
// for by ember-engines) has an "all" postprocessTree hook. We can't / won't run
Expand All @@ -14,7 +15,16 @@ import Funnel from 'broccoli-funnel';
export default class extends V1Addon {
get v2Tree() {
return new Funnel(super.v2Tree, {
exclude: ['_app/config/asset-manifest.js', '_app_/instance-initializers/load-asset-manifest.js'],
exclude: ['_app_/config/asset-manifest.js', '_app_/instance-initializers/load-asset-manifest.js'],
});
}
get packageMeta() {
let meta = super.packageMeta;
if (meta['app-js']) {
meta = cloneDeep(meta);
delete meta['app-js']!['./instance-initializers/load-asset-manifest.js'];
delete meta['app-js']!['./config/asset-manifest.js'];
}
return meta;
}
}
16 changes: 16 additions & 0 deletions packages/compat/src/compat-adapters/ember-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ import semver from 'semver';
export default class extends V1Addon {
private useRealModules = semver.satisfies(this.packageJSON.version, '>=3.27.0', { includePrerelease: true });

get newPackageJSON() {
let extra = {
'./dist/ember-template-compiler': './dist/ember-template-compiler.js',
};
let pkg = JSON.parse(JSON.stringify(super.newPackageJSON));
if (!pkg.exports) {
pkg.exports = extra;
} else {
Object.assign(pkg.exports, extra);
}
return pkg;
}
get v2Tree() {
return mergeTrees([super.v2Tree, new Funnel(this.rootTree, { include: ['dist/ember-template-compiler.js'] })]);
}

// when using real modules, we're replacing treeForAddon and treeForVendor
customizes(treeName: string) {
return (
Expand Down
4 changes: 2 additions & 2 deletions packages/compat/src/compat-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
Package,
TemplateCompilerPlugins,
Resolver,
TemplateCompiler,
NodeTemplateCompiler,
AddonPackage,
} from '@embroider/core';
import V1InstanceCache from './v1-instance-cache';
Expand Down Expand Up @@ -398,7 +398,7 @@ class CompatAppAdapter implements AppAdapter<TreeNames> {
// It's ok that this isn't a fully configured template compiler. We're only
// using it to parse component snippets out of rules.
resolver.astTransformer(
new TemplateCompiler({
new NodeTemplateCompiler({
compilerPath: resolveSync(this.templateCompilerPath(), { basedir: this.root }),
EmberENV: {},
plugins: {},
Expand Down
26 changes: 2 additions & 24 deletions packages/compat/src/rewrite-package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,15 @@ import Plugin from 'broccoli-plugin';
import { Node } from 'broccoli-node-api';
import { writeFileSync } from 'fs';
import { join } from 'path';
import { AddonMeta } from '@embroider/core';

type GetMeta = () => Partial<AddonMeta>;

export default class RewritePackageJSON extends Plugin {
constructor(inputTree: Node, private getMeta: GetMeta, private originalPackageJSON: any) {
constructor(inputTree: Node, private getPackageJSON: () => any) {
super([inputTree], {
annotation: 'embroider:core:rewrite-package-json',
});
}

build() {
let pkg = this.originalPackageJSON;
let meta: AddonMeta = Object.assign(
{},
pkg.meta,
{
version: 2,
'auto-upgraded': true,
type: 'addon',
} as AddonMeta,
this.getMeta()
);
pkg['ember-addon'] = meta;

// classic addons don't get to customize their entrypoints like this. We
// always rewrite them so their entrypoint is index.js, so whatever was here
// is just misleading to stage3 packagers that might look (rollup does).
delete pkg.main;
delete pkg.module;

writeFileSync(join(this.outputPath, 'package.json'), JSON.stringify(pkg, null, 2), 'utf8');
writeFileSync(join(this.outputPath, 'package.json'), JSON.stringify(this.getPackageJSON(), null, 2), 'utf8');
}
}
31 changes: 31 additions & 0 deletions packages/compat/src/template-compiler-broccoli-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Node } from 'broccoli-node-api';
import Filter from 'broccoli-persistent-filter';
import type { TemplateCompiler } from '@embroider/core';
import { join } from 'path';

export default class TemplateCompileTree extends Filter {
constructor(inputTree: Node, private templateCompiler: TemplateCompiler, private stage: 1 | 3) {
super(inputTree, {
name: `embroider-template-compile-stage${stage}`,
persist: true,
extensions: ['hbs', 'handlebars'],
// in stage3 we are changing the file extensions from hbs to js. In
// stage1, we are just keeping hbs.
targetExtension: stage === 3 ? 'js' : undefined,
});
}

processString(source: string, relativePath: string) {
if (this.stage === 1) {
return this.templateCompiler.applyTransforms(relativePath, source);
} else {
return this.templateCompiler.compile(relativePath, source);
}
}
cacheKeyProcessString(source: string, relativePath: string) {
return `${this.stage}-${this.templateCompiler.cacheKey}` + super.cacheKeyProcessString(source, relativePath);
}
baseDir() {
return join(__dirname, '..');
}
}
72 changes: 49 additions & 23 deletions packages/compat/src/v1-addon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import mergeTrees from 'broccoli-merge-trees';
import semver from 'semver';
import rewriteAddonTree from './rewrite-addon-tree';
import { mergeWithAppend } from './merges';
import { AddonMeta, TemplateCompiler, debug, PackageCache, Resolver, extensionsPattern } from '@embroider/core';
import { AddonMeta, NodeTemplateCompiler, debug, PackageCache, Resolver, extensionsPattern } from '@embroider/core';
import Options from './options';
import walkSync from 'walk-sync';
import ObserveTree from './observe-tree';
Expand All @@ -24,6 +24,7 @@ import writeFile from 'broccoli-file-creator';
import SynthesizeTemplateOnlyComponents from './synthesize-template-only-components';
import { isEmberAutoImportDynamic, isCompactReexports, isColocationPlugin } from './detect-babel-plugins';
import { ResolvedDep } from '@embroider/core/src/resolver';
import TemplateCompilerBroccoliPlugin from './template-compiler-broccoli-plugin';

const stockTreeNames = Object.freeze([
'addon',
Expand Down Expand Up @@ -83,7 +84,7 @@ class V1AddonCompatResolver implements Resolver {
params,
};
}
astTransformer(_templateCompiler: TemplateCompiler): unknown {
astTransformer(_templateCompiler: NodeTemplateCompiler): unknown {
return;
}
dependenciesOf(_moduleName: string): ResolvedDep[] {
Expand Down Expand Up @@ -122,15 +123,15 @@ export default class V1Addon {

// this is only defined when there are custom AST transforms that need it
@Memoize()
private get templateCompiler(): TemplateCompiler | undefined {
private get templateCompiler(): NodeTemplateCompiler | undefined {
let htmlbars = this.addonInstance.addons.find((a: any) => a.name === 'ember-cli-htmlbars');
if (htmlbars) {
let options = htmlbars.htmlbarsOptions() as HTMLBarsOptions;
if (options.plugins && options.plugins.ast) {
// our macros don't run here in stage1
options.plugins.ast = options.plugins.ast.filter((p: any) => !isEmbroiderMacrosPlugin(p));
if (options.plugins.ast.length > 0) {
return new TemplateCompiler({
return new NodeTemplateCompiler({
compilerPath: options.templateCompilerPath,
EmberENV: {},
plugins: options.plugins,
Expand Down Expand Up @@ -169,7 +170,7 @@ export default class V1Addon {
_addon: this,
toTree(this: { _addon: V1Addon }, tree: Node): Node {
if (this._addon.templateCompiler) {
return this._addon.templateCompiler.applyTransformsToTree(tree);
return new TemplateCompilerBroccoliPlugin(tree, this._addon.templateCompiler, 1);
} else {
// when there are no custom AST transforms, we don't need to do
// anything at all.
Expand Down Expand Up @@ -268,8 +269,27 @@ export default class V1Addon {
return this.packageJSON.name;
}

// you can override this to change the *input* packageJSON that the rest of
// stage1 will see. If you want to see and change the *output* packageJSON see
// `newPackageJSON`.
protected get packageJSON() {
return this.addonInstance.pkg;
return this.packageCache.get(this.root).packageJSON;
}

protected get newPackageJSON() {
// shallow copy only! This is OK as long as we're only changing top-level
// keys in this method
let pkg = Object.assign({}, this.packageJSON);
let meta: AddonMeta = Object.assign({}, pkg.meta, this.packageMeta);
pkg['ember-addon'] = meta;

// classic addons don't get to customize their entrypoints like this. We
// always rewrite them so their entrypoint is index.js, so whatever was here
// is just misleading to stage3 packagers that might look (rollup does).
delete pkg.main;
delete pkg.module;

return pkg;
}

@Memoize()
Expand Down Expand Up @@ -513,7 +533,15 @@ export default class V1Addon {
// things to the package metadata.
protected get packageMeta(): Partial<AddonMeta> {
let built = this.build();
return mergeWithAppend(built.staticMeta, ...built.dynamicMeta.map(d => d()));
return mergeWithAppend(
{
version: 2,
'auto-upgraded': true,
type: 'addon',
},
built.staticMeta,
...built.dynamicMeta.map(d => d())
);
}

@Memoize()
Expand Down Expand Up @@ -758,20 +786,23 @@ export default class V1Addon {
}

private maybeSetDirectoryMeta(built: IntermediateBuild, tree: Node, localDir: string, key: keyof AddonMeta): Node {
// unforunately Funnel doesn't create destDir if its input exists but is
// empty. And we want to only put the app-js key in package.json if
// there's really a directory for it to point to. So we need to monitor
// the output and use dynamicMeta.
let dirExists = false;
let files: AddonMeta['app-js'];
built.dynamicMeta.push(() => {
if (dirExists) {
return { [key]: localDir };
if (files) {
return { [key]: files };
} else {
return {};
}
});
return new ObserveTree(tree, (outputPath: string) => {
dirExists = pathExistsSync(join(outputPath, localDir));
let dir = join(outputPath, localDir);
if (existsSync(dir)) {
files = Object.fromEntries(
walkSync(dir, { globs: ['**/*.js', '**/*.hbs'] }).map(f => [`./${f}`, `./${localDir}/${f}`])
);
} else {
files = undefined;
}
});
}

Expand Down Expand Up @@ -877,7 +908,7 @@ export default class V1Addon {
publicAssets = {};
for (let filename of walkSync(join(outputPath, 'public'))) {
if (!filename.endsWith('/')) {
publicAssets[`public/${filename}`] = filename;
publicAssets[`./public/${filename}`] = './' + filename;
}
}
});
Expand Down Expand Up @@ -938,12 +969,7 @@ export default class V1Addon {
}

private buildPackageJSON(built: IntermediateBuild) {
let packageJSONRewriter = new RewritePackageJSON(
this.rootTree,
() => this.packageMeta,
this.packageCache.get(this.root).packageJSON
);
built.trees.push(packageJSONRewriter);
built.trees.push(new RewritePackageJSON(this.rootTree, () => this.newPackageJSON));
}

@Memoize()
Expand Down Expand Up @@ -1000,7 +1026,7 @@ function babelPluginAllowedInStage1(plugin: PluginItem) {
return false;
}

if (TemplateCompiler.isInlinePrecompilePlugin(plugin)) {
if (NodeTemplateCompiler.isInlinePrecompilePlugin(plugin)) {
// Similarly, the inline precompile plugin must not run in stage1. We
// want all templates uncompiled. Instead, we will be adding our own
// plugin that only runs custom AST transforms inside inline
Expand Down
2 changes: 1 addition & 1 deletion packages/compat/tests/namespaced-app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ describe('namespaced app', function () {
'implicit-modules have correct paths'
);
assertFile.matches(
/d\(["']@ef4\/namespaced-app\/app['"], function\(\)\{ return i\(['"]\.\.\/\.\.\/app"\);\}\);/,
/d\(["']@ef4\/namespaced-app\/app['"], function\(\)\{ return i\(['"]\.\.\/\.\.\/app\.js"\);\}\);/,
`app's own modules are correct`
);
});
Expand Down
9 changes: 2 additions & 7 deletions packages/compat/tests/resolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { join, dirname } from 'path';
import Options, { optionsWithDefaults } from '../src/options';
import sortBy from 'lodash/sortBy';
import { tmpdir } from 'os';
import { TemplateCompiler, throwOnWarnings } from '@embroider/core';
import { NodeTemplateCompiler, throwOnWarnings } from '@embroider/core';
import { emberTemplateCompilerPath } from '@embroider/test-support';
import { Options as AdjustImportsOptions } from '@embroider/core/src/babel-plugin-adjust-imports';
import Resolver from '../src/resolver';
Expand Down Expand Up @@ -45,12 +45,7 @@ describe('compat-resolver', function () {
otherOptions.adjustImportsImports
),
});
let compiler = new TemplateCompiler({
compilerPath,
resolver,
EmberENV,
plugins,
});
let compiler = new NodeTemplateCompiler({ compilerPath, resolver, EmberENV, plugins });
return function (relativePath: string, contents: string) {
let moduleName = givenFile(relativePath);
let { dependencies } = compiler.precompile(moduleName, contents);
Expand Down
4 changes: 2 additions & 2 deletions packages/compat/tests/route-split.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe('splitAtRoutes', function () {
});

it('dynamically imports the route entrypoint from the main entrypoint', function () {
expectFile('./assets/my-app.js').matches('import("./_route_/people")');
expectFile('./assets/my-app.js').matches('import("./_route_/people.js")');
});

it('has split controllers in route entrypoint', function () {
Expand Down Expand Up @@ -292,7 +292,7 @@ describe('splitAtRoutes', function () {
});

it('dynamically imports the route entrypoint from the main entrypoint', function () {
expectFile('./assets/my-app.js').matches('import("./_route_/people")');
expectFile('./assets/my-app.js').matches('import("./_route_/people.js")');
});

it('has split controllers in route entrypoint', function () {
Expand Down
2 changes: 1 addition & 1 deletion packages/compat/tests/stage1.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ describe('stage1 build', function () {

test('addon metadata', function () {
let assertMeta = expectFile('node_modules/my-addon/package.json').json('ember-addon');
assertMeta.get('app-js').equals('_app_'); // should have app-js metadata
assertMeta.get('app-js').deepEquals({ './components/hello-world.js': './_app_/components/hello-world.js' }); // should have app-js metadata
assertMeta
.get('implicit-modules')
.includes('./components/hello-world', 'staticAddonTrees is off so we should include the component implicitly');
Expand Down
Loading