buildConfig

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

  • 类型:object | object[]
TIP

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

alias

  • 类型:Record<string, string> | Function
  • 默认值:{'@': 'src',}
TIP

对于 TypeScript 项目,只需要在 tsconfig.json 中配置 compilerOptions.paths, Modern.js Module 会自动识别 tsconfig.json 里的别名,因此不需要额外配置 alias 字段。

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

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

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

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

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

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,对应资源路径。

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 来避免资源内联:

modern.config.ts
export default defineConfig({
  buildConfig: {
    asset: {
      limit: 0,
    },
  },
});

asset.path

静态资源输出路径,会基于 outDir 进行输出。

  • 类型: string
  • 默认值: assets

asset.publicPath

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

  • 类型: string
  • 默认值: undefined
modern.config.ts
export default defineConfig({
  buildConfig: {
    asset: {
      publicPath: 'https://xxx/',
    },
  },
});

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

asset.svgr

打包时将 SVG 作为一个 React 组件处理,options 参考 svgr,另外还支持了 includeexclude 两个配置项,用于匹配需要处理的 SVG 文件。

  • 类型: boolean | object
  • 默认值: false

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

index.ts
// true
import Logo from './logo.svg';

export default () => <Logo />;

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

your-app-env.d.ts
declare module '*.svg' {
  const src: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
  export default src;
}
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' 时,你可以使用以下语法导入组件:

index.ts
import { ReactComponent } from './logo.svg';

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

autoExtension

根据 formattype 自动添加产物里 js 文件和类型描述文件的后缀。

  • 类型:boolean
  • 默认值:false
  • 版本:>=2.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关闭。

注意 noUselessIndex 规则会破坏此行为,你需要禁用此规则 如果你需要在 bundleless 使用此配置,请补齐 index,例如 utils 是一个文件夹, 你需要将 import * from './utils' 改写为 import * from './utils/index'

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

autoExternal

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

  • 类型: boolean | object
  • 默认值: true

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

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

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

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

autoExternal.dependencies

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

  • 类型: boolean
  • 默认值: true

autoExternal.peerDependencies

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

  • 类型: boolean
  • 默认值: true

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

interface BannerAndFooter {
  js?: string;
  css?: string;
  dts?: string;
}
  • 类型: BannerAndFooter
  • 默认值: {}
  • 版本: >=2.36.0

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

import { moduleTools, defineConfig } from '@edenx/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
modern.config.ts
export default defineConfig({
  buildConfig: {
    copy: {
      patterns: [{ from: './src/assets', to: '' }],
    },
  },
});

copy.patterns

  • 类型: CopyPattern[]
  • 默认值: []
interface CopyPattern {
  from: string;
  to?: string;
  context?: string;
  globOptions?: globby.GlobbyOptions;
}

copy.options

  • 类型:
type Options = {
  concurrency?: number;
  enableCopySync?: boolean;
};
  • 默认值: { concurrency: 100, enableCopySync: false }

  • concurrency: 指定并行执行多少个复制任务。

  • enableCopySync: 使用 fs.copySync,默认情况下 fs.copy

define

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

  • 类型: Record<string, string>
  • 默认值: {}

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

INFO

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

如果不需要自动序列化,可以通过配置 esbuildOptions 定义 alias 来实现。

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

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

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

env.d.ts
declare const YOUR_ADD_GLOBAL_VAR;

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

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

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

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

在执行 VERSION=1.0.0 modern build 的时候,转换为:

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

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

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

dts

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

  • 类型: false | object
  • 默认值:
{
  abortOnError: true,
  distPath: './',
  only: false,
}

dts.abortOnError

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

  • 类型:boolean
  • 默认值:true

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

modern.config.ts
export default defineConfig({
  buildConfig: {
    dts: {
      abortOnError: false,
    },
  },
});
WARNING

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

dts.distPath

类型文件的输出路径,基于 outDir 进行输出。

  • 类型: string
  • 默认值: ./

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

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

