UI组件库的打包是指“将开发完成的业务代码处理成可在生产环境中运行,并供用户在浏览器上使用”的过程。浏览器可以视为用户使用的生产环境,除浏览器外,常见的生产环境还有Node.js。Node.js通常是现代前端开发过程所运行的环境,例如我们常在Node.js环境下使用Vue和React,相当于Node.js是它们的生产环境。Node.js在13.2.0版本之前仅支持CommonJS模块,在13.2.0版本之后才开始支持ESM模块。为了让开发人员在不同版本的Node.js环境下运行UI组件库,需要提供CommonJS和ESM两种模式来打包UI组件库。
除上述环境外,打包UI组件库后的代码会进行压缩处理,需要通过source map文件映射回未压缩的代码,方便开发人员调试以及定位代码的出错位置,最后还要将scss文件打包成传统的css文件,用于提供全量UI组件库的css样式。在UI组件库的打包过程中,需要完成的工作如下:
- 提供浏览器端的代码包,可以是UMD或IIFE。
- 提供Node.js环境的CommonJS模块和ESM模块代码包。
- 提供全局引入的css样式,并按需加载css样式。
- 提供source map文件。
- 对UI组件库打包的代码进行压缩。
了解Rollup
Rollup是一个用于js模块的打包工具,它将小的代码片段编译成更大,更复杂的代码,例如库或应用程序。 它使用ES6版本的js中包含的新标准化代码模块格式,而不是以往的CommonJS和AMD等特殊解决方案。
Rollup的配置简单直观,能够生成轻量、高效的构建文件,尤其适用于构建JS库或框架。它还支持代码拆分、按需加载等功能,有助于优化和提升前端应用的性能。
Rollup具有以下特点。
- 高效:Rollup通过静态分析的方式,只打包必要的代码和依赖,打包过程更高效,打包后的产物也更小。
- 可扩展性强:Rollup支持各种插件和加载器扩展其功能,可以轻松地与Babel、ts、eslint等工具集成。
- 模块化:Rollup基于ES6模块,支持使用ES6模块化地语法和特性,例如import和export。
- 代码分割:Rollup支持将代码分割成多个小块,并支持按需加载或并行加载,以优化性能。
- Tree Shaking:Rollup可以消除不必要地代码和依赖,以减少最终地产物大小。
- 多格式输出:AMD、CommonJS、ES6 modules、UMD、IIFE、等。
使用Rollup打包UI组件库只需进行全局安装,在终端执行指令npm install --global rollup。
接下来的UI组件库打包过程将围绕Rollup的JS API特性展开,实现UMD、ES以及CJS这3种模块的打包。
初始化Build打包目录
Rollup有以下两种配置方式。
- 配置文件+命令行:可以提供一个可选的Rollup配置文件,以简化命令行的使用,并启用高级Rollup功能。
- JS API:一个可以在Nodejs中使用的JS API。这种方式相比起第一种方式会更加灵活。
新建build目录,并在build目录下执行npm init -y,为build生成package.json文件作为一个打包工具包。
Rollup的基础配置
如果你的ui组件库是使用Vue开发的,打包UI组件库就是将Vue文件编译成JS文件的过程,如果使用了ts,同样需要将以.ts为后缀的文件编译成js文件。在rollup中,推荐使用@vitejs/plugin-vue插件识别vue文件,使用@rollup/plugin-node-resolve插件解析npm包。对于ts,则可以使用rollup-plugin-esbuild插件进行编译。
根据上述说明,首先在build目录下安装上述3个插件。
{
"name": "build",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@rollup/plugin-node-resolve": "^16.0.0",
"@vitejs/plugin-vue": "^5.2.1",
"rollup": "^4.30.1",
"rollup-plugin-esbuild": "^6.1.1"
}
}
Rollup打包主要有4个步骤:
- 配置打包入口文件。
- 配置所需插件。
- 配置输出文件格式。
- 打包输出目录。
在build目录下新建src目录以及umdBuild.js文件,用于实现umd格式的打包,代码如下:
import {
rollup } from "rollup";
import {
nodeResolve } from "@rollup/plugin-node-resolve";
import vue from "@vitejs/plugin-vue";
import esbuild from "rollup-plugin-esbuild";
/**
* node.js 核心方法 url、path
*/
import {
resolve } from "path";
import {
pkgRoot, outputUmd } from "./common.js"
// umd打包
export const umdBuildEntry = async () => {
const writeBundles = await rollup({
input: resolve(pkgRoot, "index.js"), // 配置打包入口文件
plugins: [ // 配置插件
vue(),
nodeResolve({
extensions: ['.ts'] }),
esbuild(),
],
external: ["vue"], // 排除不进行打包的npm包
});
writeBundles.write({
})
};
umdBuildEntry()
配置打包路径
在打包UI组件库时需要配置打包文件的入口、插件、格式和输出目录。
/**
* node.js 核心方法 url、path
*/
//common.js
import {
fileURLToPath } from "url";
import {
resolve, dirname } from "path";
export const outputPkgDir = 'hzu'//输出目录
export const filePath = fileURLToPath(import.meta.url);
export const dirName = dirname(filePath);
export const rootDir = resolve(dirName, "..", ".."); // 获取UI组件库 “根目录”
export const pkgRoot = resolve(rootDir, "packages"); // 获取UI组件包的目录,入口
console.log('filePath', filePath)
console.log('dirName', dirName)
console.log('rootDir', rootDir