# 命令行接口

Rollup 通常应该从命令行使用。你可以提供一个可选的 Rollup 配置文件,以简化命令行使用并启用高级 Rollup 功能。

# 配置文件

Rollup 配置文件是可选的,但它们非常强大和方便,因此推荐使用。配置文件是一个 ES 模块,它导出一个默认对象,其中包含所需的选项:

export default {
	input: 'src/main.js',
	output: {
		file: 'bundle.js',
		format: 'cjs'
	}
};

通常,它被称为 rollup.config.js 或 rollup.config.mjs,并位于项目的根目录中。除非使用 --configPlugin 或 --bundleConfigAsCjs 选项,否则 Rollup 将直接使用 Node 导入该文件。请注意,使用原生 Node ES 模块时存在一些注意事项,因为 Rollup 将遵循 Node ESM 语义。

如果你想使用 require 和 module.exports 编写 CommonJS 模块的配置文件,你应该将文件扩展名更改为 .cjs。

你也可以使用其他语言编写配置文件,比如 TypeScript。为此,安装相应的 Rollup 插件,例如 @rollup/plugin-typescript,并使用 --configPlugin 选项:

rollup --config rollup.config.ts --configPlugin typescript

使用 --configPlugin 选项将始终强制将你的配置文件先转换为 CommonJS 格式。同时,查看 Config Intellisense 以获取在配置文件中使用 TypeScript 类型定义的更多方法。

配置文件支持下面列出的选项。有关每个选项的详细信息,请参阅选项大全:

// rollup.config.js

// 可以是数组(即多个输入源)
export default {
	// 核心输入选项
	external,
	input, // 有条件地需要
	plugins,

	// 进阶输入选项
	cache,
	onwarn,
	preserveEntrySignatures,
	strictDeprecations,

	// 危险区域
	acorn,
	acornInjectPlugins,
	context,
	moduleContext,
	preserveSymlinks,
	shimMissingExports,
	treeshake,

	// 实验性
	experimentalCacheExpiry,
	experimentalLogSideEffects,
	perf,

	// 必需(可以是数组,用于描述多个输出)
	output: {
		// 核心输出选项
		dir,
		file,
		format,
		globals,
		name,
		plugins,

		// 进阶输出选项
		assetFileNames,
		banner,
		chunkFileNames,
		compact,
		entryFileNames,
		extend,
		footer,
		hoistTransitiveImports,
		inlineDynamicImports,
		interop,
		intro,
		manualChunks,
		minifyInternalExports,
		outro,
		paths,
		preserveModules,
		preserveModulesRoot,
		sourcemap,
		sourcemapBaseUrl,
		sourcemapExcludeSources,
		sourcemapFile,
		sourcemapIgnoreList,
		sourcemapPathTransform,
		validate,

		// 危险区域
		amd,
		esModule,
		exports,
		externalLiveBindings,
		freeze,
		indent,
		namespaceToStringTag,
		noConflict,
		preferConst,
		sanitizeFileName,
		strict,
		systemNullSetters,

		// 实验性
		experimentalMinChunkSize
	},

	watch: {
		buildDelay,
		chokidar,
		clearScreen,
		skipWrite,
		exclude,
		include
	}
};

你可以从配置文件中导出一个数组,以便一次从多个不相关的输入进行打包,即使在监视模式下也可以。要使用相同的输入打出不同的包,你需要为每个输入提供一个输出选项数组:

// rollup.config.js (building more than one bundle)

export default [
	{
		input: 'main-a.js',
		output: {
			file: 'dist/bundle-a.js',
			format: 'cjs'
		}
	},
	{
		input: 'main-b.js',
		output: [
			{
				file: 'dist/bundle-b1.js',
				format: 'cjs'
			},
			{
				file: 'dist/bundle-b2.js',
				format: 'es'
			}
		]
	}
];

如果你想异步创建配置文件,Rollup 也可以处理解析为对象或数组的 Promise。

// rollup.config.js
import fetch from 'node-fetch';

export default fetch('/some-remote-service-which-returns-actual-config');

类似地,你也可以这样做:

// rollup.config.js (Promise 解析为数组)
export default Promise.all([fetch('get-config-1'), fetch('get-config-2')]);

要使用配置文件来运行 Rollup,请传递 --config 或 -c 标志:

# 向 Rollup 传递自定义配置文件位置
rollup --config my.config.js

