---
sidebar_position: 1
---

# buildConfig

`buildConfig` 是一个用来描述如何编译、生成构建产物的配置项，它包含了构建的所有配置。

- 类型：`object | object[]`

:::tip
在开始使用 `buildConfig` 之前，请先阅读以下文档来了解其作用：

- [修改输出产物](/guide/basic/modify-output-product.html)
- [深入理解构建](/guide/advance/in-depth-about-build.html)

:::

## alias

- 类型：`Record<string, string> | Function`
- 默认值：`{'@': 'src',}`

:::tip
对于 TypeScript 项目，只需要在 `tsconfig.json` 中配置 [compilerOptions.paths](https://www.typescriptlang.org/tsconfig#paths), Modern.js Module 会自动识别 `tsconfig.json` 里的别名，因此不需要额外配置 `alias` 字段。
:::

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    alias: {
      '@common': './src/common',
    },
  },
});
```

以上配置完成后，如果在代码中引用 `@common/Foo.tsx`, 则会映射到 `<project>/src/common/Foo.tsx` 路径上。

`alias` 的值定义为函数时，可以接受预设的 alias 对象，并对其进行修改。

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    alias: alias => {
      alias['@common'] = './src/common';
    },
  },
});
```

也可以在函数中返回一个新对象作为最终结果，新对象会覆盖预设的 alias 对象。

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    alias: alias => {
      return {
        '@common': './src/common',
      };
    },
  },
});
```

## asset

包含静态资源相关的配置。

## asset.name

静态资源输出文件名。

- 类型： `string | ((assetPath) => name)`
- 默认值： `[name].[hash].[ext]`

当 asset.name 为 string 类型时，会自动对 [name]、[ext]、[hash] 进行替换，分别替换为文件名、拓展名、文件 hash。
如果想要更高的自由度，可以把 asset.name 作为方法使用，返回值即为文件名。此时，该方法接收一个参数 assetPath，对应资源路径。

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    asset: {
      // no hash
      name: [name].[ext],
      // any logic
      // name: (assetPath) => 'any.png',
    },
  },
});
```

## asset.limit

用于设置静态资源被自动内联为 base64 的体积阈值。

Modern.js Module 在进行打包时，默认会内联体积小于 10KB 的图片、字体、媒体等资源，将它们通过 Base64 编码，并内联到产物中，不再会发送独立的 HTTP 请求。

你可以通过修改 `limit` 参数来调整这个阈值。

- 类型： `number`
- 默认值： `10 * 1024`

例如，将 `limit` 设置为 `0` 来避免资源内联：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    asset: {
      limit: 0,
    },
  },
});
```

## asset.path

静态资源输出路径，会基于 [outDir](/api/config/build-config#outdir) 进行输出。

- 类型： `string`
- 默认值： `assets`

## asset.publicPath

打包时给未内联资源的 CDN 前缀。

- 类型： `string`
- 默认值： `undefined`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    asset: {
      publicPath: 'https://xxx/',
    },
  },
});
```

此时，所有静态资源都会添加 `https://xxx/` 前缀。

## asset.svgr

