17.1 使用 Rollup 打包

17.1 使用 Rollup 打包

在现代 JavaScript 工具库开发中,Rollup 是一个优秀的模块打包工具,特别适合库项目的打包需求。本节将带你从零开始配置 Rollup,并理解其核心概念。

为什么选择 Rollup?

  1. 专为库设计:生成的代码更简洁,没有冗余的模块加载代码
  2. Tree Shaking:自动移除未使用的代码
  3. ESM 优先:原生支持 ES Modules
  4. 插件生态:丰富的插件系统支持各种需求

基础配置

首先安装 Rollup:

npm install rollup --save-dev

创建基础配置文件 rollup.config.js

import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { babel } from '@rollup/plugin-babel';
import { terser } from 'rollup-plugin-terser';

export default {
  input: 'src/index.js',          // 入口文件
  output: [
    {
      file: 'dist/bundle.cjs.js', // CommonJS 格式
      format: 'cjs'
    },
    {
      file: 'dist/bundle.esm.js',  // ES Module 格式
      format: 'es'
    },
    {
      file: 'dist/bundle.umd.js',  // UMD 格式
      format: 'umd',
      name: 'MyLibrary'            // UMD 需要全局变量名
    }
  ],
  plugins: [
    nodeResolve(),                 // 解析 node_modules 中的模块
    commonjs(),                    // 将 CommonJS 转为 ES Module
    babel({                        // 使用 Babel 转译
      babelHelpers: 'bundled',
      exclude: 'node_modules/**'
    }),
    terser()                       // 代码压缩
  ]
};

关键插件说明

  1. @rollup/plugin-node-resolve

    • 解析第三方模块依赖
    • 配置示例:
      nodeResolve({
        extensions: ['.js', '.jsx'],  // 解析的文件扩展名
        moduleDirectories: ['node_modules']
      })
      
  2. @rollup/plugin-commonjs

    • 将 CommonJS 模块转换为 ES Module
    • 重要配置项:
      commonjs({
        include: /node_modules/,
        requireReturnsDefault: 'auto'
      })
      
  3. @rollup/plugin-babel

    • 集成 Babel 进行语法转译
    • 需要单独配置 .babelrc 文件
    • 推荐配置:
      babel({
        babelHelpers: 'runtime',      // 使用 @babel/plugin-transform-runtime
        skipPreflightCheck: true      // 跳过预检查提高性能
      })
      

多入口打包

对于大型工具库,可能需要多入口打包:

export default {
  input: {
    main: 'src/index.js',
    utils: 'src/utils/index.js'
  },
  output: {
    dir: 'dist',                    // 输出目录
    format: 'es',
    preserveModules: true           // 保持原始模块结构
  }
  // ...其他配置
};

Tree Shaking 实战

Rollup 的 Tree Shaking 非常高效,但需要注意:

  1. 确保使用 ES Module 语法
  2. 避免副作用代码(使用 /*#__PURE__*/ 标记)
  3. 配置 sideEffects 字段在 package.json:
{
  "sideEffects": [
    "**/*.css",
    "**/*.scss"
  ]
}

高级技巧

  1. 代码分割

    output: {
      dir: 'dist',
      format: 'es',
      chunkFileNames: '[name]-[hash].js'
    }
    
  2. 外部依赖

    external: ['lodash', 'react'],  // 不打包这些依赖
    output: {
      globals: {
        lodash: '_',                // 指定全局变量名
        react: 'React'
      }
    }
    
  3. 自定义插件示例(简单的 JSON 转换):

    const jsonPlugin = {
      transform(code, id) {
        if (!id.endsWith('.json')) return null;
        return {
          code: `export default ${code}`,
          map: null
        };
      }
    };
    

性能优化建议

  1. 使用 rollup-plugin-visualizer 分析包体积
  2. 对于大型库,考虑按需加载设计
  3. 启用缓存提高构建速度:
    import { rollup } from 'rollup';
    
    let cache;
    
    async function build() {
      const bundle = await rollup({
        cache,  // 使用缓存
        // ...其他配置
      });
      cache = bundle.cache; // 存储缓存
    }
    

完整工作流示例

  1. 添加 npm scripts:

    {
      "scripts": {
        "build": "rollup -c",
        "watch": "rollup -c -w"
      }
    }
    
  2. 典型目录结构:

    my-library/
    ├── src/
    │   ├── index.js       # 主入口
    │   ├── utils/         # 工具函数
    │   └── components/    # 组件
    ├── test/              # 测试代码
    ├── dist/              # 输出目录
    └── rollup.config.js   # 配置文件
    

调试技巧

  1. 使用 --debug 标志获取详细日志:

    rollup -c --debug
    
  2. 生成 sourcemap:

    output: {
      sourcemap: true,
      sourcemapExcludeSources: true
    }
    
  3. 使用 rollup-plugin-serve 开发服务器:

    import serve from 'rollup-plugin-serve';
    
    plugins: [
      serve({
        open: true,
        contentBase: ['dist', 'public']
      })
    ]
    

通过以上配置,你已经可以构建一个现代化的 JavaScript 工具库。接下来我们会介绍如何为这个库添加单元测试。

#前端开发 分享于 2025-03-25

【 内容由 AI 共享,不代表本站观点,请谨慎参考 】