Speedup volto razzle builds

I’ve been looking for a way to speedup Volto razzle/webpack builds, both while developing and for “production” mode, when building the final bundle. Fortunately, this solution exists and it’s extremely easy to integrate.

Let’s define the problem, to see how to approach it: what is Volto actually? What do you get when you open, in your browser, a Volto frontend Plone website? To greatly simplify (and I hope I didn’t get anything wrong as I am not a Volto core developer):

So, if my problem is that of slow compilation (generation of bundles by Webpack), the solution must certainly be in Webpack’s terrain. In the world of compiled languages, compilation speedup is achieved by bundling compiled code as libraries, which can then be linked to. DLL files in Windows, .so files in Linux. Webpack has an official DLL-like plugin, but its not very easy to integrate.

But there is another webpack plugin, mzgoddard/hard-source-webpack-plugin, which can automatically cache big chunks of modules. In my tests, production mode builds run 2 times faster (from 160 seconds to around 70 seconds), while “cold starting” the razzle process (with npm run start) worked 10 times faster: from 23 seconds to just 2 seconds.

To integrate it run:

yarn add -D hard-source-webpack-plugin

Then change your frontend’s razzle.config.js to something like (for Volto <9):

const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const jsConfig = require('./jsconfig').compilerOptions;

const pathsConfig = jsConfig.paths;
let voltoPath = './node_modules/@plone/volto';
Object.keys(pathsConfig).forEach(pkg => {
  if (pkg === '@plone/volto') {
    voltoPath = `./${jsConfig.baseUrl}/${pathsConfig[pkg][0]}`;
  }
});

let config = require(`${voltoPath}/razzle.config`);
const razzleModify = config.modify;

module.exports = {
  modify: (config, { target, dev }, webpack) => {
    const vc = razzleModify(config, { target, dev }, webpack);
    const hardSource = new HardSourceWebpackPlugin();
    vc.plugins.push(hardSource);
    return vc;
  },
};

Update: for Volto > 9, you should use:

const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');

const jsConfig = require('./jsconfig').compilerOptions;

const pathsConfig = jsConfig.paths;
let voltoPath = './node_modules/@plone/volto';
Object.keys(pathsConfig).forEach((pkg) => {
  if (pkg === '@plone/volto') {
    voltoPath = `./${jsConfig.baseUrl}/${pathsConfig[pkg][0]}`;
  }
});

let voltoConfig = require(`${voltoPath}/razzle.config`);

module.exports = {
  ...voltoConfig,
  modifyWebpackConfig: (opts) => {
    const vc = voltoConfig.modifyWebpackConfig(opts);
    const hardSource = new HardSourceWebpackPlugin();
    vc.plugins.push(hardSource);
    return vc;
  },
};

Comments