打包时将 SVG 作为一个 React 组件处理，options 参考 [svgr](https://react-svgr.com/docs/options/)，另外还支持了 `include` 和 `exclude` 两个配置项，用于匹配需要处理的 SVG 文件。

- 类型： `boolean | object`
- 默认值： `false`

开启 svgr 功能后，可以使用默认导出的方式将 SVG 当做组件使用。

```js title="index.ts"
// true
import Logo from './logo.svg';

export default () => <Logo />;
```

当开启功能后，可以新建一个类型描述文件，并在 `modern-app-env.d.ts` 文件中增加，修改使用 SVG 的类型：

```ts title="your-app-env.d.ts"
declare module '*.svg' {
  const src: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
  export default src;
}
```

```ts title="modern-app-env.d.ts"
/// <reference path='./your-app-env.d.ts' />
/// <reference types='@modern-js/module-tools/types' />
```

## asset.svgr.include

设定匹配的 SVG 文件

- 类型： `string | RegExp | (string | RegExp)[]`
- 默认值： `/\.svg$/`

## asset.svgr.exclude

设定不匹配的 SVG 文件

- 类型： `string | RegExp | (string | RegExp)[]`
- 默认值： `undefined`

## asset.svgr.exportType

用于配置使用 SVGR 时 SVG 的导出形式。

- 类型： `'named' | 'default'`
- 默认值： `default`

当此选项设置为 'named' 时，你可以使用以下语法导入组件：

```js title="index.ts"
import { ReactComponent } from './logo.svg';
```

命名导出默认为 `ReactComponent`，并可以通过 `asset.svgr.namedExport` 进行自定义。

## autoExtension

根据 [format](#format) 和 [type](https://nodejs.org/api/packages.html#type) 自动添加产物里 js 文件和类型描述文件的后缀。

- 类型：`boolean`
- 默认值：`false`
- 版本：`>=MAJOR_VERSION.38.0`

关闭时，js 产物后缀为 `.js`，类型描述文件后缀为 `d.ts`。

开启后，当 type 为 `module` 时，node 默认将 `.js` 作为 esm 加载，因此当我们要输出 cjs 产物时，js 产物后缀为 `.cjs`，类型描述文件后缀为 `d.cts`;
反之，如果缺少 type 字段或者 type 为 `commonjs` 时， node 默认将 `.js` 文件作为 cjs 加载，因此当我们要输出 esm 产物时，js 产物后缀为 `.mjs`，类型描述文件后缀为 `d.mts`。

:::warning
在 bundleless 模式下使用时，我们会有一步额外的操作，那就是处理每个文件里的 import/export 语句。我们会给相对路径加上 js 文件后缀，可能是 `.mjs` 或者 `.cjs`，这取决于你的包配置，此行为可以通过 [redirect.autoExtension](#redirect)关闭。

注意 [noUselessIndex](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-useless-path-segments.md#nouselessindex) 规则会破坏此行为，你需要禁用此规则
如果你需要在 bundleless 使用此配置，请补齐 `index`，例如 utils 是一个文件夹， 你需要将 `import * from './utils'` 改写为 `import * from './utils/index'`
:::

```ts title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    autoExtension: true,
  },
});
```

## autoExternal

自动外置项目的 `"dependencies"` 和 `"peerDependencies"`，不会将其打包到最终的 bundle 产物中。

- 类型： `boolean | object`
- 默认值： `true`

当我们希望关闭对于第三方依赖的默认处理行为时候，可以通过以下方式来实现：

```ts title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    autoExternal: false,
  },
});
```

这样对于 `"dependencies"` 和 `"peerDependencies"` 下面的依赖都会进行打包处理。如果只想要关闭其中某个下面的依赖处理，则可以使用
`buildConfig.autoExternal` 的对象形式：

```ts title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    autoExternal: {
      dependencies: false,
      peerDependencies: false,
    },
  },
});
```

## autoExternal.dependencies

是否需要外置项目的 `"dependencies"` 依赖。

- 类型： `boolean`
- 默认值： `true`

## autoExternal.peerDependencies

是否需要外置项目的 `"peerDependencies"` 依赖。

- 类型： `boolean`
- 默认值： `true`

## banner

提供为每个 JS , CSS 和 DTS 文件的顶部和底部注入内容的能力。

```ts
interface BannerAndFooter {
  js?: string;
  css?: string;
  dts?: string;
}
```

- 类型： `BannerAndFooter`
- 默认值: `{}`
- 版本： `>=MAJOR_VERSION.36.0`

例如你想为 JS 和 CSS 文件添加版权信息:

```ts
import { moduleTools, defineConfig } from '@modern-js/module-tools';

const copyRight = `/*
 © Copyright 2020 example.com or one of its affiliates.
 * Some Sample Copyright Text Line
 * Some Sample Copyright Text Line
*/`;

export default defineConfig({
  plugins: [moduleTools()],
  buildConfig: {
    banner: {
      js: copyRight,
      css: copyRight,
    },
  },
});
```

## buildType

构建类型，`bundle` 会打包你的代码，`bundleless` 只做代码的转换。

- 类型： `'bundle' | 'bundleless'`
- 默认值： `'bundle'`

## copy

将文件或目录拷贝到指定位置。

- 类型： `object`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    copy: {
      patterns: [{ from: './src/assets', to: '' }],
    },
  },
});
```

:::tip
参考 [使用 Copy 工具](/guide/advance/copy) 了解 `copy` 选项的完整用法。
:::

## copy.patterns

- 类型： `CopyPattern[]`
- 默认值： `[]`

```ts
interface CopyPattern {
  from: string;
  to?: string;
  context?: string;
  globOptions?: globby.GlobbyOptions;
}
```

## copy.options

- 类型：

```ts
type Options = {
  concurrency?: number;
  enableCopySync?: boolean;
};
```

- 默认值： `{ concurrency: 100, enableCopySync: false }`

- `concurrency`: 指定并行执行多少个复制任务。
- `enableCopySync`: 使用 [`fs.copySync`](https://github.com/jprichardson/node-fs-extra/blob/master/lib/copy/copy-sync.js)，默认情况下 [`fs.copy`](https://github.com/jprichardson/node-fs-extra/blob/master/lib/copy/copy.js)。

## define

定义全局变量，注入到代码中

- 类型： `Record<string, string>`
- 默认值： `{}`

由于 `define` 功能是由全局文本替换实现的，所以需要保证全局变量值为字符串，更为安全的做法是将每个全局变量的值转化为字符串，如下所示：

:::info
框架内部会自动进行 JSON 序列化处理，因此不需要手动执行序列化。

如果不需要自动序列化，可以通过配置 [`esbuildOptions`](/api/config/build-config.html#esbuildoptions) 定义 [`alias`](https://esbuild.github.io/api/#alias) 来实现。
:::

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    define: {
      VERSION: require('./package.json').version || '0.0.0',
    },
  },
});
```

不过要注意：如果项目是一个 TypeScript 项目，那么你可能需要在项目源代码目录下的 `.d.ts` 文件里增加以下内容：

> 如果不存在 `d.ts` 文件，则可以手动创建。

```ts title="env.d.ts"
declare const YOUR_ADD_GLOBAL_VAR;
```

我们也可以进行环境变量替换：

```js
import { defineConfig } from '@modern-js/module-tools';
export default defineConfig({
  buildConfig: {
    define: {
      'process.env.VERSION': process.env.VERSION || '0.0.0',
    },
  },
});
```

通过上面的配置，我们就可以将下面这段代码：

```js
// 编译前代码
console.log(process.env.VERSION);
```

在执行 `VERSION=1.0.0 modern build` 的时候，转换为：

```js
// 编译后代码
console.log('1.0.0');
```

:::tip
为了防止全局替换替换过度，建议使用时遵循以下两个原则：

- 全局常量使用大写
- 自定义全局常量前缀后缀，确保独一无二

:::

## dts

类型文件生成的相关配置，默认情况会生成。

- 类型： `false | object`
- 默认值：

```js
{
  abortOnError: true,
  distPath: './',
  only: false,
}
```

## dts.abortOnError

用于控制在出现类型错误的时候，是否允许构建成功。

- 类型：`boolean`
- 默认值：`true`

**默认情况下，在出现类型错误的时候会导致构建失败**。将 `abortOnError` 设置为 `false` 后，即使代码中出现了类型问题，构建依然会成功：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    dts: {
      abortOnError: false,
    },
  },
});
```

:::warning
当关闭该配置后，无法保证类型文件能正常生成，且不保证内容正确。在 `buildType: 'bundle'` 时，即打包模式下，类型文件一定不会生成。
:::

## dts.distPath

类型文件的输出路径，基于 [outDir](/api/config/build-config#outdir) 进行输出。

- 类型： `string`
- 默认值： `./`

比如输出到 `outDir` 下面的 `types` 目录：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    dts: {
      distPath: './types',
    },
  },
});
```

