详解vue-cli3多页应用改造


Posted in Javascript onJune 04, 2019

需求

一个平台P,包含产品a、b、c、d、e。各产品UI样式风格统一,且会用到公共配置(HOST、是否添加埋点js)、组件(头部导航、表格、搜索框)、方法(请求拦截、生成UUID)。

现状:由于历史遗留原因,各产品为独立SPA、各自维护,配置、组件也都自成一体,只是大概样式上保持了一致,但细节(比如同一面包屑样式,左边距5px、8px都有)都不一致。
这种情况下,改组件、改配置都得一改改多个地方,且有些项目是vue-cli2、有些是vue-cli3,项目间依赖包的版本也不一致,维护起来非常不友好。

目标:整合各产品单页应用为MPA,提取公共文件(主题、配置、组件、方法),减少规范性东西的维护成本。

目录结构对比

整合前

详解vue-cli3多页应用改造

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

整合后

详解vue-cli3多页应用改造

│// 静态资源输出目录
│
└───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两个文件。

详解vue-cli3多页应用改造

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下,大概长这样

详解vue-cli3多页应用改造

Step4: 各产品原项目下package.json依赖包都挪到根目录下package.json,重新安装

PS:由于依赖向上升级,某些老版本依赖包可能会存在升级引发的问题,需要细心走查一遍。这里由于业务不一样,就不详细赘述了

然后npm start,完美启动~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
表格 隔行换色升级版
Nov 07 Javascript
jQuery DOM操作小结与实例
Jan 07 Javascript
Jquery数独游戏解析(一)-页面布局
Nov 05 Javascript
浅析JavaScript中的隐式类型转换
Dec 05 Javascript
关于jQuery中的each方法(jQuery到底干了什么)
Mar 05 Javascript
JS合并数组的几种方法及优劣比较
Sep 19 Javascript
贴近用户体验的Jquery日期、时间选择插件
Aug 19 Javascript
jQuery实现图片左右滚动特效
Apr 20 Javascript
JavaScript和HTML DOM的区别与联系及Javascript和DOM的关系
Nov 15 Javascript
在layui中layer弹出层点击事件无效的解决方法
Sep 05 Javascript
通过layer实现可输入的模态框的例子
Sep 27 Javascript
vue项目中使用bpmn-自定义platter的示例代码
May 11 Javascript
javascript异步处理与Jquery deferred对象用法总结
Jun 04 #jQuery
浅谈react-router@4.0 使用方法和源码分析
Jun 04 #Javascript
vue axios post发送复杂对象问题
Jun 04 #Javascript
vue 2.5.1 源码学习 之Vue.extend 和 data的合并策略
Jun 04 #Javascript
vue实现分环境打包步骤(给不同的环境配置相对应的打包命令)
Jun 04 #Javascript
JavaScript实现页面中录音功能的方法
Jun 04 #Javascript
vue elementUI 表单校验功能之数组多层嵌套
Jun 04 #Javascript
You might like
探讨:web上存漏洞及原理分析、防范方法
2013/06/29 PHP
PHP解析RSS的方法
2015/03/05 PHP
Yii2下点击验证码的切换实例代码
2017/03/14 PHP
php抽象类和接口知识点整理总结
2019/08/02 PHP
ie和firefox中img对象区别的困惑
2006/12/27 Javascript
[原创]站长必须要知道的javascript广告代码
2007/05/30 Javascript
固定网页背景图同时保持图片比例的思路代码
2013/08/15 Javascript
JavaScript实现多个重叠层点击切换效果的方法
2015/04/24 Javascript
js实现div层缓慢收缩与展开的方法
2015/05/11 Javascript
js实现不提交表单获取单选按钮值的方法
2015/08/21 Javascript
JS Array.slice 截取数组的实现方法
2016/01/02 Javascript
javascript结合Flexbox简单实现滑动拼图游戏
2016/02/18 Javascript
JavaScript设计模式之单例模式详解
2017/06/09 Javascript
JS实现数组简单去重及数组根据对象中的元素去重操作示例
2018/01/05 Javascript
security.js实现的RSA加密功能示例
2018/06/06 Javascript
js实现延迟加载的几种方法详解
2019/01/19 Javascript
js笔试题-接收get请求参数
2019/06/15 Javascript
[02:14]DOTA2英雄基础教程 修补匠
2013/12/23 DOTA
Python获取邮件地址的方法
2015/07/10 Python
Python实现的Excel文件读写类
2015/07/30 Python
Python matplotlib画图实例之绘制拥有彩条的图表
2017/12/28 Python
Linux系统(CentOS)下python2.7.10安装
2018/09/26 Python
Django 日志配置按日期滚动的方法
2019/01/31 Python
用Python配平化学方程式的方法
2019/07/20 Python
在python中求分布函数相关的包实例
2020/04/15 Python
利用HTML5+css3+jquery+weui实现仿微信聊天界面功能
2018/01/08 HTML / CSS
Under Armour安德玛德国官网:美国高端运动科技品牌
2019/03/09 全球购物
阿迪达斯香港官网:adidas香港
2019/11/09 全球购物
期末总结的个人自我评价
2013/11/02 职场文书
医药专业推荐信
2013/11/15 职场文书
大学生自我鉴定
2013/12/08 职场文书
幼儿园感恩节活动方案2014
2014/10/11 职场文书
小学生节水倡议书
2015/04/29 职场文书
使用pytorch实现线性回归
2021/04/11 Python
python 经纬度求两点距离、三点面积操作
2021/06/03 Python
台式电脑蓝牙适配器怎么安装?台式电脑蓝牙适配器安装教程
2022/04/08 数码科技