详解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 相关文章推荐
javascript 特性检测并非浏览器检测
Jan 15 Javascript
javascript 鼠标拖动图标技术
Feb 07 Javascript
使用jQuery实现dropdownlist的联动效果(sharepoint 2007)
Mar 30 Javascript
关于JavaScript的面向对象和继承有利新手学习
Jan 11 Javascript
在firefox和Chrome下关闭浏览器窗口无效的解决方法
Jan 16 Javascript
html dom节点操作(获取/修改/添加或删除)
Jan 23 Javascript
Angularjs中UI Router全攻略
Jan 29 Javascript
jQuery实现手机版页面翻页效果的简单实例
Oct 05 Javascript
JavaScript基于DOM操作实现简单的数学运算功能示例
Jan 16 Javascript
用VueJS写一个Chrome浏览器插件的实现方法
Feb 27 Javascript
Javascript三种字符串连接方式及性能比较
May 28 Javascript
微信小程序bindtap事件与冒泡阻止详解
Aug 08 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
如何去掉文章里的 html 语法
2006/10/09 PHP
PHP 5.3和PHP 5.4出现FastCGI Error解决方法
2015/02/12 PHP
php实现的通用图片处理类
2015/03/24 PHP
Smarty模板类内部原理实例分析
2019/07/03 PHP
jquery属性过滤选择器使用示例
2013/06/18 Javascript
JavaScript获取FCK编辑器信息的具体方法
2013/07/12 Javascript
jqgrid 编辑添加功能详细解析
2013/11/08 Javascript
让IE8浏览器支持function.bind()方法
2014/10/16 Javascript
js判断滚动条是否已到页面最底部或顶部实例
2014/11/20 Javascript
jQuery的Scrollify插件实现滑动到页面下一节点
2015/07/05 Javascript
jquery简单实现带渐显效果的选项卡菜单代码
2015/09/01 Javascript
Javascript学习之谈谈JS的全局变量跟局部变量(推荐)
2016/08/28 Javascript
微信小程序 网络请求(post请求,get请求)
2017/01/17 Javascript
JavaScript常用数组操作方法,包含ES6方法
2020/05/10 Javascript
微信JS-SDK updateAppMessageShareData安卓不能自定义分享详解
2019/03/29 Javascript
python解析中国天气网的天气数据
2014/03/21 Python
Python正则表达式使用范例分享
2016/12/04 Python
python高级特性和高阶函数及使用详解
2018/10/17 Python
Python中垃圾回收和del语句详解
2018/11/15 Python
python文件写入write()的操作
2019/05/14 Python
python实现大文件分割与合并
2019/07/22 Python
Python configparser模块操作代码实例
2020/06/08 Python
Python Switch Case三种实现方法代码实例
2020/06/18 Python
基于python requests selenium爬取excel vba过程解析
2020/08/12 Python
法国设计制造的扫帚和刷子:Andrée Jardin
2018/12/06 全球购物
英国旅行箱包和行李箱购物网站:Travel Luggage & Cabin Bags
2019/08/26 全球购物
大学生暑期实践感言
2014/02/26 职场文书
关于孝道的演讲稿
2014/05/21 职场文书
经济管理自荐书
2014/06/09 职场文书
幼师求职信
2014/06/23 职场文书
企业委托书范本
2014/09/13 职场文书
先进集体申报材料
2014/12/25 职场文书
主持人开幕词
2015/01/29 职场文书
老公写给老婆的检讨书
2015/05/06 职场文书
电台广播稿范文
2015/08/19 职场文书
Android开发手册自定义Switch开关按钮控件
2022/06/10 Java/Android