## dts.enableTscBuild

开启 tsc '--build' 选项。当使用 project reference 时，
可以使用 '--build' 选项以实现项目之间的协同工作以加快构建速度。

此选项要求版本 > MAJOR_VERSION.43.0，
事实上，我们在 MAJOR_VERSION.42.0 版本曾试验性地开启此选项，但其带来的许多问题使我们不得不动态开启。

```warning
当开启此选项时，为了满足构建需求，你必须显式地在 tsconfig.json 里设置 'declarationDir' 或者 'outDir'，
如果你用的不是 TS >= 5.0 版本，你还需要显式地设置 'declaration' 和 'emitDeclarationOnly'。
```

- 类型： `boolean`
- 默认值： `false`
- 版本： `>MAJOR_VERSION.43.0`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    dts: {
      enableTscBuild: true,
    },
  },
});
```

## dts.only

是否在构建时只生成类型文件，不生成 JavaScript 产物文件。

- 类型： `boolean`
- 默认值： `false`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    dts: {
      only: true,
    },
  },
});
```

## dts.respectExternal

当设为 `false` 时，不会打包任何三方包类型，设为 `true` 时，会根据 [externals](#externals) 来决定是否需要打包三方类型。

在对类型文件进行打包时，构建工具还未对 export 进行分析，因此当你引用的任何一个三方包出现类型错误时，都可能会中断当前的构建流程，这会导致构建流程不可控，因此我们可以通过这个配置来避免该问题。

- 类型： `boolean`
- 默认值： `true`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    dts: {
      respectExternal: false,
    },
  },
});
```

## dts.tsconfigPath

**废弃**，使用 [tsconfig](#tsconfig) 配置替代。

指定用于生成类型文件的 tsconfig 文件路径。

```ts title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    dts: {
      tsconfigPath: './other-tsconfig.json',
    },
  },
});
```

## esbuildOptions

用于修改底层的 [esbuild 配置](https://esbuild.github.io/api/)。

- 类型： `Function`
- 默认值： `c => c`

例如，我们需要修改生成文件的后缀：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    esbuildOptions: options => {
      options.outExtension = { '.js': '.mjs' };
      return options;
    },
  },
});
```

例如，注册一个 esbuild 插件：

import RegisterEsbuildPlugin from '@site-docs/components/register-esbuild-plugin';

<RegisterEsbuildPlugin />

:::tip
我们在原本 esbuild 构建的基础上做了许多扩展，因此使用此配置需要注意以下几点：

1. 优先使用 Modern.js Module 提供的配置，例如 esbuild 并不支持 `target: 'es5'`，但我们内部使用 SWC 支持了此场景，此时通过 `esbuildOptions` 设置`target: 'es5'`会报错。
2. 目前我们内部使用 `enhanced-resolve` 替代了 esbuild 的 resolve 解析算法，所以修改 esbuild resolve 相关配置无效，计划在未来会切换回来。

:::

## externalHelpers

