Rollup
是一个用于JavaScript
的模块打包工具,使用JavaScript
的ES6
版本中包含的新标准化代码模块格式,而不是以前的CommonJS
和AMD
等特殊解决方案。让你像ES 模块
一样,在所有场景获得原生支持,自由无缝地组合你最喜欢的库中最有用的个别函数…
系列文章:
一、安装使用
作为 全局命令行工具 使用
$ npm install --global rollup
二、基础示例
场景描述:利用ES MODULE
机制,封装了一个@js/sdk
包。其中,要求对于?.
类似语法,进行ES5
的编译处理。@js/sdk
具体要求如下:
sdk/src/index.js
导出如下:
export {
modelA,
modelB,
// ...
} from './zmini/index'
sdk/src/utils/util.js
等使用?.
语法文件,进行编译:
const resError = {
platform,
code: error?.code,
errorCode: error?.subCode,
message: error?.message
}
- 前期主要利用
bable
,进行构建,所以需要兼容bable
相关逻辑。历史package.json
核心如下:
{
"scripts": {
"build": "babel src -d lib" // 构建命令
},
"devDependencies": {
"@babel/cli": "^7.23.4", // babel 依赖
"@babel/core": "^7.23.5",
"@babel/preset-env": "^7.23.5"
}
}
1.安装依赖和文件配置
1.1 安装依赖
安装必要的依赖包:
$ npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-babel @rollup/plugin-terser @babel/core @babel/preset-env
@rollup/plugin-node-resolve
: 允许 Rollup 查找并打包node_modules
中的模块。@rollup/plugin-commonjs
: 使 Rollup 可以转换 CommonJS 模块为 ES6 模块。@rollup/plugin-babel
: 集成 Babel 以便处理现代 JavaScript 语法,并将其转换为支持更老的环境(如 Node.js 12+)的代码。@rollup/plugin-terser
: 用于压缩输出的代码,以减小打包后的体积。babel.config.js
: 配置 Babel,使其使用@babel/preset-env
来根据目标环境编译代码,并使用core-js
自动引入 polyfill 以支持可选链语法和其他现代 JavaScript 特性。
1.2 Rollup 配置文件
创建一个 rollup.config.js
文件,内容如下:
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import { terser } from '@rollup/plugin-terser';
// import terser from '@rollup/plugin-terser'; // 某些版本是默认导出
export default {
input: 'src/index.js', // 入口文件
output: [
// {
// file: 'lib/bundle.cjs.js', // CommonJS 输出
// format: 'cjs',
// sourcemap: true,
// },
{
file: 'lib/bundle.esm.js', // ES Module 输出
format: 'es',
sourcemap: true,
}
],
external: ['@js/base-sdk'], // 忽略package.json中的依赖,避免被打包到libs
plugins: [
resolve(), // 解析模块
commonjs(), // 处理 CommonJS 模块
babel({
babelHelpers: 'bundled',
exclude: 'node_modules/**', // 只编译我们的源码
presets: [
[
'@babel/preset-env',
{
targets: {
node: '12', // 确保支持 node 12+
},
useBuiltIns: 'usage',
corejs: 3, // 自动引入 polyfill
},
],
],
}),
terser() // 代码压缩
],
};
1.3 Babel 配置文件
创建一个 .babelrc
或 babel.config.js
文件配置Babel,确保编译目标支持较老的 Node.js 环境:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "12"
},
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
2.构建命令
在你的 sdk/package.json
中,更新 scripts
部分,使用 Rollup 构建你的包:
{
"type": "module",
// 第一种方式:使用 main 和 module 两个配置
// "main": "./lib/bundle.cjs.js", // CommonJS 入口
// "module": "./lib/bundle.esm.js", // ES Module 入口
// 第二种:只使用main —— 推荐这种
"main": "./lib/bundle.esm.js", // 入口配置ES Module
"scripts": {
"build": "rollup -c"
}
}
终端运行以下命令来构建你的 SDK 包:
$ npm run build
构建完成后,生成的文件将在 lib/
目录下,分别以 CommonJS 和 ES Module 格式输出。这些文件将兼容 Node.js 12 及更高版本。
三、常见问题
1. 想要在node 16
环境下,使用rollup
构建,请问我要如何处理?
异常如下:
lianpf@lianpf-PC:~/xxx/@js/sdk$ npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-babel @rollup/plugin-terser @babel/core @babel/preset-env
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'rollup@4.21.0',
npm WARN EBADENGINE required: { node: '>=18.0.0', npm: '>=8.0.0' },
npm WARN EBADENGINE current: { node: 'v16.17.1', npm: '8.15.0' }
npm WARN EBADENGINE }
added 63 packages, removed 4 packages, and changed 93 packages in 15s
20 packages are looking for funding
run `npm fund` for details
处理方式:
这个错误是由于你当前使用的 Node.js 版本 (v16.17.1) 和 Rollup 的最新版本 (4.21.0) 之间存在不兼容问题。Rollup 4.21.0 要求 Node.js 版本为 18.0.0 或更高版本,而你目前使用的版本是 16.17.1,因此出现了 EBADENGINE
警告。
解决方案:
升级 Node.js 版本
最简单的解决方法是升级你的 Node.js 版本到 18.0.0 或更高。你可以使用 n 或 nvm 来管理和切换 Node.js 版本。使用
n
工具升级:sudo npm install -g n sudo n stable
使用
nvm
工具升级:nvm install 18 nvm use 18
然后再次运行
npm install
来安装依赖。使用支持 Node.js 16 的 Rollup 版本
如果你无法升级 Node.js 版本(比如项目需要兼容 Node.js 16),你可以安装一个旧版本的 Rollup。比如,Rollup 3.x 支持 Node.js 16。执行以下命令安装较旧的 Rollup 版本:
npm install --save-dev rollup@3 @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-babel @rollup/plugin-terser @babel/core @babel/preset-env
2. @rollup/plugin-commonjs
主要处理什么语法?什么情况下,output才需要输出CommonJS?
@rollup/plugin-commonjs
插件主要处理CommonJS(CJS)
模块的语法,特别在Node.js
环境中。它使用require()
函数来同步地加载其他模块,并通过 module.exports
或exports
对象来导出模块的功能。
示例:
假设你有一个CommonJS
模块(math.js),它定义了一些数学函数并导出它们:
// math.js (CommonJS)
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = { add, subtract };
然后,你想在另一个使用 ES 模块语法的文件中导入这个 CommonJS 模块。但由于 Rollup 默认只理解 ES 模块,它无法直接解析 require() 调用。这就是 @rollup/plugin-commonjs 插件发挥作用的地方。它可以将 CommonJS 模块转换为 Rollup 可以理解的 ES 模块格式。
何时需要输出 CommonJS格式
(如 .cjs.js
),主要有以下几种情况:
背景:在
Node.js
中,版本12
才开始对ES 模块
有基础的支持
- 兼容性:某些库或应用程序(因为需要支持较旧的
Node.js版本
或特定环境)不支持ES 模块
。 - 生态系统支持:输出
CommonJS 格式
可确保你的库或应用程序,被基于CommonJS
的工具和构建系统(如:Node.js
包管理工具npm
)所消费。 - 性能考虑:在某些情况下,
CommonJS 模块
比ES 模块
加载得更快,因为它们通常使用同步的require()
调用。然而,在现代Node.js 版本
中通常差异很小,且随着ES 模块
性能的提升而逐渐消失。 - 外部使用场景:外部使用 CommonJS 模块的场景非常广泛,包括但不限于:
- Node.js 项目:在 Node.js 中,直到版本 12 才开始对 ES 模块有基本的支持,而 CommonJS 仍然是主流。
- 遗留代码库:许多旧的项目和库仍然使用 CommonJS,因为它们是在 ES 模块成为标准之前就开发的。
- 混合项目:在一些项目中,你可能需要同时支持 ES 模块和 CommonJS 模块,以便能够兼容不同的环境或工具链。
- npm 包:由于 npm 是 JavaScript 社区中最大的包注册表之一,并且许多包仍然使用 CommonJS,因此如果你正在开发一个 npm 包,并希望它能够被尽可能多的项目所使用,那么通常需要支持 CommonJS 格式。
3. 如何保持开发和构建文件目录一致,以便于调试和排查问题?
示例:
假设你的 src
目录结构如下:
src/
index.js
utils/
helper.js
components/
button.js
modal.js
在打包后,你的 lib
目录结构和src
保持一致:
lib/
index.js
utils/
helper.js
components/
button.js
modal.js
优化 rollup.config.js
:
dir
选项:在output
配置中使用dir
而不是file
,Rollup
会将输出的文件放在指定的目录中,而不是生成单一的文件preserveModules
:启用此选项,Rollup
将保留模块的原始结构,而不是将所有文件打包到一个文件中(每个模块会生成一个独立的文件preserveModulesRoot
:指定保留的模块目录的根目录。此例中,src
目录的层级结构会保持到lib
中
export default {
input: 'src/index.js', // 入口文件(可支持多个入口)
output: [
{
dir: 'lib', // 输出文件夹
format: 'es', // ES Module 输出
sourcemap: true,
preserveModules: true, // 保持模块结构
preserveModulesRoot: 'src', // 保持 src 目录结构
},
],
external: ['@js/base-sdk'], // 忽略package.json中的依赖,避免被打包到libs
plugins: [
// ...
],
};
总结
常用(最终)配置
待补充…
参考
最后, 希望大家早日实现:成为编程高手的伟大梦想!
欢迎交流~
本文版权归原作者曜灵所有!未经允许,严禁转载!对非法转载者, 原作者保留采用法律手段追究的权利!
若需转载,请联系微信公众号:连先生有猫病,可获取作者联系方式!