天天看點

多頁vue應用的單頁面打包方法(内含打包模式的應用)一、簡介二、實作過程三、打包模式的應用總結

目錄

  • 一、簡介
  • 二、實作過程
    • 1. 配置打包指令(指定打包模式)
    • 2. 定義模式行為
    • 3. 定義打包邏輯
  • 三、打包模式的應用
  • 總結

一、簡介

關于如何以及為什麼要建構多頁vue應用,我們在上一篇文章中已經介紹過,感興趣的請參考建構多頁vue應用。本文我們要介紹的是,對于一個多頁應用,如何單獨打包其中一個(或幾個)頁面。

一般來說,多頁應用不需要打包單個頁面,這多個頁面可以作為整個應用直接放在靜态資源伺服器上。不過我們也說過,多頁應用的每個頁面也可能會放在不同的伺服器上,這時候如果往每個伺服器上都放置完整的資源包,就會顯得過于臃腫。于是我們可能就需要将某個頁面單獨打包出來。

誠然,有一個很明顯的方法,就是在每次打包的時候直接删掉

vue.config.js

的pages字段裡不相關的頁面,如:

module.exports = {
  pages: {
    page1: {...},
    // page2: {...},
    // page3: {...}
  }
}
           

顯然,這樣打包出來的結果就是隻有page1頁面了。

但是每次打包都删改配置檔案并不是一種很優雅的做法。我們需要的方案是有多個打包指令,執行對應的打包指令即可打包對應的頁面,這樣我們就可以不再改配置檔案了。下面我們來介紹這種方法:

二、實作過程

要實作通過不同的打包指令來打包單獨的頁面,需要先從打包指令本身說起。

1. 配置打包指令(指定打包模式)

我們執行的打包指令為

npm run build

,這個指令執行的是

package.json

scripts

字段下的

build

指令,它的原始值如下:

{
  ...
  "scripts": {
    ...
    "build": "vue-cli-service build"
  }
  ...
}
           

也就是說,這個指令實際上是在調用

vue-cli-service

服務的

build

指令。

根據vue-cli的文檔介紹,build指令後面可以跟一個mode參數,定義打包模式,預設的打包模式包括

production

development

test

三個,它們的行為主要是把全局的

process.env.NODE_ENV

變量置為對應的值(即

production

development

test

)。在省略mode參數的情況下,預設值是

production

,即生産模式。

除了這三個預設模式外,我們還可以自定義打包模式。假如我們想定義一個專門打包page1的打包模式,就可以這樣一個指令:

"scripts": {
    "build-page1": "vue-cli-service build --mode page1"
  }
           

我們希望,當執行

npm run build-page1

指令時,webpack就會自動把page1打包出來。

但顯然隻修改這裡是不夠的,webpack并不知道page1是什麼模式,以及它應該有哪些行為。接下來我們需要為page1這個打包模式定義行為。

2. 定義模式行為

啟用一個打包模式的本質含義,其實是啟用一組特定的環境變量。

比如,

production

模式會把

process.env.NODE_ENV

的值置為

production

,而

process.env

是webpack所在的node環境提供的全局變量。這樣,在代碼中,隻需要根據

process.env.NODE_ENV

的值就可以判斷目前處于哪種打包模式了,代碼可以根據不同的打包模式産生不同的行為。

對于自定義的打包模式,我們也可以指定一組全局變量,以使代碼産生不同的行為。vue-cli文檔規定,每個自定義模式對應的變量應該定義在根目錄下的

.env.xxx

檔案内。比如我們的打包模式名為

page1

,那麼就需要在項目根目錄下建立一個

.env.page1

(注意,這裡是沒有字尾的)檔案:

多頁vue應用的單頁面打包方法(内含打包模式的應用)一、簡介二、實作過程三、打包模式的應用總結

當指定打包模式為

page1

時,webpack就會啟用這個檔案中所定義的變量。檔案内可以這樣定義變量:

.env.page1

NODE_ENV = 'production'
page = 'page1'
           

現在,當使用打包模式

page1

時,webpack就會讀取這個環境檔案,然後把這裡定義的變量逐個添加到全局對象

process.env

上。是以此時

process.env.page

的值就是字元串

'page1'

(NODE_ENV的值需要在這裡手動設定為

'production'

,否則會以開發模式打包)。

向全局變量注冊了變量page之後,我們就可以在程式中根據它定義打包行為了。

3. 定義打包邏輯

之前我們定義多頁應用的配置時,pages字段配置的是固定的值,也就是定義了三個打包入口。現在有了全局變量

process.env.page

