rollup打包的简单配置

632 阅读5分钟

记录的初衷:经常忘记配置项,反复需要找资料或者找以前的项目,先写个最简单的配置

创建项目目录

mkdir my-rollup

package.json初始化并修改

pnpm init

"scripts": {
    "serve": "rollup -c -w",
    "build": "rollup -c"
  },

安装rollup和ts解析器

pnpm add rollup rollup-plugin-typescript2 -D

创建本地入口文件src/index.ts

const Hello = () => {
  console.log('Hello, world!')
}

export default Hello;

rollup配置

import { defineConfig } from "rollup";
import typescript from "rollup-plugin-typescript2";
import path from "path";
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default defineConfig([
  {
    input: "src/index.ts", //入口文件
    output: [
      {
        file: path.resolve(__dirname, "lib/main.js"),
        format: "cjs",
        name: "main.cjs",
      },
      {
        file: path.resolve(__dirname, "./lib/main.umd.js"),
        format: "umd", // 打包成UMD模块
        name: "Hello" // 打包成UMD模式,需提供name
      },
      {
        file: path.resolve(__dirname, "./lib/main.iife.js"),
        name: "Hello",
        format: "iife" // iife 表示立即执行函数
      }
    ],
    plugins: [
      typescript(),
    ]
  },
]);

tsconfig.json

配置项不明白的可以看这里www.tslang.cn/docs/handbo…

{
    "compilerOptions": {
      "module": "ESNext",
      "target": "ESNext",
      "outDir": "dist",
      "baseUrl": "./",
      "rootDir": "./src"
    },
    "exclude": ["node_modules", "dist"]
}

尝试打包cjs、umd和iife格式文件

pnpm build

umd和iife在项目中引入打包后的文件,将在windows中能找到Hello变量

创建exemple/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script type="text/javascript" src="../lib/main.umd.js"></script>
  </body>
</html>

插件Live Server运行index.html

打开服务后,控制台输入Hello(),将输出Hello, world!

Snipaste_2024-04-15_18-04-22.png

image.png

常用插件

插件名功能注意项或解释
@rollup/plugin-terseres压缩
rollup-plugin-typescript2ts编译注意在babel前
@rollup/plugin-commonjs将第三方commonjs包转为ES模块
@rollup/plugin-node-resolve主要作用在于帮助 Rollup 构建工具正确解析和处理 Node.js 模块的导入路径
rollup-plugin-polyfill-node在非 Node.js 环境(如浏览器)中可能缺失的 Node.js 内置模块和全局变量提供相应的 polyfills(垫片)在浏览器环境中使用,将 Node.js 应用打包成单文件(如 UMD、IIFE 或 ESM)以供浏览器直接使用时,该插件能够确保打包后的代码不会因为依赖 Node.js 原生模块而导致运行时错误
@rollup/plugin-babel将使用现代 JavaScript 语法(如 ES6、ES7、ES8 等)编写的源代码转换为广泛支持的 JavaScript 语法
@rollup/plugin-alias提供模块别名(aliasing)功能,为项目中的模块导入路径设置自定义的映射规则注意要配合tsconfig.json共同使用
rollup-plugin-inject-process-env提供可注入自定义变量配合env-cmd使用.env文件的变量,获取process.env
rollup-plugin-copy拷贝文件到指定目录常用于拷贝静态的文件,例如:html、umd、iiffe
@rollup/plugin-json将 .json 文件转换为 ES6 模块
@rollup/plugin-strip清除调试代码console.log
rollup-plugin-delete删除目标文件

插件使用的配置例子,来源于浏览器插件项目的实例

import { defineConfig } from "rollup";
import json from "@rollup/plugin-json";
import terser from "@rollup/plugin-terser";
import nodeResolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import nodePolyfills from 'rollup-plugin-polyfill-node';
import typescript from "rollup-plugin-typescript2";
import { babel } from "@rollup/plugin-babel";
import { DEFAULT_EXTENSIONS } from '@babel/core';
import alias from "@rollup/plugin-alias";
import strip from "@rollup/plugin-strip";
import path, { dirname } from "path";
import { fileURLToPath } from "url";
import rollupPluginCopy from "rollup-plugin-copy";
import injectProcessEnv from 'rollup-plugin-inject-process-env';
// import del from 'rollup-plugin-delete';
import fs from 'fs';

