Output Config

This section describes some output related configurations in Modern.js Builder.

output.assetPrefix

  • Type: string
  • Default: '/'

When using CDN in the production environment, you can use this option to set the URL prefix of static assets.

assetPrefix will affect the URLs of most of the static assets, including JavaScript files, CSS files, images, videos, etc. If an incorrect value is specified, you'll receive 404 errors while loading these resources.

This config is only used in the production environment. In the development environment, please use the dev.assetPrefix to set the URL prefix.

After setting, the URLs of JavaScript, CSS and other static files will be prefixed with output.assetPrefix:

Example

export default {
  output: {
    assetPrefix: 'https://cdn.example.com/assets/',
  },
};

After building, you can see that the JS files are loaded from:

<script
  defer
  src="https://cdn.example.com/assets/static/js/main.ebc4ff4f.js"
></script>

Differences from Native Configuration

output.assetPrefix corresponds to the following native configurations:

The differences from the native configuration are as follows:

  • output.assetPrefix only takes effect in the production environment.

  • output.assetPrefix automatically appends a trailing / by default.

  • The value of output.assetPrefix is written to the process.env.ASSET_PREFIX environment variable.

output.assetsRetry

  • Type: Object

output.assetsRetry is used to configure the retry of assets.The type of AssetsRetryOptions is as follows:

export type AssetsRetryHookContext = {
  times: number;
  domain: string;
  url: string;
  tagName: string;
};

export type AssetsRetryOptions = {
  type?: string[];
  domain?: string[];
  max?: number;
  test?: string | ((url: string) => boolean);
  crossOrigin?: boolean | 'anonymous' | 'use-credentials';
  inlineScript?: boolean;
  onRetry?: (options: AssetsRetryHookContext) => void;
  onSuccess?: (options: AssetsRetryHookContext) => void;
  onFail?: (options: AssetsRetryHookContext) => void;
};

Since the ability will inject some extra runtime code into HTML, we have disabled this ability by default. If you need to enable it, you can configure it in the form of an object, for example:

export default {
  output: {
    assetsRetry: {},
  },
};

When you enable this ability, the default config of assetsRetry is as follows:

export const defaultAssetsRetryOptions: AssetsRetryOptions = {
  type: ['script', 'link', 'img'],
  domain: [],
  max: 3,
  test: '',
  crossOrigin: false,
  onRetry: () => {},
  onSuccess: () => {},
  onFail: () => {},
};

At the same time, you can also customize your retry logic using the following configurations.

assetsRetry.domain

  • Type: string[]
  • Default: []

Specifies the retry domain when assets fail to load. In the domain array, the first item is the currently used domain, and the following items are backup domains. When a asset request for a domain fails, Builder will find that domain in the array and replace it with the next domain in the array.

For example:

export default {
  output: {
    assetsRetry: {
      domain: ['https://cdn1.com', 'https://cdn2.com', 'https://cdn3.com'],
    },
  },
};

After adding the above configuration, when assets fail to load from the cdn1.com domain, the request domain will automatically fallback to cdn2.com.

If the assets request for cdn2.com also fails, the request will fallback to cdn3.com.

assetsRetry.type

  • Type: string[]
  • Default: ['script', 'link', 'img']

Used to specify the HTML tag types that need to be retried. By default, script tags, link tags, and img tags are processed, corresponding to JS code, CSS code, and images.

For example, only script tags and link tags are processed:

export default {
  output: {
    assetsRetry: {
      type: ['script', 'link'],
    },
  },
};

assetsRetry.max

  • Type: number
  • Default: 3

The maximum number of retries for a single asset. For example:

export default {
  output: {
    assetsRetry: {
      max: 5,
    },
  },
};

assetsRetry.test

  • Type: string | ((url: string) => boolean) | undefined
  • Default: undefined

The test function of the asset to be retried. For example:

export default {
  output: {
    assetsRetry: {
      test: /cdn\.example\.com/,
    },
  },
};

assetsRetry.crossOrigin

  • Type: undefined | boolean | 'anonymous' | 'use-credentials'
  • Default: same as html.crossorigin

When initiating a retry for assets, Builder will recreate the <script> tags. This option allows you to set the crossorigin attribute for these tags.

By default, the value of assetsRetry.crossOrigin will be consistent with the html.crossorigin configuration, so no additional configuration is required. If you need to configure the recreated tags separately, you can use this option, for example:

export default {
  output: {
    assetsRetry: {
      crossOrigin: true,
    },
  },
};

assetsRetry.onRetry

  • Type: undefined | (options: AssetsRetryHookContext) => void

The callback function when the asset is being retried. For example:

export default {
  output: {
    assetsRetry: {
      onRetry: ({ times, domain, url, tagName }) => {
        console.log(
          `Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}`,
        );
      },
    },
  },
};

assetsRetry.onSuccess

  • Type: undefined | (options: AssetsRetryHookContext) => void

The callback function when the asset is successfully retried. For example:

export default {
  output: {
    assetsRetry: {
      onSuccess: ({ times, domain, url, tagName }) => {
        console.log(
          `Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}`,
        );
      },
    },
  },
};

assetsRetry.onFail

  • Type: undefined | (options: AssetsRetryHookContext) => void

The callback function when the asset is failed to be retried. For example:

export default {
  output: {
    assetsRetry: {
      onFail: ({ times, domain, url, tagName }) => {
        console.log(
          `Retry ${times} times, domain: ${domain}, url: ${url}, tagName: ${tagName}`,
        );
      },
    },
  },
};

assetsRetry.inlineScript

  • Type: boolean
  • Default: true

Whether to inline the runtime JavaScript code of assetsRetry into the HTML file.

If you don't want to insert the code in the HTML file, you can set assetsRetry.inlineScript to false:

export default {
  output: {
    assetsRetry: {
      inlineScript: false,
    },
  },
};

After adding the above configuration, the runtime code of assetsRetry will be extracted into a separate assets-retry.[version].js file and output to the dist directory.

The downside is that assets-retry.[version].js itself may fail to load. If this happens, the assets retry will not work. Therefore, we prefer to inline the runtime code into the HTML file.

Notes

When you use assetsRetry, the Builder injects some runtime code into the HTML and serializes the assetsRetry config, inserting it into the runtime code. Therefore, you need to be aware of the following:

  • Avoid configuring sensitive information in assetsRetry, such as internal tokens.
  • Avoid referencing variables or methods outside of onRetry, onSuccess, and onFail.
  • Avoid using syntax with compatibility issues in onRetry, onSuccess and onFail as these functions are inlined directly into the HTML.

Here's an example of incorrect usage:

import { someMethod } from 'utils';

export default {
  output: {
    assetsRetry: {
      onRetry() {
        // Incorrect usage, includes sensitive information
        const privateToken = 'a-private-token';

        // Incorrect usage, uses an external method
        someMethod(privateToken);
      },
    },
  },
};

Limitation

assetsRetry may not work in the following scenarios:

Micro-frontend application

If your project is a micro-frontend application (such as a Garfish sub-application), the assets retry may not work because micro-frontend sub-applications are typically not loaded directly based on the <script> tag.

If you need to retry assets in micro-frontend scenarios, please contact the developers of the micro-frontend framework to find a solution.

Dynamic import resources

Currently, assetsRetry cannot work on dynamically imported resources. This feature is being supported.

Resources in custom templates

assetsRetry listens to the page error event to know whether the current resource fails to load and needs to be retried. Therefore, if the resource in the custom template is executed earlier than assetsRetry, then assetsRetry cannot listen to the event that the resource fails to load, so it cannot retry.

If you want assetsRetry to work on resources in custom templates, you can refer to Custom Insertion Example to modify html.inject configuration and custom template.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>custom template</title>
+   <%= htmlWebpackPlugin.tags.headTags %>
    <script src="//example.com/assets/a.js"></script>
  </head>
  <body>
    <div id="root" />
+    <%= htmlWebpackPlugin.tags.bodyTags %>
  </body>
</html>

output.charset

  • Type: 'ascii' | 'utf8'
  • Default: 'ascii'

By default, Builder's output is ASCII-only and will escape all non-ASCII characters.

If you want to output the original characters without using escape sequences, you can set output.charset to utf8.

export default {
  output: {
    charset: 'utf8',
  },
};

Builder will automatically add <meta charset="utf-8"> to the generated HTML files if output.charset is utf8.

output.cleanDistPath

  • Type: boolean
  • Default: true

Whether to clean all files in the dist path before starting compilation.

By default, Builder clean up the dist file, you can disable this behavior by setting cleanDistPath to false.

export default {
  output: {
    cleanDistPath: false,
  },
};

output.convertToRem

  • Type: boolean | object
  • Default: false

By setting output.convertToRem, the Builder can do the following things:

  • Convert px to rem in CSS.
  • Insert runtime code into the HTML template to set the fontSize of the root element.

Boolean Type

