Vue項目打包部署的實戰過程記錄

前言

使用Vue做前後端分離項目時,通常前端是單獨部署,用戶訪問的也是前端項目地址,因此前端開發人員很有必要熟悉一下項目部署的流程與各類問題的解決辦法瞭。Vue項目打包部署本身不復雜,不過一些前端同學可能對服務器接觸不多,部署過程中還是會遇到這樣那樣的問題。本文介紹一下使用nginx服務器代理前端項目的方法以及項目部署的相關問題,內容概覽:

 

一、準備工作——服務器和nginx使用

1. 準備一臺服務器

我的是ubuntu系統,linux系統的操作都差不多。沒有服務器怎麼破?

如果你隻是想體驗一下,可以嘗試各大廠的雲服務器免費試用套餐,比如華為雲免費試用,本文相關操作即是在華為雲上完成的。不過如果想時常練練手,我覺得可以購買一臺雲服務器,比如上面的華為雲或者阿裡雲都還挺可靠。我的個人網站就是部署在阿裡雲,你可以點擊我的推廣鏈接進行購買,近期有活動首次購買不到100塊/年。

2. nginx安裝和啟動

輕裝簡行,這部分不作過多贅述(畢竟網上相關教程一大堆),正常情況下僅需下面兩個指令:

# 安裝,安裝完成後使用nginx -v檢查,如果輸出nginx的版本信息表明安裝成功
sudo apt-get install nginx
# 啟動
sudo service nginx start

啟動後,正常情況下,直接訪問 http://服務器ip 或 http://域名 (本文測試用的服務器沒有配置域名,所以用ip,就本文而言,域名和ip沒有太大區別)應該就能看到nginx服務器的默認頁面瞭——如果訪問不到,有可能是你的雲服務器默認的http服務端口(80端口)沒有對外開放,在服務器安全組配置一下即可。

 

3. 瞭解nginx: 修改nginx配置,讓nginx服務器代理我們創建的文件

查看nginx的配置,linux系統下的配置文件通常會存放在/etc目錄下,nginx的配置文件就在/etc/nginx文件夾,打開文件/etc/nginx/sites-available/default(nginx可以有多個配置文件,通常我們配置nginx也是修改這個文件):

 

可以看到默認情況下,nginx代理的根目錄是/var/www/html,輸入 http://服務器ip會訪問這個文件夾下的文件,會根據index的配置值來找默認訪問的文件,比如index.html、index.htm之類。

我們可以更改root的值來修改nginx服務代理的文件夾:

創建文件夾/www,並創建index.html,寫入”Hello world”字符串

mkdir /www
echo 'Hello world' > /www/index.html

修改root值為 /www

sudo nginx -t 檢查nginx配置是否正確

加載nginx配置:sudo nginx -s reload

再次訪問頁面,發現頁面內容已經變成瞭我們創建的index.html:

 

二、Vue項目打包同步文件到遠程服務器

1. 打包

默認情況下,使用vue-cli創建的項目,package.json裡的script應該已經配置瞭build指令,直接執行yarn build 或者 npm run build即可。

2. 同步到遠程服務器

我們使用nginx部署Vue項目,實質上就是將Vue項目打包後的內容同步到nginx指向的文件夾。之前的步驟已經介紹瞭怎樣配置nginx指向我們創建的文件夾,剩下的問題就是怎麼把打包好的文件同步到服務器上指定的文件夾裡,比如同步到之前步驟中創建的/www。同步文件可以在git-bash或者powershell使用scp指令,如果是linux環境開發,還可以使用rsync指令:

