本地HTTPS站点用ParcelJS打包时出现Chrome WebSocket错误
首先先确认下你遇到的错误日志:
hmr-runtime.js:29 WebSocket connection to 'wss://ysg4206.draper.com:61396/' failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR parcelRequire.../../../node_modules/parcel-bundler/src/builtins/hmr-runtime.js @ hmr-runtime.js:29
这个问题其实是Parcel的热模块替换(HMR)机制导致的,哪怕你没在项目里主动使用WebSocket,只要你的项目曾经用Parcel构建过,打包后的代码里就会带上HMR的运行时文件(就是上面提到的hmr-runtime.js),它会自动尝试连接Parcel开发服务器的WebSocket端口,而你现在用IIS部署HTTPS站点,就触发了这个无意义的SSL错误。
问题根源拆解
- 当你用IIS部署HTTPS站点时,HMR runtime会自动切换到
wss协议(因为站点是HTTPS)去连接Parcel开发服务器的WebSocket端口,而这个61396是Parcel开发服务器启动时随机分配的端口,此时你并没有启动Parcel开发服务器,再加上IIS的SSL证书和Parcel开发服务器的自签证书不匹配,就抛出了ERR_SSL_PROTOCOL_ERROR。 - 而HTTP部署时,HMR用的是
ws协议,即使连接失败,浏览器只会在控制台输出普通的连接失败日志,不会触发SSL类的错误,所以你看不到这条报错。
可行的解决方法
这里给你几个按优先级排序的方案:
构建生产环境包(推荐)
Parcel在开发模式下会自动注入HMR runtime,而生产构建时会自动移除这部分代码。你只需要重新用生产模式构建项目:parcel build your-entry-file.html把构建好的生产包部署到IIS,这样HMR相关的代码就完全不存在了,自然不会有WebSocket连接尝试。
禁用HMR(开发测试临时用)
如果你只是在开发阶段临时用IIS部署测试,不想重新构建生产包,可以在启动Parcel时禁用HMR:parcel serve your-entry-file.html --no-hmr这样打包后的代码就不会包含HMR runtime,部署到IIS后就不会出现这个错误。
手动移除HMR代码(临时hack)
如果你已经有打包好的文件,不想重新构建,可以找到打包后的代码里引入hmr-runtime.js的部分,直接注释或删除相关代码。不过这个方法不推荐,因为下次构建代码时HMR runtime又会被加回来,只能作为临时应急用。
最后补充下:你疑惑的61396端口是Parcel开发服务器启动时随机分配的WebSocket端口,每次启动Parcel这个端口可能都会变,所以它不是你配置的固定端口,这就是你不清楚它来源的原因。
内容的提问来源于stack exchange,提问作者Dr.YSG

