Vue 項目打包部署總結

使用 Vue 做前後端分離項目時,通常前端是單獨部署,用戶訪問的也是前端項目地址,因此前端開發人員很有必要熟悉一下項目部署的流程與各類問題的解決辦法了。

Vue 項目打包部署本身不復雜,不過一些前端同學可能對服務器接觸不多,部署過程中還是會遇到這樣那樣的問題。本文介紹一下使用 nginx 服務器代理前端項目的方法以及項目部署的相關問題,內容概覽:

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

1. 準備一臺服務器

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

如果你只是想體驗一下,可以嘗試各大廠的雲服務器免費試用套餐,比如華爲雲免費試用,本文相關操作即是在華爲雲上完成的。

不過如果想時常練練手,我覺得可以購買一臺雲服務器,比如上面的華爲雲或者阿里雲都還挺可靠。

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 服務代理的文件夾:

1)、創建文件夾 / www,並創建 index.html,寫入 "Hello world" 字符串

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

2)、修改 root 值爲 /www

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

4)、加載 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/* root@117.78.4.26:/www
或
rsync -avr --delete-after dist/* root@117.78.4.26:/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/* root@117.78.4.26:/www"
  },

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

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

3、 同步 ssh key

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

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

ssh-copy-id -i ~/.ssh/id_rsa.pub root@117.78.4.26


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


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

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

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

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

至此,常規情況下發布 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 處於同級別的:

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

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

  2. 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 文件夾下的靜態資源:

關於靜態資源的問題,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 等的表現錯亂,使用測試項目分別使用兩種配置打包發佈,審查元素就能看出區別。在頁面上有兩個 router-link,Home 和 About:

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

  1. publicPath 配置爲./ 或者空串:

  2. publicPath 配置爲 / test:

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

五、結語

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

來源:https://wintc.top/article/29

推薦關注「前端大全」,提升前端技能

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/xwqPuZ5KiEFqC8Wfey8WQQ