通常狀況下,在使用webpack-dev-server熱更新的時候,使用的域名都是localhost/127.0.0.1之類的,都是基於http協議的。javascript
基於nodejs對webpack入口的處理以下:前端
webpackConfig.entry[entryKey] = [
// 這裏會發送一次請求
'webpack-dev-server/client?http://0.0.0.0:8080',
'webpack/hot/dev-server',
...webpackConfig.entry[entryKey]
];
複製代碼
熱更新成功後,瀏覽器會以當前域名+端口發送一個用於熱更新的請求。該請求默認域名是webpack入口配置中webpack-dev-server/client?http://0.0.0.0:8080
中問號後面的參數,若是參數中主機名是0.0.0.0
,將會被替換成self.location.hostname
。/sockjs-node
請求被webpack-dev-server服務器處理。 java
具體的替換規則有多種狀況,能夠參考webpack-dev-server中createSocketUrl的源碼。node
對於須要公衆號微信受權的網頁,每一個公衆號均可以配置兩個js安全回調域名。因此網頁的域名必須是公衆號中配置存在的。好比原始網頁訪問地址是http://127.0.0.1:8080/test/abc
。公衆號配置的安全回調域名是abc.com
。若是該網頁須要通過微信受權(受權過程不表),那麼須要經過配置讓網頁的域名變成abc.com
。訪問地址就是abc.com/test/abc
。不然微信會報redirect_uri參數錯誤。webpack
經過host配置以及nginx端口轉發後,就能夠經過abc.com/test/abc
訪問http://127.0.0.1:8080/test/abc
了。配置以下:nginx
127.0.0.1 abc.com
複製代碼
只配置host的話能夠經過abc.com:8080/test/abc
來訪問網頁。這時候熱更新請求的地址是http://abc.com:8080/sockjs-node/info
。git
server {
listen 80;
listen 443 ssl;
server_name abc.com;
ssl_certificate /usr/local/etc/nginx/abc.crt;
ssl_certificate_key /usr/local/etc/nginx/abc.key;
# 省略一些配置
# 3200是node端口
location / {
proxy_pass http://127.0.0.1:3200/;
# 其餘配置
}
# 8080 是前端資源端口
location /test {
proxy_pass http://127.0.0.1:8080/test;
# 其餘配置
}
}
複製代碼
完成這兩步,就能夠經過http://abc.com/test/abc
來訪問網頁了,而且能夠經過微信受權。可是仍然是在http的協議下。在這種狀況下,熱更新請求的地址仍然是http://abc.com:8080/sockjs-node/info
,顯然nginx沒有監聽8080端口以及/sockjs-node,由於8080端口已經被webpack-dev-server佔用了。可是該請求還是能夠正常打開的,不通過nginx也能夠,請求的就是本地資源,該請求被webpack-dev-server服務器處理了。。github
在某些狀況下,須要https訪問,好比service-worker
,微信支付(支付目錄是https協議的)等。web
首先在nginx中配置https://abc.com的證書,並監聽443端口。上述代碼中已經配置。打開https://abc.com/test/abc
鏈接,頁面能夠打開。熱更新請求的地址是https://abc.com:8080/sockjs-node/info
,能夠看到仍然是8080端口。由於根據createSocketUrl的源碼,在入口中配置了webpack-dev-server/client?http://0.0.0.0:8080
的狀況下,若是該連接query參數中有端口而且webpack-dev-server沒有配置端口的狀況下,就使用該端口。瀏覽器
這時候狀況就不同了,打不開熱更新請求的地址。8080沒有通過nginx,該請求請求的仍然是webpack-dev-server服務器資源。可是webpack-dev-server服務器沒有配置https證書,致使沒法訪問到。
關鍵點來了。若是該請求通過nginx,再代理到本地webpack-dev-server服務器就行了。由於nginx中配置了https證書。
查了好長時間,看到一個相關issue,在webpack-dev-server5月份發佈的3.4.0 (2019-05-17)release版本中,提供了sockPort,sockHost選項,用於配置熱更新請求的端口和主機,官網文檔中能夠查到。
因此改造須要三步。
webpackConfig.entry[entryKey] = [
// 這裏會發送一次請求
'webpack-dev-server/client?http://0.0.0.0:8080',
'webpack/hot/dev-server',
...webpackConfig.entry[entryKey]
];
複製代碼
變動爲
webpackConfig.entry[entryKey] = [
// 這裏會發送一次請求
'webpack-dev-server/client',
'webpack/hot/dev-server',
...webpackConfig.entry[entryKey]
];
複製代碼
由於不要讀取這裏的配置了。
sockPort: 443
複製代碼
/sockjs-node
location /sockjs-node {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
複製代碼
簡單來講,經過配置sockPort後,熱更新請求變成了https://abc.com/sockjs-node/info
,443能夠省略。443端口被nginx轉發到本地http協議的8080端口,最終請求的是webpack-dev-server服務器。如圖:
這裏幾乎同時發了兩個請求。通過測試,能夠改成只發一個。在上面的配置中去掉webpack-dev-server/client
這一行,而且webpack-dev-server添加配置sockHost: 'abc.com'
便可。