かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Vite + React 開発環境 (localhost) を https で立ち上げたい

Vite + React で構築したアプリの開発環境も本番環境と同じように https (TLS) で動かしたかったやつのメモ

環境

  • Vite 4.3.9
  • React 18.2.0
  • TypeScript 5.1.3

結論

  • お手軽に https 化するなら vite-plugin-mkcert を使う
  • httpsドメインを特殊にしたいなら mkcertlocal-ssl-proxy を使う

のが良さそう

1. vite-plugin-mkcert を使う

プラグインを入れるだけで mkcert を使って TLS 化できるっぽい

$ npm i -D vite-plugin-mkcert

./vite.config.ts

import {defineConfig} from'vite';
import react from '@vitejs/plugin-react-swc';
import tsconfigPaths from 'vite-tsconfig-paths';
import mkcert from'vite-plugin-mkcert';

export default defineConfig({
  plugins: [tsconfigPaths(), react(), mkcert()],
  server: {
    https: true,
  },
});

2. 自分で証明書を作って読み込ませる

  1. mkcert を使って証明書を作成
  2. vite の server.https の設定で証明書を読み込ませる

1. mkcert を使って証明書を作成する

# mkcert のインストール
$ brew install mkcert
# ローカル認証局(CA)を設定
$ mkcert -install
# 開発ディレクトリに移動
$ cd path/to/app_dire
# localhost 用の証明書を作成
$ mkcert localhost

localhost-key.pemlocalhost.pem という2つのファイルが作成される

2. vite の server.https の設定で証明書を読み込ませる

./vite.config.ts

import fs from 'fs';
import {defineConfig} from'vite';
import react from '@vitejs/plugin-react-swc';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
  plugins: [tsconfigPaths(), react(), mkcert()],
  server: {
    port: { 3031 },
    https: {
      key: fs.readFileSync('./localhost-key.pem'),
      cert: fs.readFileSync('./localhost.pem'),
    },
  },
});

ローカルサーバーを起動

$ npm run dev
➜  Local:   https://localhost:3031/

https://localhost:3031/ にアクセスしたら問題なく https で開発中のアプリが表示されました!

3. local-ssl-proxy を使って httpshttps の環境を同時に起動する

local-ssl-proxy--target オプションで指定したポート (https) に来たリクエストを裏で動く --source で指定したポート (http) に転送してくれる

$ npx local-ssl-proxy --source 3001 --target 3000

これは https://localhost:3000 にアクセスすれば http://localhost:3001 の内容が返される

You'll get a warning because the certificate is self-signed, this is safe to ignore during development.
cf. GitHub - cameronhunter/local-ssl-proxy: Simple SSL HTTP proxy using a self-signed certificate. Intended for local development only.

local-ssl-proxy だけでは証明書の警告が出るので mkcert と組み合わせることで警告なしで https な開発環境を立ち上げられるようになる

1. mkcert で証明書を発行する

$ brew install mkcert
$ mkcert -install
$ mkcert localhost

2. key と cert を使って local-ssl-proxy で起動する npm スクリプトを作成する

package.json

"scripts": {
  "dev:https": "vite --port 13031 & local-ssl-proxy --key ./localhost-key.pem --cert ./localhost.pem --source 3031 --target 13031"

vite --port 13031http://localhost:13031 で通常のアプリを起動し、local-ssl-proxy --key ./localhost-key.pem --cert ./localhost.pem --source 3031 --target 13031https://localhost:3031 を起動させ 3031 へのアクセスを 13031 番に転送する
https://localhost:3031 にアクセスすれば https な環境で、http://localhost:13031 にアクセスすると通常の http なアプリでも確認することができる

local-ssl-proxy を使う場合は vite.config.tshttps の設定をする必要はない

local-ssl-proxy × mkcert を使えば好きなドメインhttps 環境にできる

local-ssl-proxy は proxy しているだけようなので、 mkcert で好きなドメインの証明書を作ってしまえば、そのドメインへのリクエストが通常の開発環境に転送されるようになる

mkcert で好きなドメインの証明書を作成する

$ mkcert local.mydomain.dev

local.mydomain.dev-key.pemlocal.mydomain.dev.pem が作成されるので local-ssl-proxy のオプションにこれらを渡す

package.json

"scripts": {
  "dev:https": "vite --port 13031 & local-ssl-proxy --key ./local.mydomain.dev-key.pem --cert ./local.mydomain.dev.pem --source 3031 --target 13031"

npm run dev:https で開発サーバーを起動させると https://local.mydomain.dev:3031 にアクセスすれば localhost:13031 の内容が表示される!
好き勝手に証明書を作れるけど、存在するサイトと同じドメインで作ると困ったことになると思うので、開発用と分かるドメインにするのが無難

所感

  • お手軽に https 化するなら vite-plugin-mkcert を使う
  • httpsドメインを特殊にしたいなら mkcertlocal-ssl-proxy を使う

のが良さそう


⚠ npm の mkcert を使って証明書を作成したものは警告が出てしまう

TLS に対するる理解が浅く正確なことが解ってはないが、npm にもオレオレ証明書を発行できる mkert があったので試してみたが、証明書の警告と無効な証明書になり上手くいかなかった

$ npm i -D mkcert
# 証明局の作成
$ npx mkcert create-ca
CA Private Key: ./ca.key
CA Certificate: ./ca.crt
# 証明書の作成
$ npx mkcert create-cert --key localhost-key.pem --cert localhost.pem
Private Key: ./localhost-key.pem
Certificate: ./localhost.pem

vite.config.tsserver.httpslocalhost-key.pemlocalhost.pem を読み込む設定を追加し、npm run dev でローカルサーバーを起動する

👇 証明書は読み込めているが警告が出てしまう。

node mkcert

localhost にアクセスする (安全ではありません) をクリックすれば表示できるが、毎回この作業をするのは少し面倒です… (NODE_TLS_REJECT_UNAUTHORIZED=0 を設定しても同様)

mkcertは信頼できる機関として登録されているため、ブラウザは証明書を信頼し、HTTPS接続を作成します。
cf. How to use HTTPS for local development

CA の organization を mkcert にしても警告は出たままでした。
オプションを駆使すれば警告なしの証明書と証明局が作れるのかもですが大変そうなのでこれ以上の深追いはしていません

cf.

メモ

SSL(Secure Sockets Layer)は、インターネット上でデータを暗号化して送受信するプロトコルです。TLS(Transport Layer Security)は、SSLの後継プロトコルであり、SSLをもとに標準化させています。現在ではTLSが使用されていますが、SSLの名称が広く使用されていたこともあり、TLSのことをSSLと呼んだり、TLSのことをSSL/TLSと表記する場合があります。
cf. SSL/TLSとは、SSL、TLS、HTTPSの違い

CA と証明書については下記のサイトがとても理解しやすかったです

通信まわり全く解ってないので IT パスポート勉強したほうがいいかな


[参考]

create-react-app で作った場合の方法