,我們就不需要設為定值了,而是可以根據這個變量的值,動态定義打包入口。此時vue.config.js可以進行如下改造:

function resolvePages(page){
  let page1 = {
    entry: 'src/pages/page1/main.js',
    template: 'public/index.html',
    filename: 'page1.html',
  };
  let page2 = {
    entry: 'src/pages/page2/main.js',
    template: 'public/index.html',
    filename: 'page2.html',
  };
  let page3 = {
    entry: 'src/pages/page3/main.js',
    template: 'public/index.html',
    filename: 'page3.html',
  };
  return page === 'page1' ? { page1 } : 
    { page1, page2, page3 };
}
module.exports = {
  pages: resolvePages(process.env.page),
}
           

我們現在讀取

process.env.page

的值進行判斷,如果它的值是

page1

,那麼說明我們處于

page1

打包模式下,于是resolvePages函數傳回的對象僅包括

page1

這一個頁面的入口,否則就傳回三個打包入口,進行完整多頁應用的建構。

基于這個原理,我們同樣可以定義

page2

page3

的打包模式,甚至定義更加複雜的打包模式(如同時打包

page1

page2

),此時resolvePages函數的傳回值隻是稍微複雜一些:

return page === 'page1' ? { page1 } : 
  page === 'page2' ? { page2 } : 
  page === 'page1,page2' ? { page1, page2 } :
  ...
  { page1, page2, page3 };
           

現在一切準備就緒。

我們執行

npm run build-page1

指令時,vue-cli會先讀取指定的

page1

模式對應的

.env.page1

檔案,它會為

process.env

新增環境變量

page

。然後vue-cli會去讀取

vue.config.js

配置檔案中的pages字段,調用resolvePages函數,并傳入變量

process.env.page

,得到打包入口對象為:

{ page1 }

,由于隻有一個打包入口,是以vue-cli會調用webpack的打包服務,對該頁面進行單獨建構。

有人可能會問,難道隻有打包時才能指定mode嗎?其實不是的,

serve

指令也有mode參數。根據以上過程,你也可以單獨啟動某一個頁面,此時你隻需要定義下面這樣的腳本:

{
  ...
  "scripts": {
    "serve-page1": "vue-cli-service serve --mode page1"
  }
}
           

與打包過程沒有什麼差别,這裡就不再贅述了。

需要注意的是,public檔案夾下的資源是靜态資源,無論使用任何打包模式,它們都會被直接拷貝到dist檔案夾下。

三、打包模式的應用

打包模式的應用不僅在于單頁打包,我們舉一個更常見的例子:假設我們的代碼打包後可能被派發到多個項目上,而這些項目之間卻存在一些細小的差别(比如某個表格的樣式不同)。如果我們為每個項目都單獨建立一份代碼,那麼代碼庫将變得極難維護。這時候,打包模式就可以派上用場了。

我們可以為這些項目分别建立單獨的打包指令,如:

{
  "scripts": {
    "build-project1": "vue-cli-service build --mode project1",
    "build-project2": "vue-cli-service build --mode project2",
  }
}
           

然後在根目錄下分别為每個打包模式定義一個環境檔案:

.env.project1

.env.project2

。我們在這裡分别定義一組全局變量:

.env.project1

.env.project2

這裡需要強調的是,如果需要在src路徑下的代碼中引用env中的某個變量,那麼這個變量必須以

VUE_APP_

開頭,否則結果都會是undefined(在src之外的代碼中沒有這個限制,如上面我們在vue.config.js中引用的變量就沒有遵循這個限制,當然你可以更規範地對所有自定義變量添加這個字首,以防止出錯)。

現在,當執行

npm run build-project1

時,

process.env.VUE_APP_PROJECT

的值就是

project1

,我們可以在代碼中根據這個值來區分不同的項目。比如在某個元件中,我們需要對項目1添加一些額外的邏輯:

methods: {
  doSomething(){
    if(process.env.VUE_APP_PROJECT === 'project1'){
      // 對project1項目添加額外的邏輯
      ...
    }
  }
}
           

當你運作

npm run build-project1

打包指令時,if語句的内容就會生效,反之,在其他模式下,它不會生效。同樣的,你也可以配置項目1專屬的啟動指令:

你可以運作

npm run serve-project1

來啟用project1環境。

總結

通過學習在多頁應用中打包單個頁面,我們學會了如何自定義打包模式,這應該是本文最重要的知識點。将打包模式推廣,我們學會了如何在一份代碼中添加多個項目的邏輯,這使得我們維護多個項目分支的成本大大降低。打包模式的用途可能還遠不止這些,希望讀者了解它,并熟練運用。