dts.enableTscBuild

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

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

当开启此选项时,为了满足构建需求,你必须显式地在 tsconfig.json 里设置 'declarationDir' 或者 'outDir',
如果你用的不是 TS >= 5.0 版本,你还需要显式地设置 'declaration' 和 'emitDeclarationOnly'。
  • 类型: boolean
  • 默认值: false
  • 版本: >2.43.0
modern.config.ts
export default defineConfig({
  buildConfig: {
    dts: {
      enableTscBuild: true,
    },
  },
});

dts.only

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

  • 类型: boolean
  • 默认值: false
modern.config.ts
export default defineConfig({
  buildConfig: {
    dts: {
      only: true,
    },
  },
});

dts.respectExternal

当设为 false 时,不会打包任何三方包类型,设为 true 时,会根据 externals 来决定是否需要打包三方类型。

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

  • 类型: boolean
  • 默认值: true
modern.config.ts
export default defineConfig({
  buildConfig: {
    dts: {
      respectExternal: false,
    },
  },
});

dts.tsconfigPath

废弃,使用 tsconfig 配置替代。

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

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

esbuildOptions

用于修改底层的 esbuild 配置

  • 类型: Function
  • 默认值: c => c

例如,我们需要修改生成文件的后缀:

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

例如,注册一个 esbuild 插件:

modern.config.ts
import { myEsbuildPlugin } from './myEsbuildPlugin';

export default defineConfig({
  buildConfig: {
    esbuildOptions: options => {
      options.plugins = [myEsbuildPlugin, ...options.plugins];
      return options;
    },
  },
});

在增加 esbuild 插件时,请注意你需要将插件加在 plugins 数组的头部,因为 Modern.js Module 内部也是通过一个 esbuild 插件介入到整个构建流程中去的,因此需要将自定义插件优先注册。

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

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

开启前:

./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
};

开启后:

./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 中。

  • 类型:
type Externals = (string | RegExp)[];
  • 默认值: []
  • 构建类型:仅支持 buildType: 'bundle'
  • 示例:
modern.config.ts
export default defineConfig({
  buildConfig: {
    // 避免打包 React
    externals: ['react'],
  },
});

banner 配置,用于在输出文件末尾添加注释。

format

用于设置 JavaScript 产物输出的格式,其中 iifeumd 只在 buildTypebundle 时生效。

  • 类型:'esm' | 'cjs' | 'iife' | 'umd'
  • 默认值:cjs

format: esm

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

  • 示例:
modern.config.ts
export default defineConfig({
  buildConfig: {
    format: 'esm',
  },
});

format: cjs

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

  • 示例:
modern.config.ts
export default defineConfig({
  buildConfig: {
    format: 'cjs',
  },
});

format: iife

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

  • 示例:
modern.config.ts
export default defineConfig({
  buildConfig: {
    format: 'iife',
  },
});

format: umd

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

  • 示例:
modern.config.ts
export default defineConfig({
  buildConfig: {
    format: 'umd',
  },
});

hooks

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

  • 类型:
type HookList = {
  name: string;
  apply: (compiler: ICompiler) => void;
  // 是否在 buildIn 钩子之后执行
  applyAfterBuiltIn?: boolean;
};
  • 默认值:[]

我们可以在 apply 方法里拿到 compiler 实例,修改其属性,以及在不同阶段执行自定义逻辑,对于 Hook 的详细介绍, 参考使用 Hook 介入构建流程

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

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

  • 类型:
type Input =
  | string[];
  | {
      [name: string]: string;
    }
  • 默认值:bundle 模式下默认为 ['src/index.ts']bundleless 模式下默认为 ['src']

数组用法:

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

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

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

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

bundleless 模式下,数组模式还支持使用 ! 来过滤部分文件:

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

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

对象用法:

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

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

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,则可以设置 jsxtransform

