webpack-dev-server + nginx + node調試https微信受權網頁

概述

通常狀況下,在使用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

nginx + host 配置url

對於須要公衆號微信受權的網頁,每一個公衆號均可以配置兩個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

  1. host配置,將abc.com代理到本地地址
127.0.0.1 abc.com
複製代碼

只配置host的話能夠經過abc.com:8080/test/abc來訪問網頁。這時候熱更新請求的地址是http://abc.com:8080/sockjs-node/infogit

  1. nginx配置
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

https協議熱更新

首先在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選項,用於配置熱更新請求的端口和主機,官網文檔中能夠查到。

因此改造須要三步。

  1. 入口改造
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]
];
複製代碼

由於不要讀取這裏的配置了。

  1. webpack-dev-server添加該配置
sockPort: 443
複製代碼
  1. nginx轉發/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'便可。

相關文章
相關標籤/搜索