const configStr = fs.readFileSync("./package.json", "utf-8");
const packageJson = JSON.parse(configStr);

const args = process.argv.slice(2);
const entry = args[0];
console.log('entry', entry, process.env.NODE_ENV)
// import pkg from "./package.json" assert { type: "json" }; //断言导出json模块

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// rimrafSync("dist");// 删除打包目录

const myVariables = {
  NODE_ENV: process.env.NODE_ENV,
  baseUrl: process.env.NODE_OPSHIELDS_URL,
  apiUrl: process.env.NODE_OPSHIELDS_API,
  f2eUrl: process.env.NODE_F2E_API,
  version: packageJson.version,
};

const customResolver = nodeResolve({
  extensions: [".mjs", ".js", ".jsx", ".tsx", ".json", ".less"]
});

const config = 
{
  // input: [
  //   "src/background.ts",
  //   "src/contentScript.ts",
  //   "src/popup.tsx"
  // ], //入口文件
  // output: [
  //     {
  //       dir: 'dist', //出口文件夹
  //       format: "iife",
  //     },
  //     // {
  //     //   dir: 'dist/background.js', //出口文件夹
  //     //   format: "iife",
  //     //   // banner: Global
  //     // },
  //     // {
  //     //   dir: 'dist/contentScript', //出口文件夹
  //     //   format: "iife",
  //     // },
  // ],
  context: 'window',
  plugins: [
    // bakedEnv(myVariables, {
    //   // moduleName: 'enviroment_vars', // expose variables as a module called 'enviroment_vars' example: `import { FOO } from 'enviroment_vars';`
    //   preferConst: true,
    //   compact: false,
    //   indent: '  ',
    // }),
      json(),         // 将 .json 文件转换为 ES6 模块
      terser(),       // 压缩es包
      nodeResolve({
        browser: true,
        // 将自定义选项传递给解析插件
        moduleDirectories: ["node_modules"]
      }),  // Use the Node resolution algorithm.
      // nodePolyfills(),
      commonjs(),  // Convert CommonJS modules to ES Modules.
      injectProcessEnv({
        ...myVariables
      }),
      alias({
          entries: [{ find: "@", replacement: path.resolve(__dirname, "src") }],
          customResolver,
      }),
      typescript(),  // 注意在babel前
      babel({
        babelHelpers: 'runtime',
        // presets: ["@babel/preset-env"],  // 将ES6转换为向后兼容的JavaScript
        
        babelrc: false,
        presets: [
            [
                "@babel/preset-env",
                {
                    useBuiltIns: "usage", // 垫片开启
                    targets: {
                        browsers: ["chrome 99"]
                    },
                    modules: false, // 开启后会影响tree-shaking
                    corejs: 3 // 垫片开启
                }
            ]
        ],
        plugins: [
          [
            "@babel/plugin-transform-runtime",
            // { useESModules: true },
            {
              helpers: true // reqiure运行时代码
              // corejs: 3 // reqiure运行时代码
            }
          ]
        ],
        // 处理async,await、import()等语法关键字的帮助函数
        extensions: [...DEFAULT_EXTENSIONS, ".ts", ".tsx"], //增加配置
        exclude: "node_modules/**",
      }),
      // del({ targets: "dist/*" }),
      // strip(),  // 清除调试代码console.log
      rollupPluginCopy({
        targets: [
          { src: 'src/assets', dest: 'dist' },
          { src: 'src/manifest.json', dest: 'dist' },
          { src: 'src/template', dest: 'dist' },
        ]
      })
  ],
  // 指出应将哪些模块视为外部模块, 现在将被视为外部的,不会与你的库打包在一起
  // external: [
  //   "@babel/plugin-transform-runtime",
  //   "@babel/runtime"
  // ]
}


// config.plugins.push(
//   injectProcessEnv({
//       NODE_ENV: "production"
//   })
// )


// rollup(config).then(function (bundle) {
//   bundle.write({
//       format: "iife",
//       dir: 'dist',
//       // name: entry,
//       // file: path.resolve(__dirname, `dist/${entry}.js`)
//   });
// })

