最近有很多小伙伴让我赶紧出打包教程,那就我们先打包,久等了👋
Rollup 打包
Rollup 是一个 JavaScript 模块打包器,可以将多个模块打包成一个或多个文件。它支持多种模块化标准,如 CommonJS、ESM 等,并且可以自动移除未使用的代码,从而减小打包文件的大小。
选择 Rollup 打包的优势:
Tree-shaking
Rollup 可以自动移除未使用的代码,这在一定程度上减少了打包文件的大小,提高了应用的加载速度。模块化支持
Rollup 支持各种模块化代码,能够很好地处理 ESM。插件丰富
Rollup 的插件系统非常强大,开发者可以通过安装各种插件来实现不同的打包需求。配置灵活
Rollup 的配置文件可以实现非常灵活的打包规则,开发者可以根据应用需求调整配置,满足个性化需求。优化性能
Rollup 可以高效地处理模块依赖关系,减少重复代码的加载,提高应用的执行效率。
安装
npm install -D rollup @rollup/plugin-node-resolve rollup-plugin-vue -w
Vue 打包配置
我们在项目根目录下创建一个 rollup.config.js 文件,我们先打包为我们最常用的 es 模块,配置如下:
import resolve from "@rollup/plugin-node-resolve";
import vuePlugin from "rollup-plugin-vue";
export default {
input: "./packages/components/index.js",
output: {
file: "dist/es.js",
name: "TestUI",
format: "es",
},
plugins: [resolve(), vuePlugin()],
external: ["vue"], // 依赖模块
};
然后我们需要配置打包命令 "build": "rollup -c"
package.json
{
"name": "test-ui",
"version": "1.0.0",
"description": "",
"scripts": {
"dev": "vite examples",
"test": "echo \"Error: no test specified\" && exit 1",
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs",
"docs:preview": "vitepress preview docs",
"build": "rollup -c"
}
}
我们执行一下 npm run build
,结果报错了
这是因为我们的配置文件使用的 ES module 写法,我们需要将 package.json
中的 type
改为 module
这时候再来试一下,成功了
由于我们打包的是 es 模块,所有可以直接在我们的 examples 项目中引入一下我们刚才打包的文件,看看是否能够正常使用
examples/index.js
import { createApp } from "vue";
import App from "./app.vue";
// import TestUI from '@test-ui/components'
// import "@test-ui/theme-chalk/index.less"; // 引入样式文件
import TestUI from "../dist/es.js";
const app = createApp(App);
app.use(TestUI);
app.mount("#app");
我们可以看到是正常的,只是没有样式,接下来我们配置一下样式文件打包
配置样式文件打包
我们会用到一些插件,来安装一下
pnpm i rollup-plugin-postcss autoprefixer -D -w
使用插件配置一下
import resolve from "@rollup/plugin-node-resolve";
import vuePlugin from "rollup-plugin-vue";
import postcss from "rollup-plugin-postcss";
import autoprefixer from "autoprefixer";
export default {
input: "./packages/components/index.js",
output: {
file: "dist/es.js",
name: "TestUI",
format: "es",
},
plugins: [
resolve(),
vuePlugin(),
postcss({
extract: "theme-chalk/style.css", // 将css提取到单独的文件中
plugins: [autoprefixer()],
}),
],
external: ["vue"], // 依赖模块
};
因为我们需要使用 postcss 来抽离我们 js 中所引入的样式文件,所以我们需要在我们的组件库中引入样式文件,然后使用 extract
抽离打包到 dist/theme-chalk/style.css
中
packages/components/index.js
import * as components from "./components";
import "@test-ui/theme-chalk/index.less";
const FUNCTION_COMP = ["TMessage"];
export default {
install(app) {
Object.entries(components).forEach(([key, value]) => {
if (!FUNCTION_COMP.includes(key)) app.component(key, value);
});
},
};
export const TMessage = components.TMessage;
我们打包一下试试
发现样式确实已经打包成功,但是我们的 font 文件并没有一并打包出来,这时候我们需要将 font 文件拷贝出来,我们需要用到一个插件 rollup-plugin-copy
pnpm i rollup-plugin-copy -D -w
再来添加一下配置,我们将 packages/theme-chalk/fonts/
路径下的所有文件打包拷贝到 dist/theme-chalk/fonts/
下
import resolve from "@rollup/plugin-node-resolve";
import vuePlugin from "rollup-plugin-vue";
import postcss from "rollup-plugin-postcss";
import autoprefixer from "autoprefixer";
import copy from "rollup-plugin-copy";
export default {
input: "./packages/components/index.js",
output: {
file: "dist/es.js",
name: "TestUI",
format: "es",
},
plugins: [
resolve(),
vuePlugin(),
postcss({
extract: "theme-chalk/style.css", // 将css提取到单独的文件中
plugins: [autoprefixer()],
}),
copy({
targets: [{ src: "packages/theme-chalk/fonts/*", dest: "dist/theme-chalk/fonts/" }],
}),
],
external: ["vue"], // 依赖模块
};
再打包一下看看
font 文件顺利拷贝出来了,但是路径不对,我们总不能每次打包完成后手动修改路径,这时候我们又需要使用一个插件 postcss-url
pnpm i postcss-url -D -w
import resolve from "@rollup/plugin-node-resolve";
import vuePlugin from "rollup-plugin-vue";
import postcss from "rollup-plugin-postcss";
import autoprefixer from "autoprefixer";
import copy from "rollup-plugin-copy";
import url from "postcss-url";
export default {
input: "./packages/components/index.js",
output: {
file: "dist/es.js",
name: "TestUI",
format: "es",
},
plugins: [
resolve(),
vuePlugin(),
postcss({
extract: "theme-chalk/style.css", // 将css提取到单独的文件中
plugins: [
autoprefixer(),
url({
url: "copy",
basePath: "fonts",
assetsPath: "fonts",
}),
],
}),
copy({
targets: [{ src: "packages/theme-chalk/fonts/*", dest: "dist/theme-chalk/fonts/" }],
}),
],
external: ["vue"], // 依赖模块
};
再来试试,发现路径已经正确了
我们再启动一下 examples 项目看看样式是否正常
丸美!
✨ 拓展一下,postcss-url
也可以配置 url
属性为 inline
,这样就可以将字体文件直接内联到 css 文件中,这样就可以不用拷贝 font 文件了,我们可以改一下然后打包试试
import resolve from "@rollup/plugin-node-resolve";
import vuePlugin from "rollup-plugin-vue";
import postcss from "rollup-plugin-postcss";
import autoprefixer from "autoprefixer";
import copy from "rollup-plugin-copy";
import url from "postcss-url";
export default {
input: "./packages/components/index.js",
output: {
file: "dist/es.js",
name: "TestUI",
format: "es",
},
plugins: [
resolve(),
vuePlugin(),
postcss({
extract: "theme-chalk/style.css", // 将css提取到单独的文件中
plugins: [
autoprefixer(),
url({
url: "inline",
basePath: "fonts",
assetsPath: "fonts",
}),
],
}),
// copy({
// targets: [
// { src: 'packages/theme-chalk/fonts/*', dest: 'dist/theme-chalk/fonts/' }
// ]
// })
],
external: ["vue"], // 依赖模块
};
打包之后我们点开样式文件看看,他会转为 base64 编码,这时候我们即使不用拷贝 font 文件也就可以使用,我们也可以运行一下看看也是正常显示的
不过还是建议将 font 分出来,因为这会造成 css 文件过大,浏览器加载时间就会变长,影响用户体验
打包为其他格式
我们也可以打包为其他格式,比如 cjs,umd 等,我们可以在 rollup.config.js
中配置一下
import resolve from "@rollup/plugin-node-resolve";
import vuePlugin from "rollup-plugin-vue";
import postcss from "rollup-plugin-postcss";
import autoprefixer from "autoprefixer";
import copy from "rollup-plugin-copy";
import url from "postcss-url";
export default {
input: "./packages/components/index.js",
output: [
{
file: "dist/es.js",
name: "TestUI",
format: "es",
},
{
file: "dist/cjs.js",
name: "TestUI",
format: "cjs",
exports: "named",
},
{
file: "dist/umd.js",
name: "TestUI",
format: "umd",
exports: "named",
globals: {
vue: "Vue",
},
},
],
plugins: [
resolve(),
vuePlugin(),
postcss({
extract: "theme-chalk/style.css", // 将css提取到单独的文件中
plugins: [
autoprefixer(),
url({
url: "copy",
basePath: "fonts",
assetsPath: "fonts",
}),
],
}),
copy({
targets: [{ src: "packages/theme-chalk/fonts/*", dest: "dist/theme-chalk/fonts/" }],
}),
],
external: ["vue"], // 依赖模块
};
Vite 打包
由于我们在 examples 中使用了 vite,所以我们也可以直接使用 vite 来打包,我们在根目录下创建一个 build 文件夹,分别创建一个 vite.es.config.js
vite.umd.config.js
,分来代表 es 的配置和 umd 的配置
/build/vite.es.config.js
// 组件库打包配置
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
export default defineConfig({
plugins: [vue()],
build: {
outDir: "dist/es",
lib: {
entry: path.resolve(__dirname, "../packages/components/index.js"),
name: "TestUI",
fileName: "index",
formats: ["es"],
},
rollupOptions: {
external: ["vue"],
output: {
exports: "named",
globals: {
vue: "Vue",
},
},
},
},
});
/build/vite.umd.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
export default defineConfig({
plugins: [vue()],
build: {
outDir: "dist/umd",
lib: {
entry: path.resolve(__dirname, "../packages/components/index.js"),
name: "TestUI",
fileName: "index",
formats: ["umd"],
},
rollupOptions: {
external: ["vue"],
output: {
exports: "named",
globals: {
vue: "Vue",
},
assetFileNames: (assetInfo) => {
if (assetInfo.name === "index.css") {
return "style.css";
}
return assetInfo.name;
},
},
},
},
});
我们添加一下打包命令
{
"name": "test-ui",
"version": "1.0.0",
"description": "",
"type": "module",
"scripts": {
"dev": "vite examples",
"test": "echo \"Error: no test specified\" && exit 1",
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs",
"docs:preview": "vitepress preview docs",
"build": "rollup -c",
"build:es": "vite build --config ./build/vite.es.config.js",
"build:umd": "vite build --config ./build/vite.umd.config.js"
}
}
这样我们就可以使用 pnpm run build:es
和 pnpm run build:umd
来打包 es 和 umd 格式的组件库了
✨ 本专栏源码地址