Webpack Configuration

Webpack and Webpack dev server are used as the default bundlers in Bit's official envs and frontend application types.

Envs use webpack for component previews (compositions and docs), while application types use it for the app's bundle.

The Webpack configurations for Webpack and Webpack Dev Server are generated dynamically during their execution. Modifying Webpacks configuration is therefore done, dynamically, using transformers.

Webpack transformers

A Webpack transformer is a function that receives a webpack config, and returns a modified version of it.

Webpack configs are wrapped as Webpack config mutators. These are objects that include the raw webpack config, as well as a set of useful methods for modifying it.

For example, the following transformer receives a config mutator that includes a raw config (shown under the 'Original config' tab). It uses the mutator's addEntry method to modify it.

const addEntryTransformer = (configMutator) => {
    configMutator.addEntry('./new/entry');
    return configMutator;
  }
Copied
Transformed config
Original config
{
  entry: ["./new/entry", "./app-root.js"],
  output: {
    filename: "main.js",
    path: "path/to/output"
  }
}
CopiedCopy

Webpack config mutators also include a merge method that uses the webpack-merge library to merge an array of configs.

const modifyOutputTransformer = (configMutator) => {
  const newWebpackConfig = {
    output: {
      publicPath: 'path/to/assets',
    },
  };

  configMutator.merge([newWebpackConfig]);
  return configMutator;
};
Copied
Transformed config
Original config
{
  entry: ["./app-root.js"],
  output: {
    filename: "main.js",
    path: "path/to/output",
    publicPath: "path/to/assets"
  }
}
CopiedCopy

Reviewing Webpack config

To review your Webpack config (after mutation), print out your mutator's raw config. For example:

const addEntryTransformer = (configMutator) => {
  configMutator.addEntry('./new/entry');

  console.log('Webpack config', configMutator.raw);

  return configMutator;
};
CopiedCopy

Note that a different output will be printed out, according to the process being run:

  • Webpack config for preview during development: bit start
  • Webpack config for preview during build: bit build <component>
  • Webpack config for an app's bundle during development: bit run <app-name>
  • Webpack config for an app's bundle during build (for production): bit build <app-component-id>

Alternatively, to inspect your env's (preview) Webpack config, run the following on a component that uses that env:

$bit
Copiedcopy

The output is similar to the following:

Environment: my-org.my-scope/examples/my-react-env

teambit.compilation/bundler

dev server config:

{ mode: 'development', devtool: 'inline-source-map', ... } ...

Piping transformers

Customize your Webpack config by passing an array of transformers. Webpack will use this array to pipe the mutated config from one transformer to the other.

The following example passes and array of webpack transformers to the env's preview options:

preview(): {
    return EnvPreview.from({
      transformers: [
        addEntryTransformer,
        modifyOutputTransformer
      ],
    });
  }
Copied
Transformed config
Original config
{
  entry: ["./new/entry", "./app-root.js"],
  output: {
    filename: "main.js",
    path: "path/to/output",
    publicPath: "path/to/assets"
  }
}
CopiedCopy

Sharing transformers

It is recommended to maintain transformers as independent Bit components. This will allow you to reuse your transformers across envs and apps, to save time and maintain consistency between your component previews and your apps' production bundles.

For example, the following React env and React app, use the same transformer to add support for GraphQL files: