source.include

const defaultInclude = [
  {
    and: [rootPath, { not: /[\\/]node_modules[\\/]/ }],
  },
  /\.(?:ts|tsx|jsx|mts|cts)$/,
];

The source.include is used to specify additional JavaScript files that need to be compiled.

To avoid redundant compilation, by default, Rsbuild only compiles JavaScript files in the current directory and TypeScript and JSX files in all directories. It does not compile JavaScript files under node_modules.

Through the source.include config, you can specify directories or modules that need to be compiled by Rsbuild. The usage of source.include is consistent with Rule.include in Rspack, which supports passing in strings or regular expressions to match the module path.

For example:

import path from 'path';

export default {
  source: {
    include: [path.resolve(__dirname, '../other-dir')],
  },
};

Compile Npm Packages

A typical usage scenario is to compile npm packages under node_modules, because some third-party dependencies have ES6+ syntax, which may cause them to fail to run on low-version browsers. You can solve the problem by using this config to specify the dependencies that need to be compiled.

Take query-string as an example, you can add the following config:

import path from 'path';

export default {
  source: {
    include: [
      // Method 1:
      // First get the path of the module by require.resolve
      // Then pass path.dirname to point to the corresponding directory
      path.dirname(require.resolve('query-string')),
      // Method 2:
      // Match by regular expression
      // All paths containing `/node_modules/query-string/` will be matched
      /\/node_modules\/query-string\//,
    ],
  },
};

The above two methods match the absolute paths of files using "path prefixes" and "regular expressions" respectively. It is worth noting that all referenced modules in the project will be matched. Therefore, you should avoid using overly loose values for matching to prevent compilation performance issues or compilation errors.

Compile Sub Dependencies

When you compile an npm package via source.include, Builder will only compile the matching module by default, not the Sub Dependencies of the module.

Take query-string for example, it depends on the decode-uri-component package, which also has ES6+ code, so you need to add the decode-uri-component package to source.include as well.

export default {
  source: {
    include: [
      /\/node_modules\/query-string\//,
      /\/node_modules\/decode-uri-component\//,
    ],
  },
};

Compile Libraries in Monorepo

When developing in Monorepo, if you need to refer to the source code of other libraries in Monorepo, you can add the corresponding library to source.include:

import path from 'path';

export default {
  source: {
    include: [
      // Method 1:
      // Compile all files in Monorepo's package directory
      path.resolve(__dirname, '../../packages'),

      // Method 2:
      // Compile the source code of a package in Monorepo's package directory
      // This way of writing matches the range more accurately and has less impact on the overall build performance.
      path.resolve(__dirname, '../../packages/xxx/src'),
    ],
  },
};

Compile CommonJS Module

Babel cannot compile CommonJS modules by default, and if you compile a CommonJS module, you may get a runtime error message exports is not defined.

When you need to compile a CommonJS module using source.include, you can set Babel's sourceType configuration to unambiguous.

export default {
  tools: {
    babel(config) {
      config.sourceType = 'unambiguous';
    },
  },
};

Setting sourceType to unambiguous may have some other effects, please refer to Babel official documentation.

If you match a module that is symlinked to the current project, then you need to match the real path of the module, not the symlinked path.

For example, if you symlink the packages/foo path in Monorepo to the node_modules/foo path of the current project, you need to match the packages/foo path, not the node_modules/foo path.

This behavior can be controlled via webpack's resolve.symlinks config.

Precautions

Note that source.include should not be used to compile the entire node_modules directory. For example, the following usage is wrong:

export default {
  source: {
    include: [/\/node_modules\//],
  },
};

If you compile the entire node_modules, not only will the build time be greatly increased, but also unexpected errors may occur. Because most of the npm packages in node_modules are already compiled, there is usually no need for a second compilation. In addition, exceptions may occur after npm packages such as core-js are compiled.