# 如果你没有传递文件名,Rollup 将会尝试
# 按照以下顺序加载配置文件:
# rollup.config.mjs -> rollup.config.cjs -> rollup.config.js
rollup --config

你还可以导出一个返回任何上述配置格式的函数。该函数将传递当前的命令行参数,以便你可以动态地调整你的配置以遵循例如 --silent。如果你使用 config 作为前缀定义自己的命令行选项,你甚至可以自定义它们:

// rollup.config.js
import defaultConfig from './rollup.default.config.js';
import debugConfig from './rollup.debug.config.js';

export default commandLineArgs => {
	if (commandLineArgs.configDebug === true) {
		return debugConfig;
	}
	return defaultConfig;
};

如果你现在运行 rollup --config --configDebug,将使用调试配置。

默认情况下,命令行参数将始终覆盖从配置文件中导出的相应值。如果你想更改这种行为,可以通过从 commandLineArgs 对象中删除它们来让 Rollup 忽略命令行参数:

// rollup.config.js
export default commandLineArgs => {
  const inputBase = commandLineArgs.input || 'main.js';

  // 这会使 Rollup 忽略 CLI 参数
  delete commandLineArgs.input;
  return {
    input: 'src/entries/' + inputBase,
    output: { ... }
  }
}

# 填写配置时的智能提示

由于 Rollup 随附了 TypeScript 类型定义,因此你可以使用 JSDoc 类型提示来利用你的 IDE 的智能感知功能:

// rollup.config.js
/**
 * @type {import('rollup').RollupOptions}
 */
const config = {
	/* 你的配置 */
};
export default config;

或者,你可以使用 defineConfig 辅助函数,它应该提供无需 JSDoc 注释即可使用智能感知的功能:

// rollup.config.js
import { defineConfig } from 'rollup';

export default defineConfig({
	/* 你的配置 */
});

除了 RollupOptions 和封装了该类型的 defineConfig 辅助函数之外,以下类型也可能会很有用:

  • OutputOptions:配置文件的 output 部分
  • Plugin:提供 name 和一些钩子的插件对象。所有钩子都是完全类型化的,以帮助插件开发。
  • PluginImpl:将选项对象映射到插件对象的函数。大多数公共的 Rollup 插件都遵循这种模式。

你还可以通过 --configPlugin 选项直接使用 TypeScript 编写配置文件。使用 TypeScript,你可以直接导入 RollupOptions 类型:

import type { RollupOptions } from 'rollup';

const config: RollupOptions = {
	/* 你的配置 */
};
export default config;

# 与 JavaScript API 的差异

虽然配置文件提供了一种简单的配置 Rollup 的方式,但它们也限制了 Rollup 可以被调用和配置的方式。特别是如果你正在将 Rollup 嵌入到另一个构建工具中,或者想将其集成到更高级构建流程中,直接从脚本中以编程方式调用 Rollup 可能更好。

如果你想在某个时候从配置文件切换到使用 JavaScript API,则需要了解一些重要的差异:

  • 当使用 JavaScript API 时,传递给 rollup.rollup 的配置必须是一个对象,不能被包装在 Promise 或函数中。
  • 你不能再使用配置数组。相反,你应该为每个 inputOptions 集运行一次 rollup.rollup。
  • output 选项将被忽略。相反,你应该为每个 outputOptions 集运行一次 bundle.generate(outputOptions) 或 bundle.write(outputOptions)。

# 从一个 NPM 包加载配置

为了实现互操作性,Rollup 还支持从安装到 node_modules 中的包中加载配置文件:

# 这将首先尝试加载包 "rollup-config-my-special-config"
# 如果失败,则尝试加载 "my-special-config"
rollup --config node:my-special-config

# 使用原生 Node ES 模块时的注意事项

特别是在从旧版本 Rollup 升级时,当使用原生 ES 模块作为配置文件时,有一些需要注意的事项。

# 获取当前目录

对于 CommonJS 文件,人们经常使用 __dirname 访问当前目录并将相对路径解析为绝对路径。这在原生 ES 模块中不被支持。相反,我们建议使用以下方法 (例如生成外部模块的绝对 id):

// rollup.config.js
import { fileURLToPath } from 'node:url'

export default {
  ...,
  // 为 <currentdir>/src/some-file.js 生成绝对路径
  external: [fileURLToPath(new URL('src/some-file.js', import.meta.url))]
};