// 多入口配置示例
export default defineConfig([
  {
    input: "src/background.ts", //入口文件
    output: [
        {
          dir: 'dist', //出口文件夹
          format: "iife",
        },
        // {
        //   dir: 'dist/background.js', //出口文件夹
        //   format: "iife",
        //   // banner: Global
        // },
        // {
        //   dir: 'dist/contentScript', //出口文件夹
        //   format: "iife",
        // },
    ],
    ...config,
    plugins: [
      ...config.plugins,
      nodePolyfills(),
    ],
  },
  {
    input: "src/contentScript.ts", //入口文件
    output: [
        {
          dir: 'dist', //出口文件夹
          format: "iife",
        },
        // {
        //   dir: 'dist/background.js', //出口文件夹
        //   format: "iife",
        //   // banner: Global
        // },
        // {
        //   dir: 'dist/contentScript', //出口文件夹
        //   format: "iife",
        // },
    ],
    ...config
  },
  {
    input: "src/popup.tsx", //入口文件
    output: [
        {
          dir: 'dist', //出口文件夹
          format: "iife",
        },
        // {
        //   dir: 'dist/background.js', //出口文件夹
        //   format: "iife",
        //   // banner: Global
        // },
        // {
        //   dir: 'dist/contentScript', //出口文件夹
        //   format: "iife",
        // },
    ],
    ...config
  }
])

// 单入口配置示例
// export default defineConfig([
//   {
//     input: [
//       "src/background.ts",
//       // "src/contentScript.ts",
//       // "src/popup.tsx"
//     ], //入口文件
//     output: [
//         {
//           dir: 'dist', //出口文件夹
//           format: "iife",
//         },
//         // {
//         //   dir: 'dist/background.js', //出口文件夹
//         //   format: "iife",
//         //   // banner: Global
//         // },
//         // {
//         //   dir: 'dist/contentScript', //出口文件夹
//         //   format: "iife",
//         // },
//     ],
//     context: 'window',
//     plugins: [
//         json(),         // 将 .json 文件转换为 ES6 模块
//         terser(),       // 压缩es包
//         nodeResolve({
//           browser: true,
//           // 将自定义选项传递给解析插件
//           moduleDirectories: ["node_modules"]
//         }),  // Use the Node resolution algorithm.
//         // nodePolyfills(),
//         commonjs(),  // Convert CommonJS modules to ES Modules.
//         alias({
//             entries: [{ find: "@", replacement: path.resolve(__dirname, "src") }],
//             customResolver,
//         }),
//         typescript(),  // 注意在babel前
//         babel({
//           babelHelpers: 'runtime',
//           // presets: ["@babel/preset-env"],  // 将ES6转换为向后兼容的JavaScript
          
//           babelrc: false,
//           presets: [
//               [
//                   "@babel/preset-env",
//                   {
//                       useBuiltIns: "usage", // 垫片开启
//                       targets: {
//                           browsers: ["chrome 99"]
//                       },
//                       modules: false, // 开启后会影响tree-shaking
//                       corejs: 3 // 垫片开启
//                   }
//               ]
//           ],
//           plugins: [
//             [
//               "@babel/plugin-transform-runtime",
//               // { useESModules: true },
//               {
//                 helpers: true // reqiure运行时代码
//                 // corejs: 3 // reqiure运行时代码
//               }
//             ]
//           ],
//           // 处理async,await、import()等语法关键字的帮助函数
//           extensions: [...DEFAULT_EXTENSIONS, ".ts", ".tsx"], //增加配置
//           exclude: "node_modules/**",
//         }),
//         // del({ targets: "dist/*" }),
//         // strip(),  // 清除调试代码console.log
//         rollupPluginCopy({
//           targets: [
//             { src: 'src/assets', dest: 'dist' },
//             { src: 'src/manifest.json', dest: 'dist' },
//             { src: 'src/template', dest: 'dist' },
//           ]
//         })
//     ],
//     // 指出应将哪些模块视为外部模块, 现在将被视为外部的,不会与你的库打包在一起
//     // external: [
//     //   "@babel/plugin-transform-runtime",
//     //   "@babel/runtime"
//     // ]
//   },
// ]);