If output.convertToRem is set to true, Rem processing capability will be turned on.

export default {
  output: {
    convertToRem: true,
  },
};

At this point, the rem configuration defaults as follows:

{
  enableRuntime: true,
  rootFontSize: 50,
  screenWidth: 375,
  rootFontSize: 50,
  maxRootFontSize: 64,
  widthQueryKey: '',
  excludeEntries: [],
  supportLandscape: false,
  useRootFontSizeBeyondMax: false,
  pxtorem: {
    rootValue: 50,
    unitPrecision: 5,
    propList: ['*'],
  }
}

Object Type

When the value of output.convertToRem is object type, The Builder will perform Rem processing based on the current configuration.

options:

Name Type Default Description
enableRuntime boolean true Whether to generate runtime code to calculate and set the font size of the root element
inlineRuntime boolean true Whether to inline the runtime code to HTML. If set to false, the runtime code will be extracted into a separate convert-rem.[version].js file and output to the dist directory
rootFontSize number 50 The root element font size
maxRootFontSize number 64 The root element max font size
widthQueryKey string '' Get clientWidth from the url query based on widthQueryKey
screenWidth number 375 The screen width for UI design drawings (Usually, fontSize = (clientWidth * rootFontSize) / screenWidth)
excludeEntries string[] [] To exclude some page entries from injecting runtime code, it is usually used with pxtorem.exclude
supportLandscape boolean false Use height to calculate rem in landscape
useRootFontSizeBeyondMax boolean false Whether to use rootFontSize when large than maxRootFontSize
pxtorem object
  • rootValue (Default is the same as rootFontSize)
  • unitPrecision: 5
  • propList: ['*']
postcss-pxtorem options

Example

export default {
  output: {
    convertToRem: {
      rootFontSize: 30,
      excludeEntries: ['404', 'page2'],
      pxtorem: {
        propList: ['font-size'],
      },
    },
  },
};

output.copy

  • Type: CopyPluginOptions | CopyPluginOptions['patterns']
  • Default: undefined

Copies the specified file or directory to the dist directory.

For example, copy the files under src/assets to the dist directory:

export default {
  output: {
    copy: [{ from: './src/assets', to: '' }],
  },
};

For more detailed configuration, please refer to: copy-webpack-plugin.

output.cssModules

  • Type:
type CssModuleLocalsConvention =
  | 'asIs'
  | 'camelCase'
  | 'camelCaseOnly'
  | 'dashes'
  | 'dashesOnly';

type CssModules = {
  auto?: boolean | RegExp | ((resourcePath: string) => boolean);
  exportLocalsConvention?: CssModuleLocalsConvention;
};
  • Default:
const defaultCssModules = {
  exportLocalsConvention: 'camelCase',
};

Setup css modules configuration.

cssModules.auto

The auto configuration option allows CSS modules to be automatically enabled based on their filenames.

  • Type: boolean | RegExp | ((resourcePath: string) => boolean)

  • Default: undefined

Type description:

  • undefined: According to the output.disableCssModuleExtension configuration option to determine which style files to enable CSS modules.
  • true: enable CSS modules for all files matching /\.module\.\w+$/i.test(filename) regexp.
  • false: disables CSS Modules.
  • RegExp: enable CSS modules for all files matching /RegExp/i.test(filename) regexp.
  • function: enable CSS Modules for files based on the filename satisfying your filter function check.
export default {
  output: {
    cssModules: {
      auto: resource => {
        return resource.includes('.module.') || resource.includes('shared/');
      },
    },
  },
};

cssModules.exportLocalsConvention

Style of exported class names.

  • Type: 'asIs' | 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly'

  • Default: 'camelCase'

Type description:

  • asIs Class names will be exported as is.
  • camelCase Class names will be camelized, the original class name will not to be removed from the locals.
  • camelCaseOnly Class names will be camelized, the original class name will be removed from the locals.
  • dashes Only dashes in class names will be camelized.
  • dashesOnly Dashes in class names will be camelized, the original class name will be removed from the locals.
export default {
  output: {
    cssModules: {
      exportLocalsConvention: 'camelCaseOnly',
    },
  },
};

output.cssModuleLocalIdentName

  • Type: string
  • Default:
// isProd indicates that the production build
const localIdentName = isProd
  ? '[local]-[hash:base64:6]'
  : '[path][name]__[local]-[hash:base64:6]';

Sets the format of the className generated by CSS Modules after compilation.

Default Value

cssModuleLocalIdentName has different default values in development and production.

In a production, Builder will generate shorter class names to reduce the bundle size.

import styles from './index.module.scss';

// In development, the value is `.src-index-module__header--xxxxx`
// In production, the value is `.xxxxx`
console.log(styles.header);

Template String

You can use the following template strings in cssModuleLocalIdentName:

  • [name] - the basename of the asset.
  • [local] - original class.
  • [hash] - the hash of the string.
  • [folder] - the folder relative path.
  • [path] - the relative path.
  • [file] - filename and path.
  • [ext] - extension with leading dot.
  • [hash:<hashDigest>:<hashDigestLength>]: hash with hash settings.
TIP

When using Rspack as the bundler, currently does not support custom <hashDigest>.

Example

Set cssModuleLocalIdentName to other value:

export default {
  output: {
    cssModuleLocalIdentName: '[hash:base64:4]',
  },
};

output.dataUriLimit

  • Type:
type DataUriLimitConfig = {
  svg?: number;
  font?: number;
  image?: number;
  media?: number;
};
  • Default:
const defaultDatUriLimit = {
  svg: 10000,
  font: 10000,
  image: 10000,
  media: 10000,
};

Set the size threshold to inline static assets such as images and fonts.

By default, static assets will be Base64 encoded and inline into the page if the size is less than 10KB.

You can adjust the threshold by setting the dataUriLimit config.

Detail:

  • svg: The threshold of the SVG image.
  • font: The threshold of the font file.
  • image: The threshold of non-SVG images.
  • media: The threshold of media assets such as videos.

Example

Set the threshold of images to 5000 Bytes, and set media assets not to be inlined:

export default {
  output: {
    dataUriLimit: {
      image: 5000,
      media: 0,
    },
  },
};

output.disableCssExtract

  • Type: boolean
  • Default: false

Whether to disable CSS extract and inline CSS files into JS files.

By default, Builder will extract CSS into a separate .css file and output it to the dist directory. When this option is set to true, CSS files will be inlined into JS files and inserted on the page at runtime via <style> tags.

Example

export default {
  output: {
    disableCssExtract: true,
  },
};

output.disableCssModuleExtension

  • Type: boolean
  • Default: false

Whether to treat all .css files in the source directory as CSS Modules.

By default, only the *.module.css files are treated as CSS Modules. After enabling this config, all *.css style files in the source directory will be regarded as CSS Modules.

.sass, .scss and .less files are also affected by disableCssModuleExtension.

TIP

We do not recommend enabling this config, because after enabling disableCssModuleExtension, CSS Modules files and ordinary CSS files cannot be clearly distinguished, which is not conducive to long-term maintenance.

Example

export default {
  output: {
    disableCssModuleExtension: true,
  },
};

Detailed

The following is a detailed explanation of the CSS Modules rules:

disableCssModuleExtension is false (default)

The following files are treated as CSS Modules:

  • all *.module.css files

The following files are treated as normal CSS:

  • all *.css files (excluding .module)
  • all *.global.css files

disableCssModuleExtension is true

The following files are treated as CSS Modules:

  • *.css and *.module.css files in the source directory
  • *.module.css files under node_modules

The following files are treated as normal CSS:

  • all *.global.css files
  • *.css files under node_modules (without .module)
TIP

For CSS Modules files inside node_modules, please always use the *.module.css suffix.

output.distPath

  • Type:
type DistPathConfig = {
  root?: string;
  html?: string;
  js?: string;
  css?: string;
  svg?: string;
  font?: string;
  wasm?: string;
  image?: string;
  media?: string;
  server?: string;
  worker?: string;
};
  • Default:
const defaultDistPath = {
  root: 'dist',
  html: 'html',
  js: 'static/js',
  css: 'static/css',
  svg: 'static/svg',
  font: 'static/font',
  wasm: 'static/wasm',
  image: 'static/image',
  media: 'static/media',
  server: 'bundles',
  worker: 'worker',
};

Set the directory of the dist files. Builder will output files to the corresponding subdirectory according to the file type.

Detail:

  • root: The root directory of all files.
  • html: The output directory of HTML files.
  • js: The output directory of JavaScript files.
  • css: The output directory of CSS style files.
  • svg: The output directory of SVG images.
  • font: The output directory of font files.
  • wasm: The output directory of WebAssembly files.
  • image: The output directory of non-SVG images.
  • media: The output directory of media assets, such as videos.
  • server: The output directory of server bundles when target is node.
  • worker: The output directory of worker bundles when target is service-worker.

Root Directory

The root is the root directory of the build artifacts and can be specified as a relative or absolute path. If the value of root is a relative path, it will be appended to the project's root directory to form an absolute path.

Other directories can only be specified as relative paths and will be output relative to the root directory.

Example

The JavaScript files will be output to the distPath.root + distPath.js directory, which is dist/static/js.

If you need to output JavaScript files to the build/resource/js directory, you can add following config:

export default {
  output: {
    distPath: {
      root: 'build',
      js: 'resource/js',
    },
  },
};

output.disableMinimize

  • Type: boolean
  • Default: false

Whether to disable code minification on production builds.

By default, JS and CSS code is minified during the production build to improve the page performance. If you do not want to the code to be minified, you can set disableMinimize to true.

export default {
  output: {
    disableMinimize: true,
  },
};
TIP

This configuration is usually used for debugging and troubleshooting. It is not recommended to disable code minification in production environments, as it will significantly degrade the page performance.

output.disableSourceMap

  • Type:
type DisableSourceMap =
  | boolean
  | {
      js?: boolean;
      css?: boolean;
    };
  • Default:
const defaultDisableSourceMap = {
  js: false,
  css: process.env.NODE_ENV === 'production',
};

Whether to disable Source Map generation.

What is a Source Map

Source Map is an information file that saves the source code mapping relationship. It records each location of the compiled code and the corresponding pre-compilation location. With Source Map, you can directly view the source code when debugging the compiled code.

By default, Builder's Source Map generation rules are:

  • In development build, SourceMap of JS files and CSS files will be generated, which is convenient for debugging.
  • In production build, the Source Map of JS files will be generated for debugging and troubleshooting online problems; the Source Map of CSS files will not be generated.

If the project does not need Source Map, you can turned off it to speed up the compile speed.

export default {
  output: {
    disableSourceMap: true,
  },
};

If you want to enable Source Map in development and disable it in the production, you can set to:

export default {
  output: {
    disableSourceMap: process.env.NODE_ENV === 'production',
  },
};

If you need to individually control the Source Map of JS files or CSS files, you can refer to the following settings:

export default {
  output: {
    disableSourceMap: {
      js: false,
      css: true,
    },
  },
};

output.disableSvgr

  • Type: boolean
  • Default: false

Whether to transform SVGs into React components. If true, will treat all .svg files as assets.

By default, when an SVG resource is referenced in a JS file, Builder will call SVGR to convert the SVG into a React component. If you are sure that all SVG resources in your project are not being used as React components, you can turn off this conversion by setting disableSvgr to true to improve build performance.

export default {
  output: {
    disableSvgr: true,
  },
};

output.disableTsChecker

  • Type: boolean
  • Default: false

Whether to disable TypeScript type checker during compilation.

By default, Builder will run the TypeScript type checker in a separate process during the build process. Its checking logic is consistent with TypeScript's native tsc command. You can use tsconfig.json or Builder's tools.tsChecker config to customize the checking behavior.

Blocking Compilation

  • In development build, type errors will not block the compilation process.
  • In production build, type errors will cause the build to fail to ensure the stability of the production code.

Example

Disable TypeScript type checker:

export default {
  output: {
    disableTsChecker: true,
  },
};

Disable type checker in development:

export default {
  output: {
    disableTsChecker: process.env.NODE_ENV === 'development',
  },
};

Disable type checker in production:

export default {
  output: {
    disableTsChecker: process.env.NODE_ENV === 'production',
  },
};
TIP

It is not recommended to disable type checker in production, which will reduce the stability of the production code, please use it with caution.

output.disableFilenameHash

  • Type: boolean
  • Default: false

Remove the hash from the name of static files after production build.

After the production build, there will be a hash in the middle of the filename by default. You can disable this behavior through the output.disableFilenameHash config.

WARNING

Deprecated: This configuration is deprecated, please use the boolean usage of output.filenameHash instead.

Example

By default, the filename is:

File                                     Size         Gzipped
dist/static/css/187.7879e19d.css         126.99 KB    9.17 KB
dist/static/js/main.18a568e5.js          2.24 KB      922 B

Add output.disableFilenameHash config:

export default {
  output: {
    disableFilenameHash: true,
  },
};

After rebuild, the filenames become:

File                            Size         Gzipped
dist/static/css/187.css         126.99 KB    9.17 KB
dist/static/js/main.js          2.24 KB      922 B

output.disableInlineRuntimeChunk

  • Type: boolean
  • Default: false

Used to control whether to inline the bundler's runtime code into HTML.

