vue-cli3多頁應用改造

需求

一個平臺P,包含產品a、b、c、d、e。各產品UI樣式風格統一,且會用到公共配置(HOST、是否添加埋點js)、組件(頭部導航、表格、搜索框)、方法(請求攔截、生成UUID)。javascript

現狀:因爲歷史遺留緣由,各產品爲獨立SPA、各自維護,配置、組件也都自成一體,只是大概樣式上保持了一致,但細節(好比同一麪包屑樣式,左邊距5px、8px都有)都不一致。
這種狀況下,改組件、改配置都得一改改多個地方,且有些項目是vue-cli二、有些是vue-cli3,項目間依賴包的版本也不一致,維護起來很是不友好。css

目標:整合各產品單頁應用爲MPA,提取公共文件(主題、配置、組件、方法),減小規範性東西的維護成本。html

目錄結構對比

整合前

整合前目錄結構

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配置說明vue

// 官網示例以下
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...
具體步驟參考官網:建立一個項目java

Step2: 修改配置文件vue.config.js

在根目錄下新建public文件夾,包含favicon.ico和index.html兩個文件。
圖片描述vue-cli

index文件內容以下:npm

<!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">
    <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.jsjson

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:因爲依賴向上升級,某些老版本依賴包可能會存在升級引起的問題,須要細心走查一遍。這裏因爲業務不同,就不詳細贅述了app

而後npm start,完美啓動~less

相關文章
相關標籤/搜索