Webpack Configuration Overrides

Customize your webpack configuration for advanced implementation of code components

This guide covers how to customize your webpack configuration for advanced implementation of code components.

Overview

The CLI uses an internal webpack configuration optimized for Webflow’s requirements, including Module Federation, CSS extraction, TypeScript/React support, and other optimizations. When you need to customize this configuration, you can provide an override configuration file that will be merged with the base configuration.

Review the default configuration

To view the webpack configuration used to bundle your library, use the --debug-bundler flag when running library commands:

$npx webflow library bundle --debug-bundler

This will output the final merged webpack configuration to help you understand how your overrides are being applied.

Configuration file setup

1

Specify the configuration path

In your webflow.json manifest file, add a bundleConfig property pointing to your configuration file:

webflow.json
1{
2 "library": {
3 "name": "My Library",
4 "components": ["./src/components/**/*.webflow.{js,ts,tsx}"],
5 "bundleConfig": "./webpack.override.js"
6 }
7}
2

Create your override configuration

Create a CommonJS module that exports your webpack configuration overrides, for example:

webpack.override.js
1module.exports = {
2 resolve: {
3 extensions: [".js", ".ts", ".tsx", ".json"],
4 },
5 // ...other custom configurations go here
6};

Configuration API

Your override configuration should follow the standard Webpack Configuration API with the following important exceptions and special handling:

Blocked properties

The following properties are automatically filtered out and can’t be overridden for security and compatibility reasons:

PropertyDescription
entrySpecifies the entry points for the application bundle. Determines which files webpack starts building the dependency graph from.
outputDefines how and where webpack emits the bundled files, including output directory and filename patterns.
targetSets the environment in which the bundle should run (e.g., web, node). Affects how webpack builds and optimizes the output.

If you attempt to override these properties, a warning will be logged and they will be ignored.

Special property handling

Module rules

Instead of providing an array of rules, you must provide a function that receives the current rules and returns the modified rules array:

1module.exports = {
2 module: {
3 rules: (currentRules) => {
4 // Your custom logic adding/modifying loaders goes here
5 return modifiedRules;
6 },
7 },
8};

Plugins

Your custom plugins array is merged with the default configuration using webpack-merge.

To prevent common build errors, the following plugins are automatically de-duplicated, ensuring only one instance is present in the final configuration:

  • ModuleFederationPlugin
  • MiniCssExtractPlugin

Examples

Add a new loader

To handle file types that build on existing configurations (like SCSS extending CSS), you can add a new rule that reuses parts of an existing loader chain. This ensures consistency and compatibility.

Support for common CSS frameworks

Code components support popular CSS frameworks and libraries, including Tailwind CSS, styled-components, and Emotion, material UI, shadcn/ui, and more. For detailed guidance on using these frameworks with code components, see the frameworks and libraries guide.

The example below adds a rule for .scss files by finding the existing CSS rule and appending sass-loader to it:

webpack.override.js
1module.exports = {
2 module: {
3 rules: (currentRules) => {
4 const currentCSSRule = currentRules.find(
5 (rule) =>
6 rule.test instanceof RegExp &&
7 rule.test.test("test.css") &&
8 Array.isArray(rule.use)
9 );
10 return [
11 ...currentRules,
12 {
13 test: /\.scss$/,
14 use: [...currentCSSRule.use, "sass-loader"],
15 },
16 ];
17 },
18 },
19};

Add a new rule

To process custom file types not handled by the default configuration, add a new rule. The following example adds markdown-loader to handle .md files:

webpack.override.js
1module.exports = {
2 module: {
3 rules: (currentRules) => {
4 return [
5 ...currentRules,
6 {
7 test: /\.md$/,
8 use: ["markdown-loader"],
9 },
10 ];
11 },
12 },
13};

Extend an existing loader

You can modify the options for an existing loader to customize its behavior. This requires finding the specific rule and then updating its options object.

The following example shows how to modify the css-loader to change its configuration for CSS Modules:

webpack.override.js
1module.exports = {
2 module: {
3 // Override the existing rules to modify CSS processing
4 rules: (currentRules) => {
5 return currentRules.map((rule) => {
6 // Find the rule that handles CSS files
7 if (
8 rule.test instanceof RegExp &&
9 rule.test.test("test.css") &&
10 Array.isArray(rule.use)
11 ) {
12 for (const [index, loader] of rule.use.entries()) {
13 // Find the css-loader
14 if (typeof loader === "object" && loader?.ident === "css-loader") {
15 // Preserve existing options and add a custom configuration
16 const options =
17 typeof loader.options === "object" ? loader.options : {};
18 rule.use[index] = {
19 ...loader,
20 options: {
21 ...options,
22 modules: {
23 exportLocalsConvention: "as-is", // Use original class names
24 namedExport: false, // ⚠️ Allow dot notation access
25 },
26 },
27 };
28 }
29 }
30 }
31 return rule;
32 });
33 },
34 },
35};

Add custom plugins

To add custom build-time functionality, provide an array of plugins. This example shows how to add a custom plugin to the configuration:

webpack.override.js
1const MyCustomPlugin = require("./my-custom-plugin");
2
3module.exports = {
4 plugins: [
5 new MyCustomPlugin({
6 option: "value",
7 }),
8 ],
9};

Provide aliases

To create shorter, more convenient import paths, define aliases in the resolve.alias object. This example creates an @ alias that points to the project’s root directory:

webpack.override.js
1module.exports = {
2 resolve: {
3 alias: {
4 "@": process.cwd(),
5 },
6 },
7};

Best practices

  1. Use functions for module rules: Always provide a function for module.rules to ensure proper integration with existing rules
  2. Minimal changes: Only override what you absolutely need to customize
  3. Check for conflicts: Ensure your custom loaders don’t conflict with existing ones

Troubleshooting

  • Ensure the bundleConfig path in your webflow.json is correct and relative to your project root.
  • Verify your configuration file exports a valid object using module.exports.
  • Make sure you’re providing a function for module.rules, not an array.
  • Check that your rule matching logic correctly identifies the rules you want to modify.
  • Remember that ModuleFederationPlugin and MiniCssExtractPlugin are automatically de-duplicated.
  • Ensure custom plugins don’t conflict with the base configuration.

For more information about webpack configuration options, refer to the official Webpack documentation.