需求
一个平台P,包含产品a、b、c、d、e。各产品UI样式风格统一,且会用到公共配置(HOST、是否添加埋点js)、组件(头部导航、表格、搜索框)、方法(请求拦截、生成UUID)。
现状:由于历史遗留原因,各产品为独立SPA、各自维护,配置、组件也都自成一体,只是大概样式上保持了一致,但细节(比如同一面包屑样式,左边距5px、8px都有)都不一致。
这种情况下,改组件、改配置都得一改改多个地方,且有些项目是vue-cli2、有些是vue-cli3,项目间依赖包的版本也不一致,维护起来非常不友好。
目标:整合各产品单页应用为MPA,提取公共文件(主题、配置、组件、方法),减少规范性东西的维护成本。
目录结构对比
整合前

- bds-bank-fe
- │ README.md
- │
- │// 静态资源输出目录
- │
- └───dist
- │ └───index.html + static // 平台首页
- │ └───label // 产品a
- │ │ └───index.html + static
- │ └───metrics // 产品b
- │ └───service // 产品c
- │ └───help // 产品d
- │
- │// 项目路径
- │
- └───help-center // 产品d
- └───portal-page // 平台首页
- └───service-doc // 产品c
- └───unify-label // 产品a
- └───unify-metrics // 产品b
- │ └───build
- │ └───config
- │ └───src
整合后

- │// 静态资源输出目录
- │
- └───dist
- │ └───index.html
- │ └───label.html
- │ └───metric.html
- │ └───service.html
- │ └───stocktake.html
- │ └───css
- │ └───js
- │ └───img
- ├── public
- │ └───favicon.ico
- │ └───index.html
- │
- │// 项目路径
- │
- ├── src
- │ └── assets
- │ └── components
- │ ├── pages
- │ ├── index
- │ ├── label
- │ ├── metric
- │ ├── service
- │ ├── stocktake
实现
vue-cli 3.0官方支持多页,重点在于vue.config.js文件中pages这个配置项,每个页面单独配置entry、template、filename等。pages配置说明
- // 官网示例如下
- module.exports = {
- pages: {
- index: {
- // page 的入口
- entry: 'src/index/main.js',
- // 模板来源
- template: 'public/index.html',
- // 在 dist/index.html 的输出
- filename: 'index.html',
- // 当使用 title 选项时,
- // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
- title: 'Index Page',
- // 在这个页面中包含的块,默认情况下会包含
- // 提取出来的通用 chunk 和 vendor chunk。
- chunks: ['chunk-vendors', 'chunk-common', 'index']
- },
- // 当使用只有入口的字符串格式时,
- // 模板会被推导为 `public/subpage.html`
- // 并且如果找不到的话,就回退到 `public/index.html`。
- // 输出文件名会被推导为 `subpage.html`。
- subpage: 'src/subpage/main.js'
- }
- }
Step1: 创建新项目
选择需要的Babel、Router、Vuex、eslint...
具体步骤参考官网:创建一个项目
Step2: 修改配置文件vue.config.js
在根目录下新建public文件夹,包含favicon.ico和index.html两个文件。

index文件内容如下:
- <!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">
- <link rel="icon" href="<%= BASE_URL %>favicon.ico" rel="external nofollow" >
- <title>P-公共服务平台</title>
- </head>
- <body>
- <noscript>
- <strong>
- We're sorry but page doesn't work properly without JavaScript enabled. Please enable it to continue.
- </strong>
- </noscript>
- <div id="app"></div>
- <!-- built files will be auto injected -->
- </body>
- </html>
然后,在根目录下新建vue.config.js
- const glob = require('glob')
- const path = require('path')
- const resolve = (dir) => path.join(__dirname, dir)
-
- const PAGES_PATH = './src/pages/*/*.js'
-
- module.exports = {
- pages: setPages(),
- // TODO:以下内容非生成多页应用必须配置
- lintOnSave: true,
- productionSourceMap: false,
- chainWebpack: config => {
- /**
- * 自动化导入文件
- */
- const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
- types.forEach(
- type => addStyleResource(config.module.rule('less').oneOf(type)))
- /**
- * 添加别名
- */
- config.resolve.alias
- .set('@index', resolve('src/pages/index'))
- .set('@label', resolve('src/pages/label'))
- .set('@metrics', resolve('src/pages/metric'))
- .set('@service', resolve('src/pages/service'))
- .set('@stocktake', resolve('src/pages/stocktake'))
- /**
- * 菜单icon处理为svg-sprite
- */
- config.module
- .rule('svg')
- .exclude
- .add(resolve('src/assets/icons/menus'))
- .end()
- config.module
- .rule('svg-sprite-loader')
- .test(/\.svg$/)
- .include
- .add(resolve('src/assets/icons/menus')) // 处理目录
- .end()
- .use('svg-sprite-loader')
- .loader('svg-sprite-loader')
- .options({
- symbolId: 'icon-[name]'
- })
- }
- }
-
- /**
- * 组装页面
- */
- function setPages () {
- let pages = {}
- glob.sync(PAGES_PATH).forEach(filepath => {
- let fileList = filepath.split('/')
- let fileName = fileList[fileList.length - 2]
-
- pages[fileName] = {
- entry: filepath,
- template: 'public/index.html',
- filename: `${fileName}.html`,
- // title:
- chunks: ['chunk-vendors', 'chunk-common', fileName]
- }
- })
- return pages
- }
-
- /**
- * 注入公共less
- * @param rule
- */
- function addStyleResource (rule) {
- rule.use('style-resource')
- .loader('style-resources-loader')
- .options({
- patterns: [
- path.resolve(__dirname, 'src/assets/styles/variable.less')
- ]
- })
- }
Step3: 拷贝原项目src目录至pages下,大概长这样

Step4: 各产品原项目下package.json依赖包都挪到根目录下package.json,重新安装
PS:由于依赖向上升级,某些老版本依赖包可能会存在升级引发的问题,需要细心走查一遍。这里由于业务不一样,就不详细赘述了
然后npm start,完美启动~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。