scp -r dist/* [email protected]:/www
或
rsync -avr --delete-after dist/* [email protected]:/www 

註意這裡以及後續步驟是root使用用戶遠程同步,應該根據你的具體情況替換root和ip(ip換為你自己的服務器IP)。

為瞭方便,可以在package.json腳本中加一個push命令,以使用yarn為例(如果你使用npm,則push命令中yarn改成npm  run即可):

 "scripts": {
    "build": "vue-cli-service build",
    "push": "yarn build && scp -r dist/* [email protected]:/www"
  },

這樣就可以直接執行yarn push 或者npm run push直接發佈瞭。不過還有一個小問題,就是命令執行的時候要求輸入遠程服務器的root密碼(這裡使用root來連接遠程的,你可以用別的用戶,畢竟root用戶權限太高瞭)。

為瞭避免每次執行都要輸入root密碼,我們可以將本機的ssh同步到遠程服務器的authorized_keys文件中。

3. 同步ssh key

生成ssh key:使用git bash或者powershell執行ssh-keygen可以生成ssh key。會詢問生成的key存放地址,直接回車就行,如果已經存在,則會詢問是否覆蓋:

同步ssh key到遠程服務器,使用ssh-copy-id指令同步

ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

輸入密碼後,之後再次同步就不需要輸入密碼瞭。其實ssh_key是同步到瞭服務器(此處是root用戶傢目錄)~/.ssh/authorized_keys文件裡:

當然你也可以手動復制本地~/.ssh/id_rsa.pub(註意是pub結尾的公鑰)文件內容追加到服務器~/.ssh/authorized_keys的後面(從命名可以看出該文件可以存儲多個ssh key)

註意:這裡全程使用的是root用戶,所以沒有文件操作權限問題。如果你的文件夾創建用戶不是遠程登錄用戶,或許會存在同步文件失敗的問題,此時需要遠程服務器修改文件夾的讀寫權限(命令 chmod)。

創建瞭一個測試項目(點擊本鏈接可以在gihub查看)[1]試一下,打包、文件上傳一句指令搞定啦:

 

訪問一下,果然看到瞭我們熟悉的界面:

 

至此,常規情況下發佈Vue項目就介紹完瞭,接下來介紹非域名根路徑下發佈以及history路由模式發佈方法。

三、非域名根路徑發佈

有時候同一臺服務器同一端口下可能會根據目錄劃分出多個不同的項目,比如我們希望項目部署到http://a.com/test下,這樣訪問http://a.com/test訪問到的是項目的首頁,而非test前綴的地址會訪問到其它項目。此時需要修改nginx配置以及Vue打包配置。

1. nginx配置

隻需要添加一條location規則,分配訪問路徑和指定訪問文件夾。我們可以把/test指向之前創建的/www文件夾,這裡因為文件夾名稱和訪問路徑不一致,需要用到alias這個配置:

 

如果文件夾名稱與訪問路徑一致都為test,那這裡可以用root來配置:

 

這裡要將/test配置放到/之前,意味著在路由進入的時候,會優先匹配/test。如果根路徑/下的項目有子路由/test,那http://xxxx/test隻會訪問到/www裡的項目,而不會訪問該子路由。

2. 項目配置

為瞭解決打包後資源路徑不對的問題,需要在vue.config.js中配置publicPath,這裡有兩種配置方式,分別將publicPath配置為./和/test:

 

更新nginx配置,發佈後即可正常訪問啦。這裡的兩種配置方式是有區別的,接下來會看一下它們的區別。如果不進行項目配置,直接發佈訪問會出現JS、CSS等資源找不到導致頁面空白的問題:

 

該問題原因是資源引用路徑不對,頁面審查元素可以看到,頁面引用的js都是從根路徑下引用的:

 

查看打包後的文件結構,可以看到js/css/img/static等資源文件是與index.html處於同級別的:

 

對於兩種配置方式,看看都是怎麼生效的:

publicPath配置為./, 打包後資源引用路徑為相對路徑:

publicPath配置為/test,打包後資源相對路徑為從域名根目錄開始的絕對路徑:

兩種配置都可以正確地找到JS、CSS等資源。不過還有個問題,那就是static中的靜態資源依舊會找不到。

3. 絕對路徑引用的靜態資源找不到的問題

因為在打包過程中,public下的靜態資源都不會被webpack處理,我們需要通過絕對路徑來引用它們。當項目部署到非域名根路徑上時,這點非常頭疼,你需要在每個引用的URL前面加上process.env.BASE_URL(該值即對應上文配置的publicPath),以使得資源能被正常訪問到。我們可以在main.js把這個變量值綁定到Vue.prototype,這樣每個Vue組件都可以使用它:

Vue.prototype.$pb = process.env.BASE_URL

在模板中使用:

<img :src="`${$pb}static/logo.png`">

然而,更加頭疼並且沒有良好解決方案的問題是在組件style部分使用public文件夾下的靜態資源:

  • 如果需要使用圖片等作為背景圖片等,盡量使用內聯方式使用吧,像在模板中使用一樣。
  • 如果需要引入樣式文件,則在index.html中使用插值方式引入吧。

關於靜態資源的問題,vue-cli的推薦是盡量**將資源作為你的模塊依賴圖的一部分導入(即放到assets中,使用相對路徑引用),**避免該問題的同時也帶來其它好處:

 

四、history模式部署

默認情況下,Vue項目使用的是hash路由模式,就是URL中會包含一個#號的這種形式。#號以及之後的內容是路由地址的hash部分。正常情況下,當瀏覽器地址欄地址改變,瀏覽器會重新加載頁面,而如果是hash部分修改的話,則不會,這就是前端路由的原理,允許根據不同的路由頁面局部更新而不刷新整個頁面。H5新增瞭history的pushState接口,也允許前端操作改變路由地址但是不觸發頁面刷新,history模式即利用這一接口來實現。因此使用history模式可以去掉路由中的#號。

1. 項目配置

在vue-router路由選項中配置mode選項和base選項,mode配置為’history’;如果部署到非域名根目錄,還需要配置base選項為前文配置的publicPath值(註意:此情況下,publicPath必須使用絕對路徑/test的配置形式,而不能用相對路徑./)

 

2. nginx配置

對於history模式,假設項目部署到域名下的/test目錄,訪問http://xxx/test/about的時候,服務器會去找/test指向的目錄下的about子目錄或文件,很顯然因為是單頁面應用,並不會存在a這個目錄或者文件,就會導致404錯誤:

 

我們要配置nginx讓這種情況下,服務器能夠返回單頁應用的index.html,然後剩下的路由解析的事情就交給前端來完成即可。

 

這句配置的意思就是,拿到一個地址,先根據地址嘗試找對應文件,找不到再試探地址對應的文件夾,再找不到就返回/test/index.html。再次打開剛才的about地址,刷新頁面也不會404啦:

 

3. history模式部署到非域名根路徑下

非域名根目錄下部署,首先肯定要配置publicPath。需要註意的點前面其實已經提過瞭,就是這種情況下不能使用相對路徑./或者空串配置publicPath。為什麼呢?

原因是它會導致router-link等的表現錯亂,使用測試項目[2]分別使用兩種配置打包發佈,審查元素就能看出區別。在頁面上有兩個router-link,Home和About:

 

兩種配置打包後的結果如下。

publicPath配置為./或者空串:

publicPath配置為/test:

publicPath配置為相對路徑的router-link打包後地址變成瞭相對根域名下地址,很明顯是錯誤的,所以非域名根路徑部署應該將publicPath配置為完整的前綴路徑。

五、結語

關於Vue項目發佈的相關問題就先總結這麼多,幾乎在每一步都踩過坑才有所體會,有問題歡迎各位同學一起探討。

參考資料

[1]Vue項目打包發佈: https://github.com/Lushenggang/vue-publish-test

[2]Vue項目打包部署測試項目地址: https://github.com/Lushenggang/vue-publish-test

到此這篇關於Vue項目打包部署的文章就介紹到這瞭,更多相關Vue項目打包部署內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: