Skip to content

Create webpack build script

Daniel Bischoff edited this page Apr 3, 2018 · 10 revisions

Add existing webpack build config

We set up our scripts but currently they do nothing. Let's change that.

For our build script, we want it to load our webpack build config and build our project to an output folder.

We need a folder to put all of our build configs into. So create a folder named config. In most cases you already have webpack config files so this is the moment to copy your config files to this folder. If you start from scratch, create a webpack.prod.config.js file there.

Because these config file(s) are in a completely different project than the project we want to build, we have to give our configs an absolute path to our app projects files and folders. Otherwise it will look for the files and folders in the build-project.

We will store all absolute paths in a separate file. Create another file named paths.js under the scripts folder. So whenever you have to provide a new path to any config, add this path to this file and reference it from there.

Add the following content:

scripts/paths.js

'use strict';
const path = require('path');
const fs = require('fs');

const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);

module.exports = {
  appPath: resolveApp('.'),
  appBuild: resolveApp('dist'),
  appIndex: resolveApp('src/index.jsx'),
  appHtml: resolveApp('src/index.html'),
  appSrc: resolveApp('src'),
  babelrc: path.resolve(__dirname, '../.babelrc'),
};

The most important line:

const appDirectory = fs.realpathSync(process.cwd());

This line retrieves the app's directory! Because we will always run the command from our app's directory, we can get its directory by calling process.cwd().

In your webpack config you have to change every relative path to an absolute path. I will show you the most common paths you have to change. If these properties don't exist yet, add these properties to your webpack config.

scripts/webpack.prod.config.js

const fs = require('fs');
const paths = require('./paths'); // include our paths file
const HtmlWebpackPlugin = require('html-webpack-plugin');

const babelOptions = JSON.parse(fs.readFileSync(paths.babelrc, "utf8"));

const config = {
  entry: paths.appIndex,
  output: {
    path: paths.appBuild,
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        include: paths.appSrc,
        use: [
          {
            loader: 'babel-loader',  
            options: babelOptions,            
          },
        ],
      },
    ]
  },
  plugins: [    
    new HtmlWebpackPlugin({
      template: paths.appHtml,
    }),
  ]
};

As you can see, there can be two cases how you have to set those paths.

An option to set paths exist

The webpack config file allows you to set the paths required for the build. These paths are documented in the docs. So the only thing we have to do is to set these properties to our absolute paths.

There are no properties to set paths

If there is no option to set the paths (like in the babel-loader), you can often load the config's content and pass it as an object or as a string to the specific loader. Here we load the config's contents and pass them to the options property of babel-loader.

Add build logic to build.js

In this step, we add the build logic to our build.js file.

'use strict';
process.env.NODE_ENV = 'production';

const webpack = require('webpack');
const config = require('../config/webpack.prod.config.js');

const compiler = webpack(config);
compiler.run((err, stats) => {
  if (err) {
    console.error(err.stack || err);
    if (err.details) {
      console.error(err.details.join('\n\n'));
    }
    return;
  }

  const info = stats.toJson();

  if (stats.hasErrors()) {
    console.error(info.errors.join('\n\n'));
  }

  if (stats.hasWarnings()) {
    console.warn(info.warnings.join('\n\n'));
  }
});

So what we do here, is to import our webpack build config and use the webpack compiler api to build our project. Feel free to improve the logging of errors and infos in the callback given to the run method. Here I am just doing basic logging.

FAQ

I want to know more about the webpack compile api

See here: https://webpack.js.org/api/node/

How did you know about this api?

It is in the docs: https://webpack.js.org/api/node/

I want to know more about the stats object/improve logging

See here: https://webpack.js.org/api/node/#stats-object