Replies: 2 comments 1 reply
-
Implementation PR: #11117 |
Beta Was this translation helpful? Give feedback.
0 replies
-
Hi, just wondering — would this kind of change still cause a rebuild of all files in util.ts // util.ts
export * from './date'
export * from './number'
export * from './price' // re-export.ts
export * from './util' // main.ts
import { foo } from 're-export' |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
Lazily build reexports in side-effect-free barrel files to minimize performance overhead from excessive module inclusion, avoiding unnecessary resolve and build processes for these modules.
Motivation
Optimize Rspack's build performance when processing barrel files, with the main benefits seen in project scenarios that import libraries, improving Rspack's overall build performance.
Prior Arts
Glossary
barrel file: a file that imports modules from other files and exports the said modules
User Guide
experiments.lazyBarrel
during experimental phase.factory_meta.side_effects_free
("sideEffects": false
in package.json or configured bymodule.rule.sideEffects
) and thus requires sideEffects configuration.Detailed Design
forwarded_ids
and passed to the barrel file module.factory_meta.side_effects_free
is true, all re-export dependencies will be marked as lazy.forwarded_ids
passed in. The used re-export dependencies will have their lazy mark removed and be added to the process dependencies queue for building, while unused re-export dependencies will remain lazy and won't be built (no resolve, no build, and no loaders...).mgm.all_dependencies
. The data storage remains completely identical - the only difference being some dependencies are marked as lazy.ProcessUnlazyDependenciesTask
.artifact
to ensure correctness during incremental builds and hot builds with persistent cache enabled.forwarded_ids
. Those that matched will be considered as used, have their lazy mark removed, and be added to the process dependencies queue for building.forwarded_ids
will first attempt to match against known named exports (export { x as A } from "./a";
,export * as A from "./a"
,export { a, b }
,export const A
,export default A
). When no match is found, it indicates the specifier comes from star reexports (export * from "./a"), at which point the remaining star reexports will have their lazy marks removed and be added to the process dependencies queue for building.forwarded_ids
downstream for subsequent barrel files to use.export { x as A } from "./a"
will passforwarded_ids: x
downstream, and the subsequent barrel file will only build the re-export of x while keeping other re-export dependencies lazy.export * from "./a"
andexport * as A from "./a"
will passforwarded_ids: *
downstream, requiring the subsequent barrel file to build all re-export dependencies.Drawbacks
FAQ
Can this also supports CommonJS?
Yes, theoretically this can also support CommonJS, but before that we need to improve Rspack's CJS tree shaking first, the static analyze part specifically, so currently we will only support ESM, and support CJS in the future PR.
Why depend on
"sideEffects": false
in package.json, can Rspack automatically analyze a module is side effects free or not?Rspack has the ability to analyze a module is side effects free or not of course, it's already used by
optimization.sideEffects
to tree shaking side effects free modules. But these analyzed modules still require checking whether their dependencies have side effects - only when all dependencies are also side effects free can the module be considered truly side effects free. However, during the make phase, dependencies must first be built before their side effects can be analyzed, and thelazyBarrel
is intend to avoid to build those dependencies."sideEffects": false
in package.json ormodule.rule.sideEffects
doesn't require dependency checking, as it signifies the entire package is side effects free. Therefore,lazyBarrel
can only rely on this marker rather than automatic analysis.So
export * from "./x"
is not a problem any more?No,
export * from "./x"
is still a bad practice for your build performance,lazyBarrel
won't build the star re-export only when you import a specifier, and the side effects free barrel file's named exports contains the specifier (export { x as A } from "./a";
,export * as A from "./a"
,export { a, b }
,export const A
,export default A (the name is default)
), which means the star re-export is not used. So Rspack will still build the star re-export if:Beta Was this translation helpful? Give feedback.
All reactions