最近的一个项目要在手机淘宝客户端里面开发网页,因为淘宝目前全站https,因此在开发环境搭建时候遇到了以前没有料想到的一些问题,这里分享一下此次踩坑的经历。javascript
在这个项目当中使用了 webpack 做为模块加载器,使用 webpack 进行前端开发通常会同时使用 webpack-dev-server 来提升开发的效率。前端
webpack-dev-server 会利用 Express 创建一个服务器,将打包后的 js 文件 引入到页面当中,即时反映对文件的修改。java
在配置好 webpack 以后,运行以后发现 webpack-dev-server 加载的 js 文件并不能在页面上显示。通过一番研究以后发现这里涉及到了 https 的 Mixed Content 问题。node
若是一个 HTTPS 网页当中有请求 HTTP 的资源,这种网页就被称为 Mixed Content Page。webpack
Mixed Content 被分为两类 Optionally-blockable Content 和 Blockable Content。ios
Optionally-blockable Content 包括一些引入风险较低的资源:git
<img>github
<audio>web
<video>浏览器
在现代的浏览器当中这些资源即时不是经过 https 引用也会被加载到页面当中。
而其余的引入风险较高的资源就被称为 Blockable Content,包括 <script>、<link>、<iframe> 等。这些资源若是是经过 http 协议引用的话是不会被加载到页面当中的。
既然知道问题所在,解决的方法也就很是简单了,修改一下 webpack-dev-server 的配置,启用 https 协议。
new WebpackDevServer(webpack(config), { // 省略其他代码 https: true // 启用 https }).listen(3000, function(err, res) {});
启用了 https 协议以后,依然没法正常访问 webpack 打包的资源。在桌面浏览器访问一些 https 网站时候常常会看到这样的画面:
出现这个画面的缘由是网站的证书不受信任,在桌面端的浏览器能够点击继续前往来访问不受信任的资源。而在移动端的浏览器除了少数的浏览器(如:uc浏览器)能够访问不受信任的资源以外,大部分的浏览器会直接禁止访问。
要在手机浏览器上访问 https 协议的 webpack-dev-server 服务器上面的资源,就要安装匹配服务器的证书。
打开 node-module 找到 webpack-dev-server 会发现一个叫 ssl 的文件夹,这就是用来放置 webpack-dev-server 证书的地方。
如今把客户端用的 ca.crt 证书安装到手机上,搞定。
安装完证书以后再打开手机淘宝,发现静态资源依然不能访问,打开手机安装的证书发现 webpack-dev-server 的证书已通过期了T_T。
再看看 webpack-dev-server github 的项目,发现这些证书最近的更新是一年前。看来如今只能本身去生成新的自签证书了。
查看 webpakc-dev-server 的代码:
// using built-in self-signed certificate if no certificate was configured options.https.key = options.https.key || fs.readFileSync(path.join(__dirname, "../ssl/server.key")); options.https.cert = options.https.cert || fs.readFileSync(path.join(__dirname, "../ssl/server.crt")); options.https.ca = options.https.ca || fs.readFileSync(path.join(__dirname, "../ssl/ca.crt"));
要替代原来的证书须要生成这三个文件。
生成自签的证书最多见的方法就是用 OpenSSl 工具,在 Mac OSX 上面默认已经安装了。
首先要生成一个证书颁发机构(CA)根证书,利用这个根证书能够建立客户端使用的证书,还须要用根证书去对服务端使用的证书进行签名。
建立CA证书首先建立私钥文件,2048指的是私钥的位数:
openssl genrsa -out CA.key 2048
而后建立证书:
openssl req -x509 -new -key CA.key -out CA.crt -days 730
建立证书的过程中须要填写一系列的信息,其中要留意 Common Name 须要填写服务器的域名,通过我的的测试在安卓机上即便证书是被信任的,可是 Common Name 的域名并不对应的话资源一样是没法访问的。CA.crt 已经能够发送到移动设备上面使用了。
而后建立服务端使用的证书。一样先建立私钥文件:
openssl genrsa -out server.key 2048
而后建立一个证书请求,填写与CA根证书相应的信息:
openssl req -new -out server.req -key server.key
利用CA证书签发服务端使用的证书:
openssl x509 -req -in server.req -out server.crt -CAkey CA.key -CA CA.crt -days 365 -CAcreateserial -CAserial serial
最后把生成的证书替换 ssl 文件夹里面的内容,大功告成,webpack-dev-server 上的资源能够成功访问了。
参考
本文同步于个人我的博客 http://blog.acwong.org/2016/03/05/change-webpack-certificate/