背景
公司有几个后台管理项目基于vue-element-admin,公共的组件、公共样式、公共js库及公共页面组件都各写一套。那么就存在以下问题:
- 公共部分没有权限控制,团队成员都可以修改。
- 公共部分难以维护,修改一个工程要考虑其他工程的代码同步。
- 技术得不到沉淀,难以输出团队技术影响力
所以考虑把后管公共部分抽取出一个js文件。
分析
-
在
public/index.html先引入公共的js,如paview.js<!DOCTYPE html> <html> <head> <script src="./paview.js"></script> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> </body> </html> -
但是公共库依赖于vue.js和element-ui,所以vue.js和element-ui必须在paview.js引入之前引入。
-
另外对element-ui的定制,比如主题色样式,也应该属于公共部分
-
打包生成公共js的格式应该是umd。参考: segmentfault.com/a/119000001…
- 原生webpack需要写一些配置
- 使用vue-cli构建库的功能可以更快速生成umd文件,umd会暴露全局变量 cli.vuejs.org/zh/guide/bu…
所以公共库需要打包生成两部分:vue+element--ui和公共库,并在引入时保证顺序。
研究
-
在入口文件main.js导出公共的部分
import Vue from "vue"; import "normalize.css/normalize.css"; // A modern alternative to CSS resets import ElementUI from "element-ui"; import "element-ui/lib/theme-chalk/index.css"; import "@/styles/index.scss"; // global css import request from "@/utils/request"; import Demo from "@/components/demo"; // set ElementUI lang to EN Vue.use(ElementUI); export default { version: "1.0.0", utils: { request, Demo, }, }; -
package.json中增加构建命令
// paview即是公共js暴露的全局变量 "scripts": { "lib": "vue-cli-service build --target lib --name paview src/main.js" }, -
执行npm run lib命令,在dist目录得到输出
dist/paview.umd.min.js 733.44 KiB 188.17 KiB dist/paview.umd.js 1820.97 KiB 349.87 KiB dist/paview.common.js 1820.50 KiB 349.72 KiB dist/paview.css 235.68 KiB 36.40 KiB -
考虑到了公共js访问, 去掉
default属性,增加vue.config.js文件, 增加配置configureWebpack: { output: { libraryExport: "default", }, resolve: { alias: { "@": resolve("src"), }, }, }, -
考虑到单独导出element-ui,
vue.config.js如下。 打包结果会生成vendors和common -
"use strict"; const path = require("path"); function resolve(dir) { return path.join(__dirname, dir); } // All configuration item explanations can be find in https://cli.vuejs.org/config/ module.exports = { publicPath: "/", outputDir: "dist", productionSourceMap: false, lintOnSave: false, configureWebpack: { output: { libraryExport: "default", }, resolve: { alias: { "@": resolve("src"), }, }, }, chainWebpack(config) { config.optimization.splitChunks({ chunks: "all", cacheGroups: { elementUI: { name: "element-ui", // split elementUI into a single package priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm }, }, }); }, }; -
要去掉vue-cli默认的vendors和common split chunks,增加配置
-
cacheGroups: { vendors: false, common: false, elementUI: { name: "element-ui", // split elementUI into a single package priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm }, }, -
demo.html使用打包后的js和css
<meta charset="utf-8" /> <title>paview demo</title> <link rel="stylesheet" href="./dist/css/element-ui.cf6f4420.css" /> <link rel="stylesheet" href="./dist/paview.css" /> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="./dist/paview.umd.element-ui.js"></script> <script src="./dist/paview.umd.min.js"></script> <body> <div id="app"> <el-button>按钮</el-button> <demo /> </div> </body> <script> const { request, Demo } = paview.utils; new Vue({ el: "#app", components: { Demo, }, }); console.log(request); </script> -
效果如下
