puma-devとwebpackerを使ってHTTPSで開発する

OneSignalを利用してブラウザPush通知機能を追加した際に、HTTPSでのみ使用する前提のJSライブラリを入れたのが原因で、開発環境でもHTTPSを利用する必要が出た。

前提として、

  • Mac OSX
  • puma-dev
  • webpacker

を利用している。puma-devはHTTPSに対応していて、自動でオレオレ証明書を作ってくれる。

webpack-dev-serverもHTTPSに対応している。次のようにconfig/webpacker.ymlのhttpsをtrueにするとhttps://example.com:8080/packs/application.jsといったURLでwebpackがコンパイルしたjsにアクセスできる。

development:
  <<: *default

  dev_server:
    host: example.com
    port: 8080
    https: true

問題はオレオレ証明書の認証。chromeであれば毎回https://example.com:8080/packs/application.js直接アクセスして認証する必要がある。認証しないとJS読み込みでエラーになる。毎回やるのは大変面倒*1

chromeでwebpack-dev-serverが生成した証明書を見ると「Subject Alt Nameが設定されていない」というエラーが出ていて、これにも対応する必要がありそう。puma-devはこのエラーは出ていなかった。

解決方法

次のコマンドで証明書を生成する

openssl req \
    -newkey rsa:2048 \
    -x509 \
    -nodes \
    -keyout server.pem \
    -new \
    -out server.pem \
    -subj /CN=savanna.dev \
    -reqexts SAN \
    -extensions SAN \
    -config <(cat /System/Library/OpenSSL/openssl.cnf \
        <(printf '[SAN]\nsubjectAltName=DNS:savanna.dev')) \
    -sha256 \
    -days 3650

config/webpack/server.pem など適当な場所に置く。

キーチェーンへこの証明書を登録し、「常に信頼」の設定にする。

次のようにしてwebpack-dev-serverを起動する

./bin/webpack-dev-server --cert ./config/webpack/server.pem --key ./config/webpack/server.pem

オプションを毎回つけるのがダルいのであればconfig/webpack/development.jsを次のようにしておく

const fs = require('fs');
// 省略
devServer: {
  clientLogLevel: 'none',
  https: {
    cert: fs.readFileSync('./config/webpack/server.pem'),
    key: fs.readFileSync('./config/webpack/server.pem'),
  },
  // 省略  

余談

ドメインがlocalhostでよければ chrome://flags/#allow-insecure-localhost を有効にすれば大丈夫そう(未確認)。

参考

*1:とりあえずの回避策として該当のJSライブラリを開発環境で読み込まないようにしようかとも思ったけど、バグの温床になりそうなのでやめた