Hello. This actually is a story behind one of our nuxt based production applications, some workarounds was used to make ssr bundle smaller and much much more faster. All of them are implemented in nuxt-helpers/optimize.js and tested against nuxt 0.9.9.
About one week ago just after first deployment, i just figured out that SSR is really slow (~8req/sec with 1 worker) so the first thing i have checked was big ssr bundle size (~800kb), thanks to super useful nuxt extend
function, i have enabled BundleAnalyzerPlugin
for server side like this :
extend (config, {isServer}) {
if (isServer) config.plugins.push(new BundleAnalyzerPlugin({}));
}
The result was shucking
sass and css files where bundled They are really useless for server-side and just make things much slower. unfortunately without some hacks it is not possible to remove them from bundle. so i have used ignore-loader plugin to bypass vue loader :
['scss', 'css'].forEach(function (ext) {
config.module.rules[0].query.loaders[ext] = 'ignore-loader';
});
vendors are not externalized
We are just externalizing direct dependencies in package.json (like vue documentation example) but if we have indirect dependencies like nuxt-helpers they will be loaded into SSR bundle and have to parsed/loaded on each request! Simple workaround was adding nuxt.js vendors to externals too : config.externals = _.uniq(config.externals.concat(nuxt.build.vendor));
unnecessary babel presets
If you look in bundle analyzer result again, you will see big core-js
and regenerator
runtimes packaged with bundle. As a first attempt i just tried to externalize them like other vendors, but unfortunately this won't work and will throw run-time errors as they should be required by default. Worst than it babel is compiling many lines of code into older js syntax which makes code slower, many of them (including async/await
are now enabled in modern & stable node.js releases and are much much much faster than babel compiled code. I have used this workaround to reduce amount of presets and just compiling a modern SSR bundle :) It would be great if nuxt.js just has a built-in option to enable this optimization.
The result
Bundle size is now about 9x smaller (under 100kb), it is much faster because no vendors are included and are cached and much much faster because of using modern native async/awaits
. I can't exactly remind but SSR was handling ~150requests/sec with 4 workers using optimizated version. 😎
Extra 1 I was also tried new vue ssr bundle format with no luck (mentioned problems just exists and code splitting didn't helped a lot)
Extra 2
Also during last hack i have found a bug in nuxt extend
function! base.config.js is applying defaults to bable options on original object. so if some one changes anything shared in extend
for server, it will be applied to client options too! Although no one should do this it can be easily fixed and prevented by extending on a new object like this : defaults({}, this.options,...