背景
需求是我们有两个库需要进行打包、因为两个库的打包配置都一样、我们是否有办法不需要在每个库里面创建一份rollup.config.js、然后就是尽可能的定制化强一些、因为有可能后面有的打包规则对因为库的不一样而动态起来!
目录结构
---build
---build.js
---bundles.js
---packages
---core
---src
---index.ts
---icon
---src
---index.ts
---babel.config.js
1、初始化项目
2、安装必须依赖
yarn add @rollup/plugin-babel @rollup/plugin-node-resolve @rollup/plugin-commonjs @babel/core @babel/preset-env -D
3、package.json
{
"name": "rollup-monorepo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "yarn build:js", // 指定打包某个包 yarn build core
"build:js": "node ./build/build.js --mode", // 执行打包所有包
"dev":"node ./build/build.js --watch" // 热更新、启动后监听文件变动、而执行打包
},
"devDependencies": {
"@babel/core": "^7.17.8",
"@babel/preset-env": "^7.16.11",
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-commonjs": "^21.0.3",
"@rollup/plugin-node-resolve": "^13.1.3",
"rollup": "^2.70.1"
}
}
4、build/build.js和build/bundles.js
- build.js ```javascript // build.js ‘use strict’;
const rollup = require(‘rollup’); const { babel } = require(‘@rollup/plugin-babel’); const nodeResolve = require(‘@rollup/plugin-node-resolve’).default; const commonjs = require(‘@rollup/plugin-commonjs’); const chalk = require(‘chalk’); // 输出颜色插件 const argv = require(‘minimist’)(process.argv.slice(2)); const Bundles = require(‘./bundles’); const bundles = Bundles.bundles; const isWatchMode = argv.watch;
// 获取yarn build core ===> 指定打包core const buildMode = typeof argv.mode === ‘string’ && argv.mode.split(“ “) || bundles.map(i => i.entry);
function resolveEntryFork(resolvedEntry) {
return require.resolve(../packages/${resolvedEntry}/src/index.ts
);
}
// 后缀
const extensions = [‘.js’, ‘.ts’, ‘.tsx’, ‘.json’, ‘.node’]
function getRollupPlugins() { return [ nodeResolve({ preferBuiltins: false, extensions }), commonjs(), babel({ babelHelpers: ‘bundled’, extensions }) ] }
function getRollupOutputOptions(
outputPath,
outputDir,
format,
globalName,
globals,
) {
const config = {
name: globalName,
sourcemap: false,
globals,
plugins: []
}
return format.map(type => {
const name = ${globalName}.${type}.js
return {
…config,
file: ${outputPath.replace('index.ts', '')}${outputDir}/${name}
,
format: type
}
})
}
function handleRollupError(error) {
console.error(
\x1b[31m-- 错误:${error.code}${error.plugin ?
(${error.plugin}): ''} --
);
}
async function createBundle(bundle) {
const { format, entry, outputDir } = bundle;
let resolvedEntry = resolveEntryFork(entry);
const rollupOutputOptions = getRollupOutputOptions(resolvedEntry, outputDir, format, entry);
const rollupConfig = {
input: resolvedEntry,
plugins: getRollupPlugins(),
output: rollupOutputOptions
}
if (isWatchMode) {
const watcher = rollup.watch(rollupConfig);
watcher.on(‘event’, async event => {
switch (event.code) {
case ‘BUNDLE_START’:
console.log(${chalk.bgYellow.black(
【${entry}】模块打包中….. )}
);
break;
case ‘BUNDLE_END’:
console.log(${chalk.bgGreen.black(
【${entry}】模块打包成功! )} \n
);
break;
case ‘ERROR’:
case ‘FATAL’:
console.log(${chalk.bgRed.black(' 打包错误! ')} \n
);
handleRollupError(event.error);
break;
}
});
} else {
try {
const result = await rollup.rollup(rollupConfig);
for (let outputConfig of rollupOutputOptions) {
await result.write(outputConfig);
}
console.log(chalk{rgb(103, 194, 58) 【${entry}包】build success}
);
} catch (error) {
throw error;
}
}
}
// 循环模块 逐一打包 function buildEverything() { for (const bundle of bundles) { if (buildMode.includes(bundle.entry)) createBundle(bundle); } }
buildEverything();
- bundles.js
```javascript
'use strict';
const bundles = [
{
entry: "core", // 模块名称
outputDir: "npm", // 打包输出的文件夹
format:['umd','es'], // 打包代码格式
minifyWithProdErrorCodes: true, //代码压缩
},
{
entry: "icon",
outputDir: "npm",
format:['umd','es'],
minifyWithProdErrorCodes: true,
}
];
function deepFreeze(o) {
Object.freeze(o);
Object.getOwnPropertyNames(o).forEach(function(prop) {
if (
o[prop] !== null &&
(typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
!Object.isFrozen(o[prop])
){
deepFreeze(o[prop]);
}
});
return o;
}
deepFreeze(bundles);
module.exports = {
bundles
};
5、babel.config.js
module.exports = {
presets: [
[
"@babel/preset-env",
]
]
}
总结
定制化强、打包进行解耦独立维护、支持多个包模块(monorepo模式)一起打包、争对多库的管理打包非常的方便 、适合配合lerna进行使用!