# 导入 package.json

导入你的 package 文件可能很有用,例如自动将你的依赖项标记为 “external”。根据你的 Node 版本,有不同的方法来实现此目的:

  • 对于 Node 17.5+,你可以使用导入断言

    import pkg from './package.json' assert { type: 'json' };
    
    export default {
    	// Mark package dependencies as "external". Rest of configuration
    	// omitted.
    	external: Object.keys(pkg.dependencies)
    };
    
  • 对于旧一些的 Node 版本,你可以使用 createRequire

    import { createRequire } from 'node:module';
    const require = createRequire(import.meta.url);
    const pkg = require('./package.json');
    
    // ...
    
  • 或者直接从磁盘读取并解析其内容

    // rollup.config.mjs
    import { readFileSync } from 'node:fs';
    
    // 使用 import.meta.url 可以使路径相对于当前源文件而不是 process.cwd()。
    // 更多信息参见:
    // https://nodejs.org/docs/latest-v16.x/api/esm.html#importmetaurl
    const packageJson = JSON.parse(
    	readFileSync(new URL('./package.json', import.meta.url))
    );
    
    // ...
    

# 命令行标志

许多选项都有等效的命令行标志。在这些情况下,如果你正在使用配置文件,则此处传递的任何参数都将覆盖配置文件。以下是所有支持的选项列表:

-c, --config <filename>     使用此配置文件
														(如果使用参数但未指定值,则默认为 rollup.config.js)
-d, --dir <dirname>         用于块的目录(如果不存在,则打印到 stdout)
-e, --external <ids>        排除模块 ID 的逗号分隔列表
-f, --format <format>       输出类型(amd、cjs、es、iife、umd、system)
-g, --globals <pairs>       `moduleID:Global` 对的逗号分隔列表
-h, --help                  显示此帮助消息
-i, --input <filename>      输入(替代 <entry file>)
-m, --sourcemap             生成源映射(`-m inline` 为内联映射)
-n, --name <name>           UMD 导出的名称
-o, --file <output>         单个输出文件(如果不存在,则打印到 stdout)
-p, --plugin <plugin>       使用指定的插件(可重复)
-v, --version               显示版本号
-w, --watch                 监视产物文件并在更改时重新构建
--amd.autoId                基于块名称生成 AMD ID
--amd.basePath <prefix>     要预先添加到自动生成的 AMD ID 的路径
--amd.define <name>         在 `define` 位置使用的函数
--amd.forceJsExtensionForImports 在 AMD 导入中使用 `.js` 扩展名
--amd.id <id>               AMD 模块的 ID(默认为匿名)
--assetFileNames <pattern>  发布资源的名称模式
--banner <text>             在产物顶部插入的代码(位于包装器之外)
--chunkFileNames <pattern>  发布次要块的名称模式
--compact                   缩小包装器代码
--context <variable>        指定顶级 `this` 值
--no-dynamicImportInCjs     将外部动态 CommonJS 导入编写为 require
--entryFileNames <pattern>  发布入口块的名称模式
--environment <values>      传递给配置文件的设置(请参阅示例)
--no-esModule               不添加 __esModule 属性
--exports <mode>            指定导出模式(auto、default、named、none)
--extend                    扩展由 --name 定义的全局变量
--no-externalImportAssertions 在 "es" 输出中省略导入断言
--no-externalLiveBindings   不生成支持实时绑定的代码
--failAfterWarnings         如果生成的构建产生警告,则退出并显示错误
--footer <text>             在产物底部插入的代码(位于包装器之外)
--no-freeze                 不冻结命名空间对象
--generatedCode <preset>    使用哪些代码特性(es5/es2015)
--generatedCode.arrowFunctions 在生成的代码中使用箭头函数
--generatedCode.constBindings 在生成的代码中使用 "const"
--generatedCode.objectShorthand 在生成的代码中使用简写属性
--no-generatedCode.reservedNamesAsProps 始终引用保留名称作为 props
--generatedCode.symbols     在生成的代码中使用符号
--no-hoistTransitiveImports 不将中转导入提升到入口块中
--no-indent                 不缩进结果
--inlineDynamicImports      使用动态导入时创建单次打包
--no-interop                不包括交互操作块
--intro <text>              在产物顶部插入的代码(位于包装器内部)
--no-makeAbsoluteExternalsRelative 不规范化外部导入
--maxParallelFileOps <value> 并行读取的文件数
--minifyInternalExports     强制或禁用内部导出的缩小
--noConflict                为 UMD 全局生成 noConflict 方法
--outro <text>              在产物底部插入的代码(位于包装器内部)
--perf                      显示性能计时
--no-preserveEntrySignatures 避免入口点的门面块
--preserveModules           保留模块结构
--preserveModulesRoot       将保留的模块放置在根路径下的此路径下
--preserveSymlinks          解析文件时不要跟随符号链接
--no-sanitizeFileName       不要替换文件名中的无效字符
--shimMissingExports        为丢失的导出创建卡扣变量
--silent                    不打印警告
--sourcemapBaseUrl <url>    使用给定的基本 URL 发出绝对源映射 URL
--sourcemapExcludeSources   在源映射中不包括源代码
--sourcemapFile <file>      指定源映射的包位置
--stdin=ext                 指定用于标准输入的文件扩展名
--no-stdin                  不要从 stdin 读取 "-"
--no-strict                 不在生成的模块中发出 `"use strict";`
--strictDeprecations        抛出有关不推荐使用的功能的错误
--no-systemNullSetters      不要将空的 SystemJS setter 替换为 `null`
--no-treeshake              禁用除屑优化
--no-treeshake.annotations 忽略纯调用注释
--treeshake.correctVarValueBeforeDeclaration 在声明之前将变量取消优化
--treeshake.manualPureFunctions <names> 手动将函数声明为纯函数
--no-treeshake.moduleSideEffects 假设模块没有副作用
--no-treeshake.propertyReadSideEffects 忽略属性访问副作用
--no-treeshake.tryCatchDeoptimization 不要关闭 try-catch-tree-shaking
--no-treeshake.unknownGlobalSideEffects 假设未知的全局变量不会抛出异常
--validate                  验证输出
--waitForBundleInput        等待打包输入文件
--watch.buildDelay <number> 节流观察重建
--no-watch.clearScreen      重建时不要清除屏幕
--watch.exclude <files>     排除要观察的文件
--watch.include <files>     限制观察到指定文件
--watch.onBundleEnd <cmd>   在 "BUNDLE_END" 事件上运行的 Shell 命令
--watch.onBundleStart <cmd> 在 "BUNDLE_START" 事件上运行的 Shell 命令
--watch.onEnd <cmd>         在 "END" 事件上运行的 Shell 命令
--watch.onError <cmd>       在 "ERROR" 事件上运行的 Shell 命令
--watch.onStart <cmd>       在 "START" 事件上运行的 Shell 命令
--watch.skipWrite           在监视时不要将文件写入磁盘