默认情况下，输出的 JS 代码可能会依赖一些辅助函数来支持目标环境或者输出格式，这些辅助函数会被内联在需要它的文件中。

使用此配置，将会使用 SWC 对代码进行转换，将内联的辅助函数转换为从外部模块 `@swc/helpers` 导入这些辅助函数。

- 类型：`boolean`
- 默认值：`false`

下面是使用该配置前后的产物变化比较。

开启前：

```js title="./dist/index.js"
// 辅助函数
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  // ...
}
// 辅助函数
function _async_to_generator(fn) {
  return function () {
    // use asyncGeneratorStep
    // ...
  };
}

// 你的代码
export var yourCode = function () {
  // use _async_to_generator
};
```

开启后：

```js title="./dist/index.js"
// 从 @swc/helpers 导入的辅助函数
import { _ as _async_to_generator } from '@swc/helpers/_/_async_to_generator';

// 你的代码
export var yourCode = function () {
  // use _async_to_generator
};
```

## externals

用于在打包时排除一些外部依赖，避免将这些依赖打包到最终的 bundle 中。

- 类型：

```ts
type Externals = (string | RegExp)[];
```

- 默认值： `[]`
- 构建类型：`仅支持 buildType: 'bundle'`
- 示例：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    // 避免打包 React
    externals: ['react'],
  },
});
```

## footer

同 [banner](#banner) 配置，用于在输出文件末尾添加注释。

## format

用于设置 JavaScript 产物输出的格式，其中 `iife` 和 `umd` 只在 `buildType` 为 `bundle` 时生效。

- 类型：`'esm' | 'cjs' | 'iife' | 'umd'`
- 默认值：`cjs`

### format: esm

esm 代表 "ECMAScript 模块"，它需要运行环境支持 import 和 export 语法。

- 示例：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    format: 'esm',
  },
});
```

### format: cjs

cjs 代表 "CommonJS"，它需要运行环境支持 exports、require 和 module 语法，通常为 Node.js 环境。

- 示例：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    format: 'cjs',
  },
});
```

### format: iife

iife 代表 "立即调用函数表达式"，它将代码包裹在函数表达式中，确保代码中的任何变量不会意外地与全局范围中的变量冲突，通常在浏览器环境中运行。

- 示例：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    format: 'iife',
  },
});
```

### format: umd

umd 代表 "Universal Module Definition"，用于在不同环境（浏览器、Node.js 等）中运行。umd 格式的模块可以在多种环境下使用，既可以作为全局变量访问，也可以通过模块加载器（如 RequireJS）进行模块化加载。

- 示例：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    format: 'umd',
  },
});
```

## hooks

构建生命周期钩子,允许在构建流程的特定阶段注入自定义逻辑。

- 类型：

```ts
type HookList = {
  name: string;
  apply: (compiler: ICompiler) => void;
  // 是否在 buildIn 钩子之后执行
  applyAfterBuiltIn?: boolean;
};
```

- 默认值：`[]`

我们可以在 apply 方法里拿到 compiler 实例，修改其属性，以及在不同阶段执行自定义逻辑，对于 Hook 的详细介绍，
参考[使用 Hook 介入构建流程](/guide/advance/in-depth-about-build.html#使用-hook-介入构建流程)。

```ts title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    buildType: 'bundle',
    hooks: [
      {
        name: 'renderChunk',
        apply: compiler => {
          // any logic for compiler
          compiler.hooks.renderChunk.tapPromise(
            { name: 'renderChunk' },
            async chunk => {
              return chunk;
            },
          );
        },
      },
    ],
  },
});
```

## input

指定构建的入口文件，数组形式可以指定目录。

- 类型：

```ts
type Input =
  | string[];
  | {
      [name: string]: string;
    }
```

- 默认值：`bundle` 模式下默认为 `['src/index.ts']`，`bundleless` 模式下默认为 `['src']`

**数组用法：**

在 `bundle` 模式下，下面的配置会以 `src/index.ts` 和 `src/index2.ts` 为入口分别进行构建。`bundle` 模式不支持配置 `input` 为目录。

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    buildType: 'bundle',
    input: ['src/index.ts', 'src/index2.ts'],
  },
});
```

在 `bundleless` 模式下，下面的配置会同时处理 `src/a` 目录下的文件和 `src/index.ts` 文件。

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    buildType: 'bundleless',
    input: ['src/a', 'src/index.ts'],
  },
});
```

在 `bundleless` 模式下，数组模式还支持使用 `!` 来过滤部分文件：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    buildType: 'bundleless',
    input: ['src', '!src/*.spec.ts'],
  },
});
```

上面的配置将打包 `src` 目录下的文件，同时会过滤以 `spec.ts` 为后缀的文件。这在测试文件与源码文件在同一个根目录下的情况会很有用。

**对象用法：**

当在 bundle 模式下需要修改产物的输出文件名称的时候，可以使用对象形式进行配置。

**对象的 Key 是产物的文件名称，Value 是源码的文件路径。**

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    format: 'esm',
    input: {
      'index.esm': './src/index.ts',
    },
  },
});
```

## jsx

指定 JSX 的编译方式，默认支持 React 17 及更高版本，自动注入 JSX 运行时代码。

- 类型： `automatic | transform | preserve`
- 默认值： `automatic`

如果你需要支持 React 16，则可以设置 `jsx` 为 `transform`：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    jsx: 'transform',
  },
});
```

:::tip
如果你不需要转换 JSX ,可以设置 `jsx` 为 `preserve`, 但此时请不要[使用 swc](/guide/advance/in-depth-about-build#使用-swc) 做代码转换。
关于 JSX Transform 的更多说明，可以参考以下链接：

- [React Blog - Introducing the New JSX Transform](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html).
- [esbuild - JSX](https://esbuild.github.io/api/#jsx).

:::

## loader

**试验性功能**

此选项用来更改给定输入文件的解释方式。例如你需要将 js 文件当做 jsx 处理

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    loader: {
      '.js': 'jsx',
    },
  },
});
```

## metafile

这个选项用于构建分析，开启该选项后，esbuild 会以 JSON 格式生成有关构建的一些元数据。

- 类型：`boolean`
- 默认值：`false`
- 构建类型：`仅支持 buildType: 'bundle'`

开启 `metafile` 生成：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    buildType: 'bundle',
    metafile: true,
  },
});
```

在执行 build 构建后，产物目录下会生成 `metafile-[xxx].json` 文件，你可以通过 [esbuild analyze](https://esbuild.github.io/analyze/) 和 [bundle-buddy](https://bundle-buddy.com/esbuild) 等工具进行可视化分析。

## minify

使用 esbuild 或者 terser 压缩代码，也可以传入 [terserOptions](https://github.com/terser/terser#minify-options)。

- 类型： `'terser' | 'esbuild' | false | object`
- 默认值： `false`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    minify: {
      compress: {
        drop_console: true,
      },
    },
  },
});
```

## outDir

指定构建的输出目录。

- 类型： `string`
- 默认值： `./dist`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    outDir: './dist/esm',
  },
});
```

## platform

默认生成用于 Node.js 环境下的代码，你也可以指定为 `browser`，会生成用于浏览器环境的代码。
查看[esbuild.platform](https://esbuild.github.io/api/#platform)了解更多。

- 类型： `'browser' | 'node'`
- 默认值： `'node'`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    platform: 'browser',
  },
});
```

## redirect

在 **`buildType: 'bundleless'`** 构建模式下，会对引用路径进行重定向，确保指向了正确的产物，例如：

- `import './index.less'` 会被改写成 `import './index.css'`
- `import icon from './close.svg'` 会被改写成 `import icon from '../asset/close.svg'`（依实际情况而定）
- `import * from './utils'` 会被改写成 `import * from './utils.mjs'` (如果生成了 utils.mjs，视实际情况而定)

在某些场景下，你可能不需要这些功能，那么可以通过此配置关闭它，关闭后，其引用路径将不会发生改变。

```js title="modern.config.ts"
export default {
  buildConfig: {
    redirect: {
      alias: false, // 关闭对别名路径的修改
      style: false, // 关闭对样式文件路径的修改
      asset: false, // 关闭对资源文件路径的修改
      autoExtension: false, // 关闭对 js 文件后缀的修改
    },
  },
};
```

## resolve

自定义模块解析选项

### resolve.alias

基本用法和 [alias](#alias) 一致。

[alias](#alias) 的问题在于我们在 bundleless 场景下错误的处理了 Module ID 的情况：

```js
import { createElement } from 'react';
```

当我们配置了 `alias: { react: 'react-native' }` 后，结果会变成

```js
import { createElement } from './react-native';
```

一个 Module ID 被错误的处理成了相对路径，显然这是不符合预期的。

我们想要修复这个问题，但是这可能会破坏已有的项目，因此我们在 MAJOR_VERSION.58.0 版本提供了 `resolve.alias` 来解决这个问题。
并且 `resolve.alias` 里移除了 [alias](#alias) 提供的默认值 `{ "@": "./src"}`

如果你需要此功能，请使用 `resolve.alias`。

在下一个大版本，`resolve.alias` 将会取代 `alias` 。

:::warning

- 注意此配置不要与 [alias](#alias) 混用。
- 注意此配置必须标注一个相对路径，例如 `{ "@": "./src" }` 而非 `{ "@": "src"}`。

:::

### resolve.mainFields

package.json 中，在解析包的入口点时尝试的字段列表。

- 类型：`string[]`
- 默认值：取决于[platform](#platform)
  - node: ['module', 'main']
  - browser: ['module', 'browser', 'main']
- 版本：`>=MAJOR_VERSION.36.0`

例如，我们想要先加载 `js:source` 字段：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    resolve: {
      mainFields: ['js:source', 'module', 'main'],
    },
  },
});
```

:::warning
`resolve.mainFields` 比 package.json 中 exports 字段的优先级低，如果一个入口点从 exports 成功解析，`resolve.mainFields` 将被忽略。
:::

### resolve.jsExtentions

支持隐式文件扩展名

