用rollup打包vue组件库
使用 rollup 打包成类似 elementUI 的组件库。 多仓库管理组件成本实属太大,于是想做成npm包依赖
前言
网上关于使用 rollup 打包 vue 组件的资料寥寥可数,故记录下 rollup 打包的踩坑之路,最终打包成类似 elementUI 的组件库。
多仓库管理组件成本实属太大,于是想做成npm包依赖减少维护成本,选用的是rollup工具打包。但如果有图片不建议用rollup打包,因为要装的各种插件实在太多了,也不支持 require 语法(装了 require 之类的库也不能正确引入),未知的坑略多,更适合打包纯代码文件…
附上 rollup 官方文档,vue 官网也有教程可供参考
rollup 插件
先介绍后面会用到的一些 rollup 插件:
- rollup-plugin-node-resolve — rollup 无法识别
node_modules
中的包,帮助 rollup 查找外部模块,然后导入 - rollup-plugin-commonjs — 将 CommonJS 模块转换为 ES6 供 rollup 处理
- rollup-plugin-babel — ES6 转 ES5,让我们可以使用 ES6 新特性来编写代码
- rollup-plugin-terser — 压缩 js 代码,包括 ES6 代码压缩
- rollup-plugin-eslint — js代码检测
- rollup-plugin-require-context — 使用 require.context 语法
安装
npm install --global rollup
rollup 配置
初始化
在 lerna init(yarn init -y)
初始化包依赖后安装 rollup 相关依赖,有些 rollup 插件需安装新版本的(如 babel
,commonjs
等),则应该安装 @rollup/
命名开头的插件。
yarn add @babel/core rollup rollup-plugin-node-resolve rollup-plugin-terser @rollup/plugin-babel @rollup/plugin-commonjs
如果打包文件包含 vue
,scss
,image
这些类型的文件,则还需要安装 rollup 相关的插件,否则 rollup 无法识别这些文件类型或者是其语法。
yarn add @rollup/plugin-image rollup-plugin-scss rollup-plugin-vue @vue/compiler-sfc
用到 sass 还需要安装 sass
,sass-loader
,node-sass
插件
然后新建一个 rollup.config.js
文件,把之前安装的 rollup 插件引入,基础配置如下:
// rollup.config.js
import resolve from "rollup-plugin-node-resolve"
import vue from "rollup-plugin-vue"
import babel from "@rollup/plugin-babel"
import commonjs from "@rollup/plugin-commonjs"
import image from "@rollup/plugin-image"
const config = {
input: "./index.js", // 必须,入口文件
output: { // 必须,输出文件 (如果要输出多个,可以是一个数组)
exports: "named", // 输出多个文件
globals: {
vue: "Vue" // 告诉rollup全局变量Vue即是vue
}
},
plugins: [ // 引入的插件在这里配置
resolve(),
vue({
css: true,
compileTemplate: true
}),
babel({
exclude: "**/node_modules/**"
}),
commonjs(),
image()
]
}
export default config
external配置
我们在自己的库中需要使用第三方库,例如 lodash 等,又不想在最终生成的打包文件中出现 lodash,这个时候我们就需要使用 external 属性。可根据实际情况自行选择。
external:['lodash'] //告诉rollup不要将此lodash打包,而作为外部依赖
external 可跟 globals 配套使用,如 react-redux
开源项目的 rollup 配置文件片段
input: 'src/index.js',
external: ['react', 'redux'], // 告诉rollup,不打包react,redux;将其视为外部依赖
output: {
format: 'umd', // 输出 UMD格式,各种模块规范通用
name: 'ReactRedux', // 打包后的全局变量,如浏览器端 window.ReactRedux
globals: {
react: 'React', // 跟external 配套使用,指明global.React即是外部依赖react
redux: 'Redux'
}
},
jsx 配置
如果 vue 中有用到 jsx 语法,则还需增加插件,否则会无法识别 jsx 语法
yarn add @vue/babel-preset-jsx
开始在 .babelrc
折腾了好久,发现均无效,最后发现需要在 rollup.config.js
中配置 babel 预设。
babel({
presets: ["@vue/babel-preset-jsx"]
})
入口文件配置
配置了 rollup.config.js 文件后,还需配置入口文件 index.js
,这里以多组件为例,单组件 vue 官网有示例,多组件则是参照 element-ui
框架的写法。
每个组件都要单独用一个文件夹,放在 src
里(谁让我是洁癖呐)。文件夹里一个你自己写的组件,一个 index.js
,这个 js 是用于向外暴露的。然后在 src
目录下新建 index.js
用于汇总全部组件。目录如下:
├── src
| ├── icon-font
| | ├── icon-font.vue
| | ├── index.js
├── index.js
然后在组件文件夹的 index.js
文件中如下配置:
import IconFont from "./icon-font.vue"
IconFont.install = function(Vue) {
Vue.component(IconFont.name, IconFont)
}
export default IconFont
最后在汇总全部组件的 index.js
文件中如下配置:
// Import vue component
import IconButton from "./icon-button/index"
import IconFont from "./icon-font/index"
import IconTooltip from "./icon-tooltip/index"
import LayoutHeader from "./layout-header/index"
import LayoutSidebar from "./layout-sidebar/index"
import PageIntroduce from "./page-introduce/index"
import TextHiddenTooltip from "./text-hidden-tooltip/index"
import VTable from "./v-table/index"
const components = [
IconButton,
IconFont,
IconTooltip,
LayoutHeader,
LayoutSidebar,
PageIntroduce,
TextHiddenTooltip,
VTable
]
// will install the plugin only once
const install = function(Vue) {
components.forEach(component => {
Vue.component(component.name, component)
})
}
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue)
}
// To allow use as module (npm/webpack/etc.) export component
export default { install, IconFont, TextHiddenTooltip }
// It's possible to expose named exports when writing components that can
// also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo';
// export const RollupDemoDirective = component;
可使用rollup-plugin-require-context插件的 require.context 语法改良,有需要参照使用方法的可移步至文末的 Q&A 模块
打包命令配置
最后还需要在 package.json
文件中配置打包命令,配置后直接在命令窗口中执行 yarn build
命令就可以打包了。
"scripts": {
"build": "npm run build:umd & npm run build:es & npm run build:unpkg",
"build:umd": "rollup -c --format umd --file dist/components.umd.js",
"build:es": "rollup -c --format es --file dist/components.esm.js",
"build:unpkg": "rollup -c --format iife --file dist/components.min.js"
}
在开发组件过程中,手动打包文件再联调很浪费时间,可以在 package.json
文件中增加监听文件变动自动打包的配置,同理,配置后直接执行 yarn dev
命令即可监听。
"scripts": {
"dev": "npm run dev:umd & npm run dev:es & npm run dev:unpkg",
"dev:umd": "rollup -c -w --format umd --file dist/components.umd.js",
"dev:es": "rollup -c -w --format es --file dist/components.esm.js",
"dev:unpkg": "rollup -c -w --format iife --file dist/components.min.js"
}
发布
最后就可以到 npm 网站发布了~~附上 github 例子
项目中引入组件
发布好 npm 包后,可以在项目中全局引入或局部引入组件,这里以我封装的组件库为例。
全局引入
在项目中的 main.js 中引入即可,引入组件和全局样式:
import Components from "@monorepo/components"
import "@monorepo/assets/src/scss/global.scss"
import "@monorepo/assets/src/scss/element-var.scss"
Vue.use(Components)
局部引入
在任意 vue 文件中引入:
import Components from "@monorepo/components"
Q & A
关于小伙伴的提问,统一在这里回复:
Q:关于多人提到的 vue 中的 jsx 不构建的问题,应该是指 npm run build
的时候构建报错?(不知有没理解错大家的问题)
A:个人重新拉取了仓库代码,有 yarn.lock
文件,直接执行 yarn
安装依赖后,执行 npm run build
是可以打包成功的,顺便提供 node 和 rollup 的版本供大家参考:
Q:组件库是基于 elementUI 封装的,不需要引入 elementUI 吗?
A:npm 包是不需要引入的,因为项目中会全局安装并引入 elementUI,所以这里不需要重复引入,但是需要在封装库中的 package.json 文件中写上 elementUI 这个依赖:
"devDependencies": {
"@femessage/element-ui": "^2.17.0"
}
Q:使用 require.context 优化主入口的引入方法
A:在 index.js 中代码思路大致如下:
const requireCxt = require.context("./src", true, /.vue/)
const components = {}
requireCxt.keys().map((item, index) => {
const component = requireCxt(item)
return (components[component.default.name] = component.default)
}, {})
更多推荐
所有评论(0)