背景

需求是我们有两个库需要进行打包、因为两个库的打包配置都一样、我们是否有办法不需要在每个库里面创建一份rollup.config.js、然后就是尽可能的定制化强一些、因为有可能后面有的打包规则对因为库的不一样而动态起来!

目录结构

  1. ---build
  2. ---build.js
  3. ---bundles.js
  4. ---packages
  5. ---core
  6. ---src
  7. ---index.ts
  8. ---icon
  9. ---src
  10. ---index.ts
  11. ---babel.config.js

1、初始化项目

yarn init

2、安装必须依赖

yarn add @rollup/plugin-babel @rollup/plugin-node-resolve @rollup/plugin-commonjs @babel/core @babel/preset-env -D

3、package.json

  1. {
  2. "name": "rollup-monorepo",
  3. "version": "1.0.0",
  4. "main": "index.js",
  5. "license": "MIT",
  6. "scripts": {
  7. "build": "yarn build:js", // 指定打包某个包 yarn build core
  8. "build:js": "node ./build/build.js --mode", // 执行打包所有包
  9. "dev":"node ./build/build.js --watch" // 热更新、启动后监听文件变动、而执行打包
  10. },
  11. "devDependencies": {
  12. "@babel/core": "^7.17.8",
  13. "@babel/preset-env": "^7.16.11",
  14. "@rollup/plugin-babel": "^5.3.1",
  15. "@rollup/plugin-commonjs": "^21.0.3",
  16. "@rollup/plugin-node-resolve": "^13.1.3",
  17. "rollup": "^2.70.1"
  18. }
  19. }

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();

  1. - bundles.js
  2. ```javascript
  3. 'use strict';
  4. const bundles = [
  5. {
  6. entry: "core", // 模块名称
  7. outputDir: "npm", // 打包输出的文件夹
  8. format:['umd','es'], // 打包代码格式
  9. minifyWithProdErrorCodes: true, //代码压缩
  10. },
  11. {
  12. entry: "icon",
  13. outputDir: "npm",
  14. format:['umd','es'],
  15. minifyWithProdErrorCodes: true,
  16. }
  17. ];
  18. function deepFreeze(o) {
  19. Object.freeze(o);
  20. Object.getOwnPropertyNames(o).forEach(function(prop) {
  21. if (
  22. o[prop] !== null &&
  23. (typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
  24. !Object.isFrozen(o[prop])
  25. ){
  26. deepFreeze(o[prop]);
  27. }
  28. });
  29. return o;
  30. }
  31. deepFreeze(bundles);
  32. module.exports = {
  33. bundles
  34. };

5、babel.config.js

  1. module.exports = {
  2. presets: [
  3. [
  4. "@babel/preset-env",
  5. ]
  6. ]
  7. }

总结

定制化强、打包进行解耦独立维护、支持多个包模块(monorepo模式)一起打包、争对多库的管理打包非常的方便 、适合配合lerna进行使用!