以下标志仅通过命令行界面可用。所有其他标志都对应并覆盖其配置文件等效项,请参阅选项大列表获取详细信息。

# -h/--help

打印帮助文档。

# -p <plugin>,--plugin <plugin>

使用指定的插件。在此处指定插件的方式有多种:

  • 通过相对路径:

    rollup -i input.js -f es -p ./my-plugin.js
    

    文件应该导出一个返回插件对象的函数。

  • 通过在本地或全局的 node_modules 文件夹中安装的插件的名称:

    rollup -i input.js -f es -p @rollup/plugin-node-resolve
    

    如果插件名称不以 rollup-plugin- 或 @rollup/plugin- 开头,Rollup 将自动尝试添加这些前缀:

    rollup -i input.js -f es -p node-resolve
    
  • 通过一个内联实现:

    rollup -i input.js -f es -p '{transform: (c, i) => `/* ${JSON.stringify(i)} */\n${c}`}'
    

如果你想加载多个插件,可以重复使用该选项或提供逗号分隔的名称列表:

rollup -i input.js -f es -p node-resolve -p commonjs,json

默认情况下,插件函数将不带参数调用以创建插件。但是,你也可以传递自定义参数:

rollup -i input.js -f es -p 'terser={output: {beautify: true, indent_level: 2}}'

# --configPlugin <plugin>

允许指定 Rollup 插件来转译或控制解析配置文件。主要好处是可以使用非 JavaScript 的配置文件。例如,如果你安装了 @rollup/plugin-typescript,则以下内容将允许你使用 TypeScript 编写配置文件:

rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript

对于 TypeScript,请确保在 tsconfig.json 的 include 路径中包含 Rollup 配置文件。例如:

"include": ["src/**/*", "rollup.config.ts"],