- 类型： `string[]`
- 默认值： `['.jsx', '.tsx', '.js', '.ts', '.json']`
- 版本：`>=MAJOR_VERSION.36.0`

对于 css 文件，请不要使用隐式文件扩展名，目前 Module 仅支持 ['.less', '.css', '.sass', '.scss'] 后缀。

Node 的解析算法不会将 `.mjs` 和 `cjs` 视为隐式文件扩展名，因此这里默认也不会，但是可以通过更改此配置来包含：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    resolve: {
      jsExtentions: ['.mts', 'ts'],
    },
  },
});
```

### resolve.tsconfig

用于配置 enhanced-resolve 中的 [tsconfig-paths-webpack-plugin](https://www.npmjs.com/package/tsconfig-paths-webpack-plugin)，来支持解析 tsconfig.json 中的 alias 和嵌套 `@` 别名冲突的问题。

- 类型：

```ts
type Tsconfig = {
  configFile: string;
  references?: string[] | undefined;
};
```

- 默认值： `{ configFile: config.tsconfig, references: undefined }`
- 版本：`>=MAJOR_VERSION.61.1`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    resolve: {
      tsConfig: {
        configFile: './tsconfig.json',
      },
    },
  },
});
```

## shims

在构建 cjs / esm 产物时注入一些垫片代码。

例如 `__dirname` 只能在 commonjs 里使用，开启此选项后，当产物格式为 esm 时，会将 `__dirname` 编译为 `path.dirname(fileURLToPath(import.meta.url))`。

详细代码见 [shims](https://github.com/web-infra-dev/modern.js/blob/main/packages/solutions/module-tools/shims)，
需要注意的是 esm shims 只会在 [platform](#platform) 为 node 时注入，因为用到了 url 模块。

- 类型： `boolean`
- 默认值： `false`
- 版本：`>=MAJOR_VERSION.38.0`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    shims: true,
  },
});
```

## sideEffects

配置模块的副作用

- 类型： `RegExg[] | (filePath: string, isExternal: boolean) => boolean | boolean`
- 默认值： `undefined`

通常情况下，我们通过 package.json 的 `"sideEffects"` 字段来配置模块的副作用，但是在某些情况下，三方包的 package.json 是不可靠的。
例如我们引用了一个三方包的样式文件。

```js
import 'other-package/dist/index.css';
```

但是这个三方包的 package.json 里并没有将样式文件配置到 `"sideEffects"` 里。

```json title="other-package/package.json"
{
  "sideEffects": ["dist/index.js"]
}
```

同时你又设置了 [style.inject](#styleinject) 为 `true`，在控制台可以看到类似的警告信息：

```bash
[LIBUILD:ESBUILD_WARN] Ignoring this import because "other-package/dist/index.css" was marked as having no side effects
```

这时候就可以使用这个配置项，手动配置模块的`"sideEffects"`，配置支持正则和函数形式。

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    sideEffects: [/\.css$/],
    // or
    // sideEffects: (filePath, isExternal) => /\.css$/.test(filePath),
  },
});
```

:::tip
添加此配置后，打包时将不会再读取 package.json 里的 `"sideEffects"` 字段。
:::

## sourceDir

指定构建的源码目录,默认为 `src`，用于在 `bundleless` 构建时基于源码目录结构生成对应的产物目录。
等同于[esbuild.outbase](https://esbuild.github.io/api/#outbase)。

- 类型： `string`
- 默认值： `src`

## sourceMap

控制 sourceMap 如何生成。

- 类型： `boolean | 'inline' | 'external'`
- 默认值： `false`

## sourceType

:::warning
已废弃，此配置不会产生任何影响。
:::

设置源码的格式。默认情况下，会将源码作为 EsModule 进行处理。当源码使用的是 CommonJS 的时候，需要设置 `commonjs`。

- 类型：`'commonjs' | 'module'`
- 默认值：`'module'`

## splitting

是否开启代码分割。
仅支持 [format: 'esm'](#format-esm) 和 [format: 'cjs'](#format-cjs)，查看[esbuild.splitting](https://esbuild.github.io/api/#splitting)了解更多。

- 类型： `boolean`
- 默认值： `false`

## style

配置样式相关的配置。

## style.less

less 相关配置。

## style.less.lessOptions

详细配置参考 [less](https://less.bootcss.com/usage/#less-options)。

- 类型： `object`
- 默认值： `{ javascriptEnabled: true }`

## style.less.additionalData

在入口文件起始添加 `Less` 代码。

- 类型： `string`
- 默认值： `undefined`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    style: {
      less: {
        additionalData: `@base-color: #c6538c;`,
      },
    },
  },
});
```

## style.less.implementation

配置 `Less` 使用的实现库，在不指定的情况下，使用的内置版本是 `4.1.3`。

- 类型： `string | object`
- 默认值： `undefined`

设置 `object` 类型时，可以指定 `Less` 的实现库。

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    style: {
      less: {
        implementation: require('less'),
      },
    },
  },
});
```