What is runtimeChunk

Builder will generate a builder-runtime.js file in the dist directory, which is the runtime code of webpack or Rspack.

runtimeChunk is a piece of runtime code, which is provided by webpack or Rspack, that contains the necessary module processing logic, such as module loading, module parsing, etc. See Runtime for details.

In the production environment, Builder will inline the runtimeChunk file into the HTML file by default instead of writing it to the dist directory. This is done to reduce the number of file requests.

Disable Inlining

If you don't want the runtimeChunk file to be inlined into the HTML file, you can set disableInlineRuntimeChunk to true and a separate builder-runtime.js file will be generated.

export default {
  output: {
    disableInlineRuntimeChunk: true,
  },
};

Merge Into Page Chunk

If you don't want to generate a separate runtimeChunk file, but want the runtimeChunk code to be bundled into the page chunk, you can set the config like this:

export default {
  tools: {
    bundlerChain(chain) {
      chain.optimization.runtimeChunk(false);
    },
  },
};

output.enableAssetManifest

  • Type: boolean
  • Default: false

Whether to generate a manifest file that contains information of all assets.

Example

Enable asset manifest:

export default {
  output: {
    enableAssetManifest: true,
  },
};

After compiler, there will be a dist/manifest.json file:

{
  "files": {
    "main.css": "/static/css/main.45b01211.css",
    "main.js": "/static/js/main.52fd298f.js",
    "html/main/index.html": "/html/main/index.html"
  },
  "entrypoints": ["static/css/main.45b01211.css", "static/js/main.52fd298f.js"]
}

If the current project has multiple types of build artifacts, such as including SSR build artifacts, multiple manifest.json files will be generated.

  • web artifact: asset-manifest.json

  • node artifact: asset-manifest-node.json

output.enableAssetFallback

  • Type: boolean
  • Default: false

If this option is enabled, all unrecognized files will be emitted to the dist directory; otherwise, an exception will be thrown.

Example

Enable the config:

export default {
  output: {
    enableAssetFallback: true,
  },
};

Import a module of unknown type in code:

import './foo.xxx';

After compilation, foo.xxx will be output to the dist/static/media directory.

You can control the output path and filename after fallback through the output.distPath.media and output.filename.media configs.

TIP

Enabling this config will change the rules structure in the webpack config. In most cases, we do not recommend using this config.

output.enableLatestDecorators

  • Type: boolean
  • Default: false

Whether to use the new decorator proposal.

By default, Builder uses the legacy decorator proposal when compiling decorators.

When output.enableLatestDecorators is set to true, the Builder will compile with the new decorator proposal (version 2018-09).

WARNING

Deprecated: This configuration is deprecated, please use source.decorators instead.

export default {
  output: {
    enableLatestDecorators: true,
  },
};

output.enableCssModuleTSDeclaration

  • Type: boolean
  • Default: false

Whether to generate a TypeScript declaration file for CSS modules.

Example

Enable CSS module TypeScript declaration:

export default {
  output: {
    enableCssModuleTSDeclaration: true,
  },
};

After building, there will be a .d.ts file for each CSS module file. For example

interface CssExports {
  title: string;
}
export const cssExports: CssExports;
export default cssExports;

output.enableInlineScripts

  • Type:
type EnableInlineScripts =
  | boolean
  | RegExp
  | ((params: { size: number; name: string }) => boolean);
  • Default: false

Whether to inline output scripts files (.js files) into HTML with <script> tags in production mode.

Note that, with this option on, the scripts files will no longer be written in dist directory, they will only exist inside the HTML file instead.

TIP

When using convention-based routing, you need to set output.splitRouteChunks to false if this option is turned on.

Example

By default, we have following output files:

dist/html/main/index.html
dist/static/css/style.css
dist/static/js/main.js

After turn on the output.enableInlineScripts option:

export default {
  output: {
    enableInlineScripts: true,
  },
};

The output files will become:

dist/html/main/index.html
dist/static/css/style.css

And dist/static/js/main.js will be inlined in index.html:

<html>
  <body>
    <script>
      // content of dist/static/js/main.js
    </script>
  </body>
</html>

Using RegExp

If you need to inline part of the JS files, you can set enableInlineScripts to a regular expression that matches the URL of the JS file that needs to be inlined.

For example, to inline main.js into HTML, you can add the following configuration:

export default {
  output: {
    enableInlineScripts: /\/main\.\w+\.js$/,
  },
};
TIP

The production filename includes a hash value by default, such as static/js/main.18a568e5.js. Therefore, in regular expressions, \w+ is used to match the hash.

Using Function

You can also set output.enableInlineScripts to a function that accepts the following parameters:

  • name: The filename, such as static/js/main.18a568e5.js.
  • size: The file size in bytes.

For example, if we want to inline assets that are smaller than 10KB, we can add the following configuration:

export default {
  output: {
    enableInlineScripts({ size }) {
      return size < 10 * 1000;
    },
  },
};

output.enableInlineStyles

  • Type:
type EnableInlineStyles =
  | boolean
  | RegExp
  | ((params: { size: number; name: string }) => boolean);
  • Default: false

Whether to inline output style files (.css files) into HTML with <style> tags in production mode.

Note that, with this option on, the style files will no longer be written in dist directory, they will only exist inside the HTML file instead.

TIP

When using convention-based routing, you need to set output.splitRouteChunks to false if this option is turned on.

Example

By default, we have following output files:

dist/html/main/index.html
dist/static/css/style.css
dist/static/js/main.js

After turn on the output.enableInlineStyles option:

export default {
  output: {
    enableInlineStyles: true,
  },
};

The output files will become:

dist/html/main/index.html
dist/static/js/main.js

And dist/static/css/style.css will be inlined in index.html:

<html>
  <head>
    <style>
      /* content of dist/static/css/style.css */
    </style>
  </head>
  <body></body>
</html>

Using RegExp

If you need to inline part of the CSS files, you can set enableInlineStyles to a regular expression that matches the URL of the CSS file that needs to be inlined.

For example, to inline main.css into HTML, you can add the following configuration:

export default {
  output: {
    enableInlineStyles: /\/main\.\w+\.css$/,
  },
};
TIP

The production filename includes a hash value by default, such as static/css/main.18a568e5.css. Therefore, in regular expressions, \w+ is used to match the hash.

Using Function

You can also set output.enableInlineStyles to a function that accepts the following parameters:

  • name: The filename, such as static/css/main.18a568e5.css.
  • size: The file size in bytes.

For example, if we want to inline assets that are smaller than 10KB, we can add the following configuration:

export default {
  output: {
    enableInlineStyles({ size }) {
      return size < 10 * 1000;
    },
  },
};

output.externals

  • Type: string | object | function | RegExp

  • Default: undefined

At build time, prevent some import dependencies from being packed into bundles in your code, and instead fetch them externally at runtime.

For more information, please see: webpack Externals

Example

Exclude the react-dom dependency from the build product. To get this module at runtime, the value of react-dom will globally retrieve the ReactDOM variable.

export default {
  output: {
    externals: {
      'react-dom': 'ReactDOM',
    },
  },
};
TIP

When the build target is Web Worker, externals will not take effect. This is because the Worker environment can not access global variables.

output.filename

  • Type:
type FilenameConfig = {
  js?: string;
  css?: string;
  svg?: string;
  font?: string;
  image?: string;
  media?: string;
};
  • Default:
// Development
const devDefaultFilename = {
  js: '[name].js',
  css: '[name].css',
  svg: '[name].[contenthash:8].svg',
  font: '[name].[contenthash:8][ext]',
  image: '[name].[contenthash:8][ext]',
  media: '[name].[contenthash:8][ext]',
};

// Production
const prodDefaultFilename = {
  js: '[name].[contenthash:8].js',
  css: '[name].[contenthash:8].css',
  svg: '[name].[contenthash:8].svg',
  font: '[name].[contenthash:8][ext]',
  image: '[name].[contenthash:8][ext]',
  media: '[name].[contenthash:8][ext]',
};

Sets the filename of dist files.

After the production build, there will be a hash in the middle of the filename by default. This behavior can be disabled through the output.disableFilenameHash config.

The following are the details of each filename:

  • js: The name of the JavaScript file.
  • css: The name of the CSS style file.
  • svg: The name of the SVG image.
  • font: The name of the font file.
  • image: The name of a non-SVG image.
  • media: The name of a media asset, such as a video.

Example

To set the name of the JavaScript file to [name]_script.js, use the following configuration:

export default {
  output: {
    filename: {
      js:
        process.env.NODE_ENV === 'production'
          ? '[name]_script.[contenthash:8].js'
          : '[name]_script.js',
    },
  },
};
Filename hash

Usually, we only set the filename hash in the production mode (i.e., when process.env.NODE_ENV === 'production').

If you set the filename hash in the development mode, it may cause HMR to fail (especially for CSS files). This is because every time the file content changes, the hash value changes, preventing tools like mini-css-extract-plugin from reading the latest file content.

Filename of Async Modules

When you import a module via dynamic import, the module will be bundled into a single file, and its default naming rules are as follows:

  • In the development environment, the filename will be generated based on the module path, such as dist/static/js/async/src_add_ts.js.
  • In the production environment, it will be a random numeric id, such as dist/static/js/async/798.27e3083e.js. This is to avoid leaking the source code path in the production environment, and the number of characters is also less.
src/index.ts
const { add } = await import('./add.ts');

If you want to specify a fixed name for the async module, you can use the magic comments provided by the bundler to achieve this, using webpackChunkName to specify the module name:

src/index.ts
const { add } = await import(
  /* webpackChunkName: "my-chunk-name" */ './add.ts'
);

After specifying the module name as above, the generated file will be dist/static/js/async/my-chunk-name.js.

output.legalComments

  • Type: 'linked' | 'inline' | 'none'
  • Default: 'linked'

Configure how to handle the legal comment.

A "legal comment" is considered to be any statement-level comment in JS or rule-level comment in CSS that contains @license or @preserve or that starts with //! or /*!. These comments are preserved in output files by default since that follows the intent of the original authors of the code.

This behavior can be configured by using one of the following options:

  • linked: Extract all legal comments to a .LEGAL.txt file and link to them with a comment.
  • inline: Preserve all legal comments in original position.
  • none: Remove all legal comments.

Example

Remove all legal comments:

export default {
  output: {
    legalComments: 'none',
  },
};

output.overrideBrowserslist

  • Type: string[] | Record<BuilderTarget, string[]
  • Default: undefined

Specifies the range of target browsers that the project is compatible with. This value will be used by @babel/preset-env and autoprefixer to identify the JavaScript syntax that need to be transformed and the CSS browser prefixes that need to be added.

Priority

The overrideBrowserslist config will override the .browserslistrc config file in the project and the browserslist field in package.json.

In most cases, it is recommended to use the .browserslistrc file rather than the overrideBrowserslist config. Because the .browserslistrc file is the official config file, it is more general and can be recognized by other libraries in the community.

Default Value

If there is no browserslist configs defined in the project, nor overrideBrowserslist defined, then Builder will set the default browserslist to:

['> 0.01%', 'not dead', 'not op_mini all'];

Example

An example compatible with mobile scenarios:

export default {
  output: {
    overrideBrowserslist: [
      'iOS >= 9',
      'Android >= 4.4',
      'last 2 versions',
      '> 0.2%',
      'not dead',
    ],
  },
};

Check out the browserslist documentation to learn more about browserslist.

Set according to Targets

When you build multiple targets at the same time, you can set different browser ranges for different targets. At this point, you need to set overrideBrowserslist to an object whose key is the corresponding build target.

For example to set different ranges for web and node:

export default {
  output: {
    overrideBrowserslist: {
      web: [
        'iOS >= 9',
        'Android >= 4.4',
        'last 2 versions',
        '> 0.2%',
        'not dead',
      ],
      node: ['node >= 14'],
    },
  },
};

output.polyfill

  • Type: 'entry' | 'usage' | 'ua' | 'off'
  • Default: 'entry'

Via output.polyfill you can configure how the polyfill is injected.

Config

entry

Polyfill is injected in every entry file when output.polyfill is configured as 'entry'.

Equivalent to useBuiltIns: 'entry' configuration in @babel/preset-env.

usage

Polyfill is injected in each file based on the API used in the code.

Equivalent to useBuiltIns: 'usage' configuration in @babel/preset-env.

ua

The Polyfill code is dynamically delivered according to the currently requested UA information.

The dynamic delivery feature needs to be used with the upper-level framework. For more details, please refer to Modern.js - Polyfill At Runtime.

off

Polyfill is not injected. When using this option, you need to ensure code compatibility yourself.

output.svgDefaultExport

  • Type: 'url' | 'component'
  • Default: 'url'

output.svgDefaultExport is used to configure the default export type of SVG files.

When output.svgDefaultExport is set to url , the default export of SVG files is the URL of the file. For example:

import logo from './logo.svg';

console.log(logo); // => asset url

When output.svgDefaultExport is set to component , the default export of SVG files is the React component of the file. For example:

import Logo from './logo.svg';

console.log(Logo); // => React Component

At this time, you can also specify the ?url query to import the URL, for example:

import logo from './logo.svg?url';

console.log(logo); // => asset url
ON THIS PAGE