-
Notifications
You must be signed in to change notification settings - Fork 37
feat: faster babel-loader by excluding node_module #644
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
base: master
Are you sure you want to change the base?
Conversation
The role of `babel-loader` is twofold: - Compile jsx (react) assets to js - Make js assets compatible with older browsers See the official documentation here: https://webpack.js.org/loaders/babel-loader/ It is widely recommended to exclude files in node_modules/ from that loader. See for instance: https://webpack.js.org/loaders/babel-loader/#babel-loader-is-slow Indeed, such files are assumed to be already compatible with older browsers, and built from jsx. However, the base configuration in frontend-build had the following `exclude` directive: exclude: /node_modules\/(?!@(open)?edx)/, Which means that only `@openedx` and `@edx` assets were excluded. With this change, we reduce the build time significantly for all MFEs. For instance: - frontend-app-profile: 86s -> 64s (-26%) - frontend-app-learning: 167s -> 110s (-34%) We observe a change in the fingerprint of app.js and app.css, but we don't consider these changes to be significant. The generated MFEs still worked when we tested them. If we realize later that some modules need to be compiled with babel, then we should explicitly include them with `and` directives, as documented here: https://webpack.js.org/loaders/babel-loader/#some-files-in-my-node_modules-are-not-transpiled-for-ie-11
Thanks for the pull request, @regisb! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. Where can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
This is ready for review. |
@@ -90,7 +90,7 @@ module.exports = merge(commonConfig, { | |||
// Babel is configured with the .babelrc file at the root of the project. | |||
{ | |||
test: /\.(js|jsx|ts|tsx)$/, | |||
exclude: /node_modules\/(?!@(open)?edx)/, | |||
exclude: /node_modules/, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which means that only
@openedx
and@edx
assets were excluded.
The current configuration here is excluding all node_modules
except assets scoped with @openedx
or @edx
using a negative lookup (?!
), which I believe is a bit different than what's described above and in the PR description.
Historically, the @openedx
and @edx
scoped packages were not transpiled on their own and we relied on @openedx/frontend-build
to do the transpilation of the @openedx
and @edx
scoped packages, but exclude all other node_modules
.
This change begins excluding all node_modules
, including the @openedx
and @edx
scoped packages.
For this change, we'd likely need to confirm that all @openedx
and @edx
scoped packages are already adequately transpiled upstream without relying on this negative lookup in the exclude
in the Webpack builds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oooooh my bad, I had definitely misread that regular expression. Still, the build time improvements are worth it, if the openedx/edx assets are correctly transpiled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
frontend-app-authoring definitely relies on installing un-transpiled plugins and assumes that frontend-build will transpile them because they're in the @openedx-plugins/*
namespace, or something like that. We could change this somewhow, but there may be other examples of this expectation. ref
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should transpile only jsx/tsx files from node_modules/@(open)?edx
, and not all js files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the rationale for only transpiling jsx/tsx files that only JSX syntax needs to be transpiled? I suppose I'd also think about other cases like newer JS syntax used in a project which might also require transpiling for older browsers, irrespective of JSX syntax itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the rationale for only transpiling jsx/tsx files that only JSX syntax needs to be transpiled?
Yes.
I suppose I'd also think about other cases like newer JS syntax used in a project which might also require transpiling for older browsers, irrespective of JSX syntax itself.
I don't know, I'm really just following recommendations that I'm seeing everywhere. My suggestion would be the opposite: to package openedx packages like everybody else does, without jsx/tsx/ts artifacts, and only with compiled assets. I don't see any reason why we should be doing things differently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suggestion would be the opposite: to package openedx packages like everybody else does, without jsx/tsx/ts artifacts, and only with compiled assets. I don't see any reason why we should be doing things differently.
Yeah, I totally agree this is the direction Open edX should strive for (i.e., relying on best practices as much as possible). We would just need to coordinate to be sure all @openedx
and @edx
scoped packages are adequately transpiled to our liking before we can change this behavior in frontend-build so it's not considered "breaking", if at all possible, and/or give adequate heads up to the community regarding the change if action is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I'm mistaken, the build will simply fail when we attempt to load jsx/tsx files without a transpiler, because of syntax errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suggestion would be the opposite: to package openedx packages like everybody else does, without jsx/tsx/ts artifacts, and only with compiled assets. I don't see any reason why we should be doing things differently.
There are some reasons to publish things that aren't transpiled:
(1) it means that the MFE decides what babel transforms are necessary, rather than the library. For example, our transpiled version of frontend-component-header
currently published on NPM has these babel compatibility shims in every .js file; the example below (in Header.js
) adds 1KB and is completely pointless. (This is due to a bad configuration within frontend-component-header
's babel config, but the point is that it should be the MFE's babel config that controls the presence of these shims, not the library.) Once these shims are in the library they'll always be in the MFE build; there's no way to exclude them later.
(2) it makes the process of publishing libraries much simpler. No babel, no webpack, no build process at all.
That said, in light of the performance concerns you're raising, I think it does still make sense to transpile things before publishing. I'm just pointing out that it's also considered acceptable not to do it, and sometimes preferred.
For what it's worth, my personal preference is to publish to JSR instead of NPM. Publishing there is way easier, as you just publish raw TypeScript/TSX files, and the registry automatically serves the transpiled version if your runtime (e.g. Node) requests it, or the raw source if your developer environment (e.g. VS Code) or runtime (e.g. Deno) supports it. It's also fully backwards compatible with NPM.
FTR frontend-app-ora-gradingis doing some funky rewrite of the exclude rule: https://github.com/openedx/frontend-app-ora-grading/blob/9348c4bb4c36937981d8b60e6ef72b36f8c65ac1/webpack.prod.config.js#L11
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #644 +/- ##
=============================
=============================
☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
The role of
babel-loader
is twofold:See the official documentation here: https://webpack.js.org/loaders/babel-loader/
It is widely recommended to exclude files in node_modules/ from that loader. See for instance: https://webpack.js.org/loaders/babel-loader/#babel-loader-is-slow Indeed, such files are assumed to be already compatible with older browsers, and built from jsx.
However, the base configuration in frontend-build had the following
exclude
directive:Which means that only
@openedx
and@edx
assets were excluded.With this change, we reduce the build time significantly for all MFEs. For instance:
We observe a change in the fingerprint of app.js and app.css, but we don't consider these changes to be significant. The generated MFEs still worked when we tested them. If we realize later that some modules need to be compiled with babel, then we should explicitly include them with
and
directives, as documented here: https://webpack.js.org/loaders/babel-loader/#some-files-in-my-node_modules-are-not-transpiled-for-ie-11