`string` 类型时，指定 `Less` 的实现库的路径

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    style: {
      less: {
        implementation: require.resolve('less'),
      },
    },
  },
});
```

## sass

Sass 相关配置。

## style.sass.sassOptions

详细配置参考 [node-sass](https://github.com/sass/node-sass#options)

- 类型： `object`
- 默认值： `{}`

## style.sass.additionalData

在入口文件起始添加 `Sass` 代码。

- 类型： `string | Function`
- 默认值： `undefined`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    style: {
      sass: {
        additionalData: `$base-color: #c6538c;
          $border-dark: rgba($base-color, 0.88);`,
      },
    },
  },
});
```

## style.sass.implementation

配置 `Sass` 使用的实现库，在不指定的情况下，使用的内置版本是 `1.54.4`。

- 类型： `string | object`
- 默认值： `undefined`

设置为 `object` 类型时，可以指定 `Sass` 的实现库。

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    style: {
      sass: {
        implementation: require('sass'),
      },
    },
  },
});
```

`string` 类型时，指定 `Sass` 的实现库的路径

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    style: {
      sass: {
        implementation: require.resolve('sass'),
      },
    },
  },
});
```

## style.postcss

用于配置 PostCSS 的选项，传入的值会与默认配置通过 `Object.assign` 合并。注意 `Object.assign` 是浅拷贝，因此会完全覆盖内置的 plugins 数组。

详细配置请查看 [PostCSS](https://github.com/postcss/postcss#options)。

- 类型：

```ts
type PostcssOptions = {
  processOptions?: ProcessOptions;
  plugins?: AcceptedPlugin[];
};
```

- 默认值：

```ts
const defaultConfig = {
  plugins: [
    // 以下插件默认启用
    require('postcss-flexbugs-fixes'),
    require('postcss-media-minmax'),
    require('postcss-nesting'),
    // 以下插件仅在 target 为 `es5` 时启用
    require('postcss-custom-properties'),
    require('postcss-initial'),
    require('postcss-page-break'),
    require('postcss-font-variant'),
  ],
};
```

- 示例：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    style: {
      postcss: {
        plugins: [yourPostCSSPlugin],
      },
    },
  },
});
```

## style.inject

配置打包模式下是否将 CSS 样式插入到 JavaScript 代码中。

- 类型： `boolean`
- 默认值： `false`

将 `inject` 设置为 `true` 来开启此功能：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    style: {
      inject: true,
    },
  },
});
```

开启后，你会看到源码中引用的 CSS 代码被包含在了打包后的 JS 产物中。

例如，你在源码里写了 `import './index.scss'`，那么在产物中你会看到以下代码：

```js title="dist/index.js"
// node_modules/style-inject/dist/style-inject.es.js
function styleInject(css, ref) {
  // ...
}
var style_inject_es_default = styleInject;

// src/index.scss
var css_248z = '.body {\n  color: black;\n}';
style_inject_es_default(css_248z);
```

:::tip

开启 `inject` 后，你需要注意以下几点：

- CSS 文件中的 `@import` 不会被处理。如果你的 CSS 文件中有 `@import` ，那么你需要在 JS 文件中手动引入 CSS 文件（less,scss 文件不需要，因为它们会有预处理）。
- 需要考虑 `sideEffects` 的影响。默认情况下，我们的构建器会认为 CSS 是有副作用的，如果你的项目中或者三方包的 package.json 设置了 `sideEffects` 字段并且没有包含此 CSS 文件，那么你将会得到一个警告：

```shell
[LIBUILD:ESBUILD_WARN] Ignoring this import because "src/index.scss" was marked as having no side effects by plugin "libuild:adapter"
```

