通常状况下,在使用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'
便可。