modern.config.ts
export default defineConfig({
  buildConfig: {
    jsx: 'transform',
  },
});
TIP

如果你不需要转换 JSX ,可以设置 jsxpreserve, 但此时请不要使用 swc 做代码转换。 关于 JSX Transform 的更多说明,可以参考以下链接:

loader

试验性功能

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

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

metafile

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

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

开启 metafile 生成:

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

在执行 build 构建后,产物目录下会生成 metafile-[xxx].json 文件,你可以通过 esbuild analyzebundle-buddy 等工具进行可视化分析。

minify

使用 esbuild 或者 terser 压缩代码,也可以传入 terserOptions

  • 类型: 'terser' | 'esbuild' | false | object
  • 默认值: false
modern.config.ts
export default defineConfig({
  buildConfig: {
    minify: {
      compress: {
        drop_console: true,
      },
    },
  },
});

outDir

指定构建的输出目录。

  • 类型: string
  • 默认值: ./dist
modern.config.ts
export default defineConfig({
  buildConfig: {
    outDir: './dist/esm',
  },
});

platform

默认生成用于 Node.js 环境下的代码,你也可以指定为 browser,会生成用于浏览器环境的代码。 查看esbuild.platform了解更多。

  • 类型: 'browser' | 'node'
  • 默认值: 'node'
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,视实际情况而定)

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

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

resolve

自定义模块解析选项

resolve.alias

基本用法和 alias 一致。

alias 的问题在于我们在 bundleless 场景下错误的处理了 Module ID 的情况:

import { createElement } from "react";

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

import { createElement } from "./react-native";

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

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

如果你需要此功能,请使用 resolve.alias

在下一个大版本,resolve.alias 将会取代 alias

WARNING
  • 注意此配置不要与 alias 混用。
  • 注意此配置必须标注一个相对路径,例如 { "@": "./src" } 而非 { "@": "src"}

resolve.mainFields

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

  • 类型:string[]
  • 默认值:取决于platform
    • node: ['module', 'main']
    • browser: ['module', 'browser', 'main']
  • 版本:>=2.36.0

例如,我们想要先加载 js:source 字段:

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']
  • 版本:>=2.36.0

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

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

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

resolve.tsconfig

用于配置 enhanced-resolve 中的 tsconfig-paths-webpack-plugin,来支持解析 tsconfig.json 中的 alias 和嵌套 @ 别名冲突的问题。

  • 类型:
type Tsconfig = {
  configFile: string,
  references?: string[] | undefined,
};
  • 默认值: { configFile: config.tsconfig, references: undefined }
  • 版本:>=2.61.1
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, 需要注意的是 esm shims 只会在 platform 为 node 时注入,因为用到了 url 模块。

  • 类型: boolean
  • 默认值: false
  • 版本:>=2.38.0
modern.config.ts
export default defineConfig({
  buildConfig: {
    shims: true,
  },
});

sideEffects

配置模块的副作用

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

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

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

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

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

同时你又设置了 style.injecttrue,在控制台可以看到类似的警告信息:

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

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

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

  • 类型: string
  • 默认值: src

sourceMap

控制 sourceMap 如何生成。

  • 类型: boolean | 'inline' | 'external'
  • 默认值: false

sourceType

WARNING

已废弃,此配置不会产生任何影响。

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

  • 类型:'commonjs' | 'module'
  • 默认值:'module'

splitting

是否开启代码分割。 仅支持 format: 'esm'format: 'cjs',查看esbuild.splitting了解更多。

  • 类型: boolean
  • 默认值: false

style

配置样式相关的配置。

style.less

less 相关配置。

style.less.lessOptions

详细配置参考 less

  • 类型: object
  • 默认值: { javascriptEnabled: true }

style.less.additionalData

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

  • 类型: string
  • 默认值: undefined
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 的实现库。

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

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

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

sass

Sass 相关配置。

style.sass.sassOptions

详细配置参考 node-sass

  • 类型: object
  • 默认值: {}

