Closed rluba closed 6 years ago
This is inaccurate.
The bail out of ModuleConcatenationPlugin is by design for modules meant to be loaded by aurelia-loader
, i.e. those found by PLATFORM.moduleName
and friends. It's on purpose because otherwise Aurelia won't work.
Hoisting is possible for all other modules.
@jods4 You might be right, but I wouldn’t know how. Can you show me any example of Aurelia where using ModuleConcatenationPlugin
results in an even marginally smaller bundle?
I can see that ModuleConcatenationPlugin
bails out of every single file in my Aurelia application because every module can be traced down to the bootstrapping in main.js
:
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName('app')));
(…or another reference using PLATFORM.moduleName(…)
).
Since the root of the application requires using PLATFORM.moduleName(…)
, every single file that’s used within the application bails from optimization because its usage is (either directly or indirectly) traced back to an unsupported reference.
ModuleConcatenation bailout: Module is referenced from these modules with unsupported syntax: ./src/main.js (referenced with aurelia module)
It's on purpose because otherwise Aurelia won't work.
I know. But the question is: How could this be improved so that Aurelia is less toxic to optimization.
Do you use includeAll: "src"
or similar? It would do that.
Otherwise, regular ES imports are hoisted when it is possible and benefits the app.
If you need proof:
How could this be improved so that Aurelia is less toxic to optimization.
It is a fundamental change in the design of Aurelia. It means not using strings anymore, not relying on modules shapes, using import
exclusively...
@bigopon has done some work in this area recently to create alternative API that are more tooling friendly, but you need to change your code to take advantage of them.
Plans for the next major version of Aurelia are to fully go this way. It will take some time though, don't hold your breath.
Final note: it's not nearly as bad as you're making it to be. Don't expect properly minimized builds to suddenly get 20% smaller because Aurelia modules are hoisted.
The link you provided compares thousands of tiny modules. So yes if you just export trimLeft
the overhead of webpack is significant. When using more realists ViewModels it's not that big.
@jods4 Thank you for the reply.
No, I don’t use includeAll
. I manually import all dependencies and use PLATFORM.moduleName(…)
where needed.
But your screenshot helped me find my problem! I tried running Webpack with and without adding new webpack.optimize.ModuleConcatenationPlugin()
to the plugins – there was zero difference. But when I saw your screenshot, I remembered similar lines in my build. Some googling revealed that ModuleConcatenationPlugin
is enabled by default in production in Webpack 4! That’s why I saw no difference – manually adding new webpack.optimize.ModuleConcatenationPlugin()
is a no-op in production. Thank you.
@bigopon has done some work in this area recently to create alternative API that are more tooling friendly, but you need to change your code to take advantage of them.
That’s great to hear. I’m looking forward to it. @bigopon Let me know if I can be of help.
Don't expect properly minimized builds to suddenly get 20% smaller because Aurelia modules are hoisted.
I didn’t expect that. But we recently switched a (non-aurelia) project to Webpack and saw around 10% increase in minified bundle size – both non-gzipped and gzipped! So the overhead is large enough to be significant. (We couldn’t use ModuleConcatenationPlugin
for that project because it doesn't use ES6 modules.)
Out of curiosity, what were you bundling with before Webpack? 10% is significant and Webpack 4 builds -- for production -- are rather optimized.
I don't know what this project was made with, but you can use import
in otherwise lower targets (ES5) and bundle it with Webpack (which removes all imports). This gives you access to many import optimizations (beyond hoisting) while still targeting old browsers.
For example with Typescript this is easy to do as the target language and module system are two distinct options.
It was an ES5 project using AngularJS and a custom build process. Before we switched to Webpack it mostly relied on AngularJS’s builtin module system so the files were simply concatenated (with some pre-processing and template compilation) and then optimized.
I know that it’s possible to use import
but it was a rather large codebase of many small files that we just retrofitted with Webpack to get rid of Bower. Rewriting everything to fit ES6 modules was not an option. Since there’s nothing for Webpack to optimize (apart from what the old build system already did, too), we were just left with Webpack’s overhead.
@rluba Will do 👍
I'm submitting a feature request
Please tell us about your environment:
Operating System: OSX 10.13.6
Node Version: 8.11.4
NPM Version: 6.4.0
JSPM OR Webpack AND Version webpack 4.8.3
Browser: all
Language: ESNext
Current behavior:
Using Webpack adds a huge overhead both in terms of bundle size and startup size to every application. Webpack 3 and 4 introduced ModuleConcatenationPlugin to mitigate most of this overhead.
But trying to use
ModuleConcatenationPlugin
with Aurelia has no effect because Aurelia’s way of bootstrapping the app and loading its dependencies causesModuleConcatenationPlugin
to bail out for every single file. (See Debugging Optimization Bailouts on how to see the bailout reasons for each file.)Expected/desired behavior:
It would be great if Aurelia would retain at least some support for using
ModuleConcatenationPlugin
, especially since it encourages having lots of small modules – which magnifies the overhead created by Webpack.I haven’t investigated Aurelias internal bootstrapping mechanisms enough to know how to achieve this, but I’d be willing to offer my help.