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

New babel config #2016

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft

New babel config #2016

wants to merge 7 commits into from

Conversation

BlueCutOfficial
Copy link
Collaborator

@BlueCutOfficial BlueCutOfficial commented Jul 4, 2024

Fixes #1962

TODO:

  • If addons bring more than plugins (e.g. presets), use error messages to say it's not going to work.
  • Using test templates, check if we can remove the dependency on ember-cli-babel and write a dedicated test that still relies on it.
  • Make sure we can use some exclude option with the new config that can achieve what skipBabel does.
  • Merging app and legacy config: do we want to put effort in this case and let the app win? If so, how to identify the same plugin is defined on both side? (legacy json uses full path, so we would need to resolve app plugins to compare the paths?)
  • Maybe rename babel.ts to load-babel-config.ts to be more explicit it's config loading and not some Babel plugin
  • Check we can move loadPluginDebugMacros right after loadLegacyPlugins to simplify
  • Create new issues to track the work to do on the upgrade guide

@BlueCutOfficial BlueCutOfficial force-pushed the new-babel-config branch 2 times, most recently from 9d7c1ef to 9ad7cc8 Compare July 4, 2024 12:59
@BlueCutOfficial
Copy link
Collaborator Author

BlueCutOfficial commented Jul 11, 2024

@ef4, @mansona,

About modifying this block 👉 https://github.com/embroider-build/embroider/blob/main/packages/compat/src/compat-app.ts#L244C1-L255C1 to help developers get how to update their app. I need some rough idea.

I understand the value of identifying app's options and addon's options to output good messages, for instance:

  • if a preset if from an addon: "addons' presets no longer working",
  • if an option is from app: "move the app's options to babel.config.cjs"...

But I don't think I can know that using only legacyAppInstance.options.babel. This field comes from ember-cli, which concat app's options and addon's options, so it's already an as-is parameter when we enter Embroider default pipeline. The only way I see to find what options come from where is to loop through addons, but if it's indeed the right thing to do, I wonder what would be the best place. Can I take advantage somehow of an existing loop, and create new information for legacyAppInstance to use?

Is the above worth it or should I try to go with slightly more generic messages?


EDIT: discussed with Chris, we will go with the generic message.

@BlueCutOfficial BlueCutOfficial force-pushed the new-babel-config branch 3 times, most recently from df00ceb to 5956d5d Compare July 12, 2024 07:27
@BlueCutOfficial BlueCutOfficial self-assigned this Jul 19, 2024
…abel plugins for classic addons, import it in the babel.config.cjs of the app-template to merge explicit and classic plugins
…abel config from generated config to the app config
…ate counterpart and install them in app-template deps
…lates, use an empty config for classic templates
Copy link
Contributor

@ef4 ef4 left a comment

Choose a reason for hiding this comment

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

The only state that we need to capture during the prebuild is the plugins that were inserted by v1 addons. Most of our own plugins don't need to be in that legacy plugins list. They can be provided as directly importable utilities in the babel config.

Here is where we add many plugins:

