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'便可。

相关文章
相关标签/搜索