1. 程式人生 > 程式設計 >vue多頁面專案開發實戰指南

vue多頁面專案開發實戰指南

目錄
  • 單頁應用和多頁應用
    • 單頁應用
    • 多頁應用
    • 優缺點
    • 配置多頁應用
      • 1. 修改.config.
      • 2. 修改title
      • 3. 合併第三方庫
      • 4. 打包第三方s
      • 5. 其它常見設定
  • 總結

    單頁應用和多頁應用

    單頁應用

    SPA(single page application): 單頁面應用,即一個web專案就只有一個頁面(即一個HTML檔案)。

    就是把整個專案的所有頁面的所有內容分成了很多的小塊(就是元件),可以重複利用的,可以任意調整的元件,每個元件就是一個獨立的部分(包括html,css和script程式碼)。再做一個html(基本上啥也沒有),這個html就是一個頁面容器,需要放哪個元件時,直接引入就行。跳轉時,直接跳轉元件就行。當需要載入某個元件時,js會動態建立這些元件裡的HTML,CSS。

    這類專案通常都需要router來進行頁面跳轉.

    一開始只需要載入一次js、css的相關資源。所有內容都包含在主頁面,對每一個功能模組元件化。單頁應用跳轉,就是切換相關元件,僅僅重新整理區域性資源。

    打包後的頁面dist 目錄結構

    dist
    ├── static
    │   ├── css
    │   ├── js
    │   ├── img
    │   ├── dll
    │   └── ...
    └── index.html
    └── ...
    └── ...

    多頁應用

    MPA(multipage application): 多頁面應用,即一個web專案就有多個頁面(即多個HTML檔案)。

    指有多個獨立頁面的應用(多個html頁面),每個頁面必須重複載入js、css等相關資源。多頁應用跳轉,需要整頁資源重新整理。

    專案是由多個完整的頁面組成。多頁面跳轉重新整理所有資源,每個公共資源(js、css等)需選擇性重新載入。

    打包後的頁面dist 目錄結構

    dist
    ├── page(這裡名字打包出哪個資料夾自己配置)
    │   ├── css
    │   ├── js
    │   ├── img
    │   ├── index.html
    │   └── user.html
    │   └── setting.html
    │   └── ....html
    │   └── ....html
    .   ....
    .   ....
    .   ....

    優缺點

    單頁應用的優缺點

    優點
    有良好的互動體驗。能提升頁面切換體驗,使用者在訪問應用頁面是不會頻繁的去切換瀏覽頁面,從而避免了頁面的重新載入。

    單頁面是一次性把web應用的所有程式碼(HTML,和CSS)全部請求過來,有時候考慮到首屏載入太慢會按需載入。這樣一來,以後使用者的每一個動作都不會重新載入頁面(即不用再問伺服器要頁面的HTML慢,css和js程式碼),取而代之的是利用 JavaScript 動態的變換HTML的內容(這不需要和伺服器互動,除非資料是動態,那麼只需要問伺服器要資料即可)。

    缺點
    SEO難度較高。
    首屏載入(初次載入)耗時多。為實現單頁Web應用功能及顯示效果,需要在載入頁面的時候將JavaScript、CSS統一載入,部分頁面可以在需要的時候載入。所以必須對JavaScript及CSS程式碼進行合併壓縮處理;

    多頁應用的優缺點
    優點
    有利於seo。
    首屏載入載入快。

    缺點
    頁面切換慢。資源共用(html、css,js)不共享,不共用,每個頁面都需要載入。
    頁面重複程式碼多。

    配置多頁應用

    1. 修改vue.config.js

    官網配置入口

    在 multi-page 模式下構建應用。每個“page”應該有一個對應的 JavaScript 入口檔案。其值應該是一個物件,物件的 key 是入口的名字,value 是:

    • 一個指定了 entry,template,filename,title 和 chunks 的物件 (除了 entry 之外都是可選的);
    • 或一個指定其 entry 的字串。
    module.exports = {
      pages: {
        index: {
          // page 的入口
          entry: 'src/index/main.js',// 模板來源
          template: 'pwww.cppcns.comublic/index.html',// 在 dist/index.html 的輸出
          filename: 'index.html',// 當使用 title 選項時,
          // template 中的 title 標籤需要是 <title><%= htmlWebpackPlugin.options.title %></title>
          title: 'Index Page',// 在這個頁面中包含的塊,預設情況下會包含
          // 提取出來的通用 chunk 和 vendor chunk。
          chunks: ['chunk-vendorhttp://www.cppcns.coms','chunk-common','index']
        },// 當使用只有入口的字串格式時,
        // 模板會被推導為 `public/subpage.html`
        // 並且如果找不到的話,就回退到 `public/index.html`。
        // 輸出檔名會被推導為 `subpage.html`。
        subpage: 'src/subpage/main.js'
      }
    }

    以上是官網的例子,這裡我們改寫一下,統一配置多頁

    前提條件在src 下新建一個pages資料夾

    pages新建如下三個檔案

    pages
    └── index-skeleton.html
    └── indexApp.html
    └── app.js
    const glob = require('glob')
    const fs = require('fs');
    let titleObj = {};
    // 統一配置多頁
    
    // 這裡是遍歷src下面的pages 下面每個資料夾(例如index)下以xxxApp.vue 命名的vue頁面
    glob.sync('./src/pages/**/*App.vue').forEach((path) => {
        // 遍歷path
        console.log(path,'path')
       //./src/pages/index/indexApp.vue path
      
      // 找到檔名
      const fileName = path.split('/')[path.split('/').length - 1];
       console.log(fileName,'fileName')
       // indexApp.vue fileName
      
      // 去掉App 字尾
      const chunk = path.substring(12,path.indexOf('/' + fileName));
        console.log(chunk,'chunk')
       // index chunk
     
      // 這裡是給每個頁面設定標題,需要在indexApp.vue設定一個變數pageTitle
      let fileContent = fs
        .readFileSync(path,{ encoding: 'utf-8' })
        .toString()
        .replace(/\r\n/g,'');
      fileContent = fileContent.substr(fileContent.indexOf('pageTitle:'));
      fileContent = fileContent.substr(0,fileContent.indexOf(','));
    
      fileContent =
        fileContent.indexOf('"') > 0
          ? fileContent.substr(fileContent.indexOf('"') + 1)
          : fileContent.substr(fileContent.indexOf("'") + 1);
    
      fileContent =
        fileContent.indexOf('"') > 0
          ? fileContent.substr(0,fileContent.indexOf('"'))
          : fileContent.substr(0,fileContent.indexOf("'"));
      titleObj[chunk] = fileContent ? fileContent : '標題';
    });
    
    
    // 這裡是遍歷src下面的pages 下面每個資料夾(例如index)下以app.js
    glob.sync('./src/pages/**/app.js').forEach((path) => {
      //打包js
      const chunk = path.split('./src/pages/')[1].split('/app.js')[0];
      const tmp = chunk.split('/');
      // 模版html,如果都是一樣的,可以直接使用public下index.html,如果要設定標題的話,需要每個頁面都有一個html模版,如果不需要,就可以使用同一個,看個人習慣
      let templateUrl =
        'src/pages/' + chunk + '/' + tmp[tmp.length - 1] + '-skeleton.html';
    
      pages[chunk] = {
        entry: path,//入口檔案
        template: templateUrl,//模版html
        title: titleObj[chunk] ? titleObj[chunk] : '標題',//標題
        filename: chunk.replace(/\//g,'-') + '.html',//打包出來的html名字
        chunks: ['chunk-vendors',chunk],//依賴包
      };
    });
    module.exports = {
      // 選項...
      publicPath: process.env.NODE_ENV === 'production'
        ? '/dist/'
        : '/',pages,}

    2. 修改title

    其實是用外掛替換的

    很簡單,就是把html模版中的title使用模版語法就行

    例如index-skeleton.html 這裡每個頁面html都是一樣的,複製即可

    <title><%= htmlWebpackPlugin.options.title %></title>

    3. 合併第三方庫

    如果不設定分包,所有node_modules 裡面的第三方資源庫,例如Echarts,Axios,ali-oss,等等都會被打進chunk-vendors,至於為什麼會打進去,我們看下vue.config.js預設的分包規則

    官網分包splitChunks入口

    官網預設的配置

    module.exports = {
      //...
     //...
      optimization: {
        splitChunks: {
          chunks: 'async',// 程式碼分割時對非同步程式碼生效,all:所有程式碼有效,inital:同步程式碼有效
          minSize: 30000,// 程式碼分割最小的模組大小,引入的模組大於 30000B 才做程式碼分割
          maxSize: 0,// 程式碼分割最大的模組大小,大於這個值要進行程式碼分割,一般使用預設值
          minChunks: 1,// 引入的次數大於等於1時才進行程式碼分割
          maxAsyncRequests: 6,// 最大的非同步請求數量,也就是同時載入的模組最大模組數量
          maxInitialRequests: 4,// 入口檔案做程式碼分割最多分成 4 個 js 檔案
          automaticNameDelimiter: '~',// 檔案生成時的連線符
          automaticNameMaxLength: 30,// 自動生成的檔名的最大長度
          cacheGroups: {
            vendors: {
              test: /[\\/]node_modules[\\/]/,// 位於node_modules中的模組做程式碼分割
              priority: -10 // 根據優先順序決定打包到哪個組裡,例如一個 node_modules 中的模組進行程式碼
            },// 分割,,既滿足 vendors,又滿足 default,那麼根據優先順序會打包到 vendors 組中。
            default: { // 沒有 test 表明所有的模組都能進入 default 組,但是注意它的優先順序較低。
              priority: -20,//  根據優先順序決定打包到哪個組裡,打包到優先順序高的組裡。
              reuseExistingChunk: true // //如果一個模組已經被打包過了,那麼再打包時就忽略這個上模組
            }
          }
        }
      }
    };

    我們重點看下 minChunks 這個配置,預設大於1次就會進行分包操作,以前是一個單頁面,所以分包沒有問題,只會在index.html引入,現在是多頁面,每個頁面都會引入這個chunk-vendors,有些包其實只有兩三個頁面用到,因此,最好是不分包,或者達到一定次數才有分包意義

    我們這裡設定8次,才分包,幾乎沒有分包,根據各位需求可以自己設定

        optimization: {
          minimize: false,splitChunks: {
            cacheGroups: {// 快取分組
              common: {// 公共的模組
                name: 'chunk-common',//命名要和上面chunks定義的一致
                chunks: 'initial',minSize: 1,// 大小限制
                priority: 0,minChunks: 8,// 最少複用過幾次
              },// 打包第三方庫的檔案
              vendor: {
                name: 'chunk-vendors',//命名要和上面chunks定義的一致
                test: /[\\/]node_modules[\\/]/,chunks: 'initial',priority: 10,// 許可權更高,優先抽離,重要!!!
                minChunks: 8,},

    4. 打包第三方scss

    有一些自己寫的公共scss,比如common.scss,不想在頁面引入,因為每個頁面都要引入,其實也有很簡單處理的方法,這和以前沒什麼變化,話不多說,直接上程式碼

    let scssVariables = require('./src/scss/variables.scss.js');
    
    css: {
        loaderOptions: {
          scss: {
            prependData:
              Object.keys(scssVariables)
                .map((k) => `${k.replace('_','-')}: ${scssVariables[k]};`)
                .join('\n') + '\n',

    5. 其它常見設定

    就是一些常見設定,看個人設定 這裡重點推薦一下filenameHashing,多頁面應用不帶hash的設定,因為沒有使用路由,也就用不到了.

    module.exports = {
      publicPath: './',//輸出目錄
      outputDir: 'fund',assetsDir: '',// 配置別名
      chainWebpack: (config) => {
        config.resolve.alias.set('@',resolve('src'));
        config.resolve.alias.set('@@',resolve('src/components'));
        config.resolve.alias.set('@assets',resolve('src/assets'));
        config.resolve.alias.set('scss',resolve('src/scss'));
      },// 關閉eslint校驗
      lintOnSave: false,// 不生成map檔案
      productionSourceMap: false,//檔名稱不帶hash值
      filenameHashing: false,devServer: {
        publicPath: '/fund/',proxy: {// 本地除錯轉發
          '/api': {
            target: 'http://127.0.0.1:8080',changeOrigin: true,pathRewrite: {
              '^/api': '',};

    總結

    到此這篇關於vue多頁面專案開發的文章就介紹到這了,更多相關vue多頁面專案開發內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!