// Our stage3 code is always allowed to use dynamic import. We may emit it
// ourself when splitting routes.
babel.plugins.push(require.resolve('@babel/plugin-syntax-dynamic-import'));
// https://github.com/webpack/webpack/issues/12154
babel.plugins.push(require.resolve('./rename-require-plugin'));
babel.plugins.push([
require.resolve('babel-plugin-ember-template-compilation'),
await this.etcOptions(resolverConfig),
]);
// this is @embroider/macros configured for full stage3 resolution
babel.plugins.push(...this.compatApp.macrosConfig.babelPluginConfig());
let colocationOptions: TemplateColocationPluginOptions = {
appRoot: this.origAppPackage.root,
// This extra weirdness is a compromise in favor of build performance.
//
// 1. When auto-upgrading an addon from v1 to v2, we definitely want to
// run any custom AST transforms in stage1.
//
// 2. In general case, AST transforms are allowed to manipulate Javascript
// scope. This means that running transforms -- even when we're doing
// source-to-source compilation that emits handlebars and not wire
// format -- implies changing .hbs files into .js files.
//
// 3. So stage1 may need to rewrite .hbs to .hbs.js (to avoid colliding
// with an existing co-located .js file).
//
// 4. But stage1 doesn't necessarily want to run babel over the
// corresponding JS file. Most of the time, that's just an
// unnecessarily expensive second parse. (We only run it in stage1 to
// eliminate an addon's custom babel plugins, and many addons don't
// have any.)
//
// 5. Therefore, the work of template-colocation gets defered until here,
// and it may see co-located templates named `.hbs.js` instead of the
// usual `.hbs.
templateExtensions: ['.hbs', '.hbs.js'],
// All of the above only applies to auto-upgraded packages that were
// authored in v1. V2 packages don't get any of this complexity, they're
// supposed to take care of colocating their own templates explicitly.
packageGuard: true,
};
babel.plugins.push([templateColocationPluginPath, colocationOptions]);
babel.plugins.push([
require.resolve('./babel-plugin-adjust-imports'),
(() => {
let pluginConfig: AdjustImportsOptions = {
appRoot: resolverConfig.appRoot,
};
return pluginConfig;
})(),
]);
// we can use globally shared babel runtime by default
babel.plugins.push([
require.resolve('@babel/plugin-transform-runtime'),
{ absoluteRuntime: __dirname, useESModules: true, regenerator: false },
]);

  • syntax-dynamic-import may not be needed at all, I would be surprised if it's not enabled by default in new-enough babel. If it is needed, it can go directly in the user's config.
  • rename-require-plugin is only needed by webpack, so it can be dropped entirely here
  • babel-plugin-ember-template-compilation is important for users to be able to control in their own babel config. We will need to work on cleanly generating its options. For now, we could provide an importable utilities that builds the options for you.
  • Macros is similar, users should be able to see it in their config, but right now it has a not-user-friendly API, so it could be an importable utility that wraps over that for now.
  • template colocation could go directly into the users's config.
  • babel-pluign-adjust-imports is a v1-addon rule-system-supporting plugin. I think we should consider renaming loadLegacyPlugins() to v1AddonSupport() and then it mean both the v1-addon-inserted plugins plus any of our own hacks like babel-plugin-adjust-imports that exist purely to support v1 addons. That way users either add or remove all v1 addon support, without needing to study a lot of details.

}

module.exports = config;
module.exports = {};
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this file can just be deleted.

Comment on lines +58 to +69
function _warnIfNoLegacyPlugins(legacyPlugins: any) {
if (!legacyPlugins || !legacyPlugins.length) {
console.warn(`
Your Ember app doesn't use any classic addon that requires Babel plugins.
In your babel.config.cjs, you can safely remove the usage of loadLegacyPlugins.

Remove:
- const { loadLegacyPlugins } = require('@embroider/compat');
- ...loadLegacyPlugins(),

If you install a classic addon in your app afterward, make sure to add any Babel config it may require to babel.config.cjs.
`);
Copy link
Contributor

Choose a reason for hiding this comment

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

I worry that this is premature. Long after someone has seen this message and removed the legacy plugin support, someone on their team could add an addon that needs it and be puzzled why the addon doesn't work.

@mansona just suggested to me that perhaps it would be better to wait to tell people to remove the legacy plugin support until we can do a deprecation against any v1 addon trying to add babel plugins, and that sounds reasonable.

@@ -225,21 +225,8 @@ export default class CompatApp {

@Memoize()
babelConfig(): TransformOptions {
Copy link
Contributor

Choose a reason for hiding this comment

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

This whole method can change name and return type because its only remaining responsibility is to capture the plugins added by v1 addons. It could become captureLegacyBabelPlugins(): { plugins: PluginItem[] }

@@ -581,6 +581,9 @@ export class CompatAppBuilder {
`module.exports = ${JSON.stringify(pconfig.config, null, 2)}`,
'utf8'
);
outputJSONSync(join(locateEmbroiderWorkingDir(this.compatApp.root), '_babel_config_.json'), pconfig.config, {
spaces: 2,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

This is adding a new output location without removing the previous one on the lines above?

Also, similar to my comment in combat-app.ts, this value we're creating no longer needs to be a whole babel config. It's just a file that exports a plugins array (and eventually it will probably also export an AST transforms array, but that is a separate topic.).

Comment on lines +36 to +39
"@babel/plugin-proposal-decorators": "^7.22.5",
"@babel/plugin-transform-class-properties": "7.24.7",
"@babel/plugin-transform-private-methods": "7.24.7",
"@babel/plugin-transform-private-property-in-object": "^7.24.7",
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a non-blocking comment, but it's probably safe for us to replace all four of these with https://github.com/ef4/decorator-transforms instead. It could be a separate PR.

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.

implement the "correct solution" for babel config in vite
2 participants