1. 程式人生 > >「 Vue×Docker」伺服器部署Vue遇到的那些坑

「 Vue×Docker」伺服器部署Vue遇到的那些坑

專案之前一直在電腦本地做的,廢棄了很久才想起來部署到伺服器上。因為是第一次用vue,釋出時遇到了很多問題,用了5個小時才解決掉。
主要問題有兩個:
1. 不清楚如何釋出vue專案,伺服器上npm run dev只能本地測試使用。
2. 資料介面的代理載入不出資源。

伺服器環境:

linux 7.0 x86_64
npm 6.1.0
vue 2.9.6
docker 17.12.0-ce
開放埠8003(前端)和3000(介面)
注:以下過程為已安裝好npm/vue-cli/docker且資料介面正常工作為前提。

vue在本地測試執行時是使用 $ npm run dev。
但vue環境真正的部署是要通過webpack構建成html後通過nginx等web服務解析工作的。
首先看vue的配置檔案config/index.js,生產環境部署vue時網上的案例常遇到資源載入404的問題,根本原因是在構建配置時“assetsPublicPath”的問題,webpack會根據這一項配置修改資源引用的路徑。

module.exports = {
  ...
  build: {
    index: path.resolve(__dirname, '../dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    ...
  }
}

如果是配置“assetsPublicPath: ‘/’”,那麼就要把構建出來的內容放到nginx的html根目錄下(不是伺服器的根目錄),這樣資源才能正常載入。因為伺服器沒有直接安裝nginx,所以借用了docker環境。

$ sudo npm run build // vue專案打包

打包後生成的html檔案是在專案的dist目錄下,會產生一個index.html和static資料夾。也可以直接在計算機本地打包後,只將dist資料夾傳到伺服器上。
第二個問題是我的vue專案中請求資料使用了代理,即.get(‘/api/……’),而不是.get(‘http://……’)。
在本地測試時可以直接在vue的配置檔案config/index.js的dev部分配置代理,用/api替換掉了 http: //localhost:3000/。

module.exports = {
  dev: {
    assetsSubDirectory: 'static'
, assetsPublicPath: '/', proxyTable: { '/api': { target: 'http://localhost:3000/', changeOrigin: true, pathRewrite: { '^/api': '/', }, }, }, ... }

但在伺服器上該方法不適用,所以如果不修改nginx配置的話,是無法請求到/api/……的資料的。建立一個nginx配置檔案default.conf,內容如下:

server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    location ^~/api/ {        
        rewrite ^/api/(.*)$ /$1 break;        
        proxy_set_header   Host             $host;        
        proxy_set_header   x-forwarded-for  $remote_addr;        
        proxy_set_header   X-Real-IP        $remote_addr;        
        proxy_pass http://127.0.0.1:3000;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

關鍵部分在於 location ^~/api/{…},是將原本寫在index.js配置檔案中的代理用nginx來實現。當nginx接收到 http: //xxx.xxx.xxx.xxx:8003/api/… 的請求時自動轉發到3000埠。
準備完畢後,docker拉取nginx的映象,我使用的版本是[email protected]。不用編寫dockerfile,直接例項化容器:

$ sudo docker run -d --name vue -p 8003:80 -v /mnt/donghan/default.conf:/etc/nginx/conf.d/default.conf -v /mnt/donghan/vue/dist:/usr/share/nginx/html nginx:latest

在這裡要注意的幾個引數:

-p 8003:80 // 容器內的80埠對映到外部主機8003埠
-v /mnt/donghan/vue/dist:/usr/share/nginx/html // 將vue生成的html檔案直接匯入到容器中nginx的根目錄下,前面的是我伺服器上存放dist的目錄
-v /mnt/donghan/default.conf:/etc/nginx/conf.d/default.conf // 匯入nginx環境配置檔案

經過這麼一折騰,vue才能夠在伺服器上真正部署起來。整個流程做下來還是踩了不少坑,網上的那些部落格解決方案都很零散。在沒有描述詳細伺服器環境的情況下,很難根據一句話兩句話搞定問題。所以在這裡也希望大家以後寫部落格的時候能更詳細的說說伺服器上的環境和問題的描述,一起加油。

題外話

這次做的是express+vue+mongodb的一個站,基本核心都是nodejs,然!而!就在部署完之後我得到了這個很難過的訊息:「Node之父Ryan Dahl說:Node 失誤太多無力迴天,Deno 前景明朗。」
nodejs零零散散接觸了有一年,現在已經慢慢熟悉了,居然有種老友訣別之感。但也確實也存在各種各樣的問題,Ry的PPT上的這張圖相信大家都深有感觸。

希望下一代的Nodejs——Deno能越走越遠,也祝js家族更加壯大。