此时可以通过配置 [sideEffects](#sideeffects) 来解决。

:::

## style.autoModules

根据文件名自动启用 CSS Modules。

- 类型： `boolean | RegExp`
- 默认值： `true`

`true` : 为以 `.module.css` `.module.less` `.module.scss` `.module.sass` 文件名结尾的样式文件启用 CSS Modules。

`false` : 禁用 CSS Modules.

`RegExp` : 为匹配正则条件的所有文件启用 CSS Modules.

## style.modules

CSS Modules 配置。

- 类型： `object`
- 默认值： `{}`

一个常用的配置是 `localsConvention`，它可以改变 CSS Modules 的类名生成规则。

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    style: {
      modules: {
        localsConvention: 'camelCaseOnly',
      },
    },
  },
});
```

对于以下样式：

```css
.box-title {
  color: red;
}
```

你可以使用 `styles.boxTitle` 来访问。

详细配置查看 [postcss-modules](https://github.com/madyankin/postcss-modules#usage)

## style.tailwindcss

用于修改 [Tailwind CSS](https://tailwindcss.com/docs/configuration) 的配置项。

- 类型： `object | Function`
- 默认值：

```js title="modern.config.ts"
const tailwind = {
  content: ['./src/**/*.{js,jsx,ts,tsx}', './config/html/**/*.{html,ejs,hbs}'],
};
```

### 启用 Tailwind CSS

在使用 `style.tailwindcss` 之前，你需要启用 Modern.js Module 的 Tailwind CSS 插件。

请阅读[「使用 Tailwind CSS」](/guide/best-practices/use-tailwindcss.html) 章节来了解开启方式。

### 类型

值为 `object` 类型时，与默认配置通过 `Object.assign` 合并。

值为 `Function` 类型时，函数返回的对象与默认配置通过 `Object.assign` 合并。

其他的使用方式和 Tailwind CSS 一致: [快速传送门](https://tailwindcss.com/docs/configuration)。

### 注意事项

注意：

- 如果你同时使用了 `tailwind.config.{ts,js}` 文件和 `tools.tailwindcss` 选项，那么 `tools.tailwindcss` 定义的配置会优先生效，并覆盖 `tailwind.config.{ts,js}` 中定义的内容。
- 如果你同时使用了 `designSystem` 配置项，那么 Tailwind CSS 的 `theme` 配置将会被 `designSystem` 的值所覆盖。

其他配置的使用方式与 Tailwind CSS 官方用法一致，请参考 [tailwindcss - Configuration](https://tailwindcss.com/docs/configuration)。

## target

`target` 用于为生成的 JavaScript 代码设置目标环境。它让 Modern.js Module 将目标环境无法识别的 JavaScript 语法转换为在这些环境中可用的低版本 JavaScript 语法。

- 类型：

```ts
type Target =
  | 'es5'
  | 'es6'
  | 'es2015'
  | 'es2016'
  | 'es2017'
  | 'es2018'
  | 'es2019'
  | 'es2020'
  | 'es2021'
  | 'es2022'
  | 'esnext';
```

- 默认值： `'es6'`

例如，将代码编译到 `es5` 语法：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    target: 'es5',
  },
});
```

## transformImport

提供与 babel-plugin-import 等价的能力和配置，基于 SWC 实现，使用此配置，将会使用 SWC 对代码进行转换。

- 类型：`object[]`
- 默认值：`[]`

数组元素为一个 babel-plugin-import 的配置对象。配置对象可以参考 [options](https://github.com/umijs/babel-plugin-import#options)。

使用示例：

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    transformImport: [
      // babel-plugin-import 的 options 配置
      {
        libraryName: 'foo',
        style: true,
      },
    ],
  },
});
```

参考[「Import 插件——注意事项」](plugins/official-list/plugin-import.html#注意事项)

## transformLodash

是否模块化 [lodash](https://www.npmjs.com/package/lodash) 的导入，删除未使用的 lodash 模块，从而减少 lodash 代码体积。这项优化基于 [babel-plugin-lodash](https://www.npmjs.com/package/babel-plugin-lodash) 和 [swc-plugin-lodash](https://github.com/web-infra-dev/swc-plugins/tree/main/crates/plugin_lodash) 实现。
使用此配置，将会使用 SWC 对代码进行转换。

- 类型：`boolean`
- 默认值：`false`

当开启此选项时，Modern.js Module 会自动将 lodash 的代码引用指向子路径。

比如：

```ts title="input.js"
import _ from 'lodash';
import { add } from 'lodash/fp';

const addOne = add(1);
_.map([1, 2, 3], addOne);
```

转换后的代码：

```ts title="output.js"
import _add from 'lodash/fp/add';
import _map from 'lodash/map';

const addOne = _add(1);
_map([1, 2, 3], addOne);
```

## tsconfig

TypeScript 配置文件的路径。

- 类型： `string`
- 默认值： `tsconfig.json`
- 版本： `>=MAJOR_VERSION.36.0`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    tsconfig: 'tsconfig.build.json',
  },
});
```

## umdGlobals

指定 UMD 产物外部导入的全局变量。

- 类型： `Record<string, string>`
- 默认值： `{}`

```ts title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    umdGlobals: {
      react: 'React',
      'react-dom': 'ReactDOM',
    },
  },
});
```

此时，`react` 和 `react-dom` 会被看做是外部导入的全局变量，不会被打包进 UMD 产物中，而是通过 `global.React` 和 `global.ReactDOM` 的方式进行访问。

## umdModuleName

指定 UMD 产物的模块名。

- 类型： `string | Function`
- 默认值： `name => name`

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    format: 'umd',
    umdModuleName: 'myLib',
  },
});
```

此时 UMD 产物会去挂载到 `global.myLib` 上。

:::tip

- 需要遵守 UMD 规范，UMD 产物的模块名不能和全局变量名冲突。
- 模块名会被转换为驼峰命名，如 `my-lib` 会被转换为 `myLib`，可参考[toIdentifier](https://github.com/babel/babel/blob/main/packages/babel-types/src/converters/toIdentifier.ts)。

:::

同时函数形式可以接收一个参数，为当前打包文件的输出路径

```js title="modern.config.ts"
export default defineConfig({
  buildConfig: {
    format: 'umd',
    umdModuleName: path => {
      if (path.includes('index')) {
        return 'myLib';
      } else {
        return 'myLib2';
      }
    },
  },
});
```