此选项支持与 --plugin 选项相同的语法,即你可以多次指定该选项,可以省略 @rollup/plugin- 前缀,只需编写 typescript,并可以通过 ={...} 指定插件选项。

使用此选项将使 Rollup 首先将你的配置文件转译为 ES 模块,然后再执行它。如果要转译为 CommonJS,请还传递 --bundleConfigAsCjs 选项。

# --bundleConfigAsCjs

此选项将强制将你的配置转译为 CommonJS。

这允许你在配置中使用 CommonJS 常用的变量/方法,例如 __dirname 或 require.resolve,即使配置本身是作为 ES 模块编写的。

# -v/--version

打印已安装的版本号。

# -w/--watch

当其源文件在磁盘上发生更改时重新打包。

注意:在观察模式下,Rollup 的命令行界面将设置 ROLLUP_WATCH 环境变量为 "true",其他进程可以进行检查。插件应该检查 this.meta.watchMode,它独立于命令行界面。

# --silent

不在控制台上打印警告信息。如果你的配置文件包含一个 onwarn 处理程序,该处理程序仍然会被调用。要手动防止这种情况,你可以按照配置文件结尾处所述的方式在配置文件中访问命令行选项。

# --failAfterWarnings

一旦构建完成,如果出现任何警告,则以错误退出构建。

# --environment <values>

通过 process.ENV 传递其他设置到配置文件。

rollup -c --environment INCLUDE_DEPS,BUILD:production

将设置 process.env.INCLUDE_DEPS === 'true' 和 process.env.BUILD === 'production'。你可以多次使用此选项。在这种情况下,后续设置的变量将覆盖先前的定义。这使你可以覆盖 package.json 脚本中的环境变量:

json

{
	"scripts": {
		"build": "rollup -c --environment INCLUDE_DEPS,BUILD:production"
	}
}

如果通过以下方式调用此脚本:

npm run build -- --environment BUILD:development

则配置文件将接收到 process.env.INCLUDE_DEPS === 'true' 和 process.env.BUILD === 'development'。

# --waitForBundleInput

如果入口点文件中有一个文件不可用,这不会引发错误。相反,在开始构建之前,它将等待所有文件都存在。这在监视模式下特别有用,当 Rollup 正在使用另一个进程的输出时。

# --stdin=ext

在从 stdin 读取内容时指定虚拟文件扩展名。默认情况下,Rollup 将使用虚拟文件名 -,没有扩展名,用于从 stdin 读取的内容。但是,一些插件依赖于文件扩展名来确定是否处理文件。另请参见从 stdin 读取文件。

# --no-stdin

不要从 stdin 读取文件。设置此标志将防止将内容传输到 Rollup 并确保 Rollup 将 - 和 -.[ext] 解释为常规文件名,而不是将其解释为 stdin 的名称。另请参见从 stdin 读取文件。

# --watch.onStart <cmd>,--watch.onBundleStart <cmd>,--watch.onBundleEnd <cmd>,--watch.onEnd <cmd>,--watch.onError <cmd>

在监视模式下,为监视事件代码运行一个 shell 命令 <cmd>。另请参见 rollup.watch。

rollup -c --watch --watch.onEnd="node ./afterBuildScript.js"

# 从标准输入读取文件

当使用命令行界面时,Rollup 也可以从标准输入中读取内容:

echo "export const foo = 42;" | rollup --format cjs --file out.js

当该文件包含导入时,Rollup 将尝试相对于当前工作目录解析它们。当使用配置文件时,只有当入口点的文件名为 - 时,Rollup 才会使用 stdin 作为入口点。要从 stdin 读取非入口点文件,只需将其命名为 -,这是用于引用 stdin 的内部文件名。例如:

import foo from '-';

在任何文件中,都可以提示 Rollup 尝试从 stdin 读取导入的文件,并将默认导出分配给 foo。你可以向 Rollup 传递 --no-stdin CLI 标志,将 - 视为常规文件名。

由于某些插件依赖于文件扩展名来处理文件,你可以通过 --stdin=ext 指定 stdin 的文件扩展名,其中 ext 是所需的扩展名。在这种情况下,虚拟文件名将为 -.ext:

echo '{"foo": 42, "bar": "ok"}' | rollup --stdin=json -p json

JavaScript API 总是将 - 和 -.ext 视为常规文件名。

Last Updated: 6/14/2023, 8:56:23 AM