style.sass.additionalData

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

  • 类型: string | Function
  • 默认值: undefined
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.5.4

  • 类型: string | object
  • 默认值: undefined

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

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

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

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

style.postcss

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

详细配置请查看 PostCSS

  • 类型:
type PostcssOptions = {
  processOptions?: ProcessOptions;
  plugins?: AcceptedPlugin[];
};
  • 默认值:
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'),
  ],
};
  • 示例:
modern.config.ts
export default defineConfig({
  buildConfig: {
    style: {
      postcss: {
        plugins: [yourPostCSSPlugin],
      },
    },
  },
});

style.inject

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

  • 类型: boolean
  • 默认值: false

inject 设置为 true 来开启此功能:

modern.config.ts
export default defineConfig({
  buildConfig: {
    style: {
      inject: true,
    },
  },
});

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

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

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 文件,那么你将会得到一个警告:
[LIBUILD:ESBUILD_WARN] Ignoring this import because "src/index.scss" was marked as having no side effects by plugin "libuild:adapter"

此时可以通过配置 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 的类名生成规则。

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

对于以下样式:

.box-title {
  color: red;
}

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

详细配置查看 postcss-modules

style.tailwindcss

用于修改 Tailwind CSS 的配置项。

  • 类型: object | Function
  • 默认值:
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」 章节来了解开启方式。

类型

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

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

其他的使用方式和 Tailwind CSS 一致: 快速传送门

注意事项

注意:

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

其他配置的使用方式与 Tailwind CSS 官方用法一致,请参考 tailwindcss - Configuration

target

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

  • 类型:
type Target =
  | 'es5'
  | 'es6'
  | 'es2015'
  | 'es2016'
  | 'es2017'
  | 'es2018'
  | 'es2019'
  | 'es2020'
  | 'es2021'
  | 'es2022'
  | 'esnext';
  • 默认值: 'es6'

例如,将代码编译到 es5 语法:

modern.config.ts
export default defineConfig({
  buildConfig: {
    target: 'es5',
  },
});

transformImport

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

  • 类型:object[]
  • 默认值:[]

数组元素为一个 babel-plugin-import 的配置对象。配置对象可以参考 options

使用示例:

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

参考「Import 插件——注意事项」

transformLodash

是否模块化 lodash 的导入,删除未使用的 lodash 模块,从而减少 lodash 代码体积。这项优化基于 babel-plugin-lodashswc-plugin-lodash 实现。 使用此配置,将会使用 SWC 对代码进行转换。

  • 类型:boolean
  • 默认值:false

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

比如:

input.js
import _ from 'lodash';
import { add } from 'lodash/fp';

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

转换后的代码:

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
  • 版本: >=2.36.0
modern.config.ts
export default defineConfig({
  buildConfig: {
    tsconfig: 'tsconfig.build.json',
  },
});

umdGlobals

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

  • 类型: Record<string, string>
  • 默认值: {}
modern.config.ts
export default defineConfig({
  buildConfig: {
    umdGlobals: {
      react: 'React',
      'react-dom': 'ReactDOM',
    },
  },
});

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

umdModuleName

指定 UMD 产物的模块名。

  • 类型: string | Function
  • 默认值: name => name
modern.config.ts
export default defineConfig({
  buildConfig: {
    format: 'umd',
    umdModuleName: 'myLib',
  },
});

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

TIP
  • 需要遵守 UMD 规范,UMD 产物的模块名不能和全局变量名冲突。
  • 模块名会被转换为驼峰命名,如 my-lib 会被转换为 myLib,可参考toIdentifier

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

modern.config.ts
export default defineConfig({
  buildConfig: {
    format: 'umd',
    umdModuleName: path => {
      if (path.includes('index')) {
        return 'myLib';
      } else {
        return 'myLib2';
      }
    },
  },
});
```import { aliases } from '../../../../../../toolkit/utils/dist/compiled/browserslist';
import { createElement } from 'react';