蓝戒博客

  • 首页
  • 研发说
  • 架构论
  • 效能录
  • AI谈
  • 随笔集
智构苍穹
AI为翼,架构为骨,文化为魂,实践探新境,价值筑长青。
  1. 首页
  2. 效能录
  3. 正文

本地开发环境启用 HTTPS / HTTP2 :使用 mkcert 实践分享

2025年10月9日 92点热度 0人点赞 0条评论

一、为什么本地开发要启用 HTTPS / HTTP2?

在现代 Web 开发中,越来越多的特性(如 Service Worker、WebRTC、Push API、HTTP/2 等)仅在安全上下文(HTTPS)下可用。
如果你的本地环境仍然运行在 http://localhost,可能会遇到以下问题:

  • 浏览器报错:“此 API 仅在安全上下文中可用”
  • WebSocket、WebRTC、Push 等无法工作
  • 与生产环境行为不一致(如 cookie SameSite、secure 属性)

而 HTTP2 不仅能开启多路复用、头部压缩,还可显著加快静态资源加载速度。
👉 因此,在本地启用 HTTPS + HTTP2 是开发提效和调试的关键一步。


二、什么是 mkcert?

mkcert 是一个零配置、跨平台的本地 CA(Certificate Authority)工具。
它可以创建并信任自签名证书,让你的本地 HTTPS 环境完全受浏览器信任,不再出现「不安全」警告。

✨ 核心特点

  • 自动生成根证书并导入系统信任库
  • 为任意域名(含 localhost、127.0.0.1、自定义域)生成证书
  • 一键启用 HTTPS,完全离线可用
  • 支持 macOS / Windows / Linux / WSL

三、安装 mkcert

macOS

Bash
brew install mkcert
brew install nss  # 如果使用 Firefox

Windows

使用 Chocolatey:

Bash
choco install mkcert

或下载 可执行文件。

Linux

Bash
sudo apt install libnss3-tools
brew install mkcert  # 或手动下载

四、生成本地 HTTPS 证书

1️⃣ 初始化本地 CA

Bash
mkcert -install

这一步会在系统中安装一个根证书,使浏览器信任由它签发的证书。

2️⃣ 生成证书

Bash
mkcert localhost 127.0.0.1 ::1

生成文件:

localhost+2.pem       # 证书文件
localhost+2-key.pem   # 私钥文件

你也可以指定自定义域名:

Bash
mkcert myproject.local

📝 提示:你可以在 hosts 文件中添加 127.0.0.1 myproject.local。


五、在不同服务中使用 HTTPS / HTTP2

1️⃣ Nginx 配置

Nginx
server {
  listen 443 ssl http2;
  server_name localhost;

  ssl_certificate     /path/to/localhost+2.pem;
  ssl_certificate_key /path/to/localhost+2-key.pem;

  root /Users/you/project/dist;
  index index.html;

  location / {
    try_files $uri $uri/ =404;
  }
}

server {
  listen 80;
  server_name localhost;
  return 301 https://$host$request_uri;
}

打开浏览器访问 https://localhost,安全锁图标 ✅。


2️⃣ VSCode Live Server

Live Server 本身支持 HTTPS 模式,可通过配置文件启用。

在项目根目录创建 .vscode/settings.json:

JSON
{
  "liveServer.settings.https": {
    "enable": true,
    "cert": "/path/to/localhost+2.pem",
    "key": "/path/to/localhost+2-key.pem"
  }
}

启动 Live Server 后,访问 https://127.0.0.1:5500/ 即可安全访问。


3️⃣ http-server(npm 工具)

安装:

Bash
npm i -g http-server

使用 mkcert 证书启动:

Bash
http-server -S -C localhost+2.pem -K localhost+2-key.pem -p 443<br>

访问:https://localhost


4️⃣ Node.js (Express / Koa / Fastify)

Node.js 原生 HTTP/2 + HTTPS 静态服务器

NodeJs
// server-http2.mjs
import fs from 'fs';
import http2 from 'http2';
import path from 'path';
import { fileURLToPath } from 'url';
import mime from 'mime-types';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PORT = 8443;
const DIST_DIR = __dirname; // 脚本同级目录,可改为 ./dist

const options = {
  key: fs.readFileSync('./localhost-key.pem'),
  cert: fs.readFileSync('./localhost.pem'),
  allowHTTP1: true
};

const server = http2.createSecureServer(options);

server.on('stream', (stream, headers) => {
  try {
    let reqPath = headers[':path'];
    if (reqPath === '/') reqPath = '/index.html';

    const filePath = path.normalize(path.join(DIST_DIR, decodeURIComponent(reqPath)));

    if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) {
      stream.respond({ ':status': 404 });
      stream.end('Not Found');
      return;
    }

    const contentType = mime.lookup(filePath) || 'application/octet-stream';
    stream.respond({
      ':status': 200,
      'content-type': contentType
    });

    stream.end(fs.readFileSync(filePath));

  } catch (err) {
    console.error(err);
    stream.respond({ ':status': 500 });
    stream.end('Internal Server Error');
  }
});

server.listen(PORT, () => {
  console.log(`🚀 HTTP/2 static server running at https://localhost:${PORT}`);
});

使用方式

  1. 将 server-http2.mjs、index.html、localhost.pem、localhost-key.pem 放在同一目录。
  2. 安装依赖:
Bash
npm install mime-types

  1. 启动:
Bash
node server-http2.mjs

  1. 打开浏览器访问:
INI
https://localhost:8443

✅ 此时 访问 https://localhost:8443,index.html 和所有静态资源均可加载,浏览器 Network 面板协议显示 h2。

Express 示例

NodeJs
import fs from 'fs';
import https from 'https';
import express from 'express';

const app = express();

app.get('/', (req, res) => {
  res.send('Hello HTTPS + HTTP2!');
});

const options = {
  key: fs.readFileSync('./localhost+2-key.pem'),
  cert: fs.readFileSync('./localhost+2.pem')
};

https.createServer(options, app).listen(443, () => {
  console.log('HTTPS server running at https://localhost');
});

Koa 示例

NodeJs
import Koa from 'koa';
import https from 'https';
import fs from 'fs';

const app = new Koa();
app.use(ctx => { ctx.body = 'Koa over HTTPS!'; });

https.createServer({
  key: fs.readFileSync('./localhost+2-key.pem'),
  cert: fs.readFileSync('./localhost+2.pem')
}, app.callback()).listen(443);

Fastify 示例

NodeJs
import Fastify from 'fastify';
import fs from 'fs';

const fastify = Fastify({
  https: {
    key: fs.readFileSync('./localhost+2-key.pem'),
    cert: fs.readFileSync('./localhost+2.pem')
  },
  http2: true
});

fastify.get('/', async () => ({ hello: 'HTTP2' }));
fastify.listen({ port: 443 });

以上示例均支持 HTTP2 与 HTTPS,可直接在 Chrome 调试 Network 协议为 h2。

5️⃣ Vite 本地服务支持 HTTP/2 + HTTPS 实现

在使用 Vite 作为前端开发服务器时,默认它只启用基于 HTTP/1.1 的开发服务,
若希望支持更接近生产环境的 HTTP/2 + HTTPS 本地预览,
我们可以借助 Node.js 原生模块与 mkcert 生成的本地证书来扩展。


📁 目录结构

为避免影响现有开发配置,我们新建一个独立的 vite-server-http2.mjs 与扩展配置文件:

project-root/
├─ index.html
├─ vite.config.js                 # 原有 Vite 配置(保持不变)
├─ vite.h2.extend.js              # 新增:HTTP/2 + HTTPS 扩展配置
├─ vite-server-http2.mjs          # 新增:启动 HTTP/2 + HMR 服务脚本
├─ localhost+2.pem                # mkcert 生成证书
└─ localhost+2-key.pem            # mkcert 生成私钥

⚙️ vite.h2.extend.js

独立的 Vite 配置文件,用于在中间件模式下提供 HTTPS 与独立的 HMR WebSocket 服务。

JavaScript
import fs from 'fs';
import path from 'path';
import getPort from 'get-port';

export default async () => {
  const hmrPort = await getPort({ port: 24678 });
  console.log(`[vite] HMR WebSocket will use port ${hmrPort}`);

  return {
    server: {
      middlewareMode: true,
      https: {
        key: fs.readFileSync(path.resolve('./localhost+2-key.pem')),
        cert: fs.readFileSync(path.resolve('./localhost+2.pem')),
      },
      hmr: {
        protocol: 'wss',
        host: 'localhost',
        port: hmrPort,
      },
    },
  };
};

🧩 vite-server-http2.mjs

使用 Node.js 原生 http2.createSecureServer() 搭建开发服务,
支持动态端口检测、静态资源访问和热更新注入。

JavaScript
// vite-server-http2.mjs
import fs from 'fs';
import path from 'path';
import http2 from 'http2';
import os from 'os';
import getPort from 'get-port';
import { createServer as createViteServer } from 'vite';

// 获取所有非内网回环的 IPv4 地址(与 Vite 打印风格一致)
function getNetworkAddresses() {
  const nets = os.networkInterfaces();
  const addrs = new Set();
  for (const name of Object.keys(nets)) {
    for (const net of nets[name]) {
      if (net.family === 'IPv4' && !net.internal) {
        addrs.add(net.address);
      }
    }
  }
  return [...addrs];
}

async function startServer() {
  // 首选端口(会自动查找空闲端口)
  const preferredPort = 12443;
  const port = await getPort({ port: preferredPort });

  console.log(`\n🟢 Starting custom Vite HTTP/2 server on https://localhost:${port} ...\n`);
  console.log(`🔑 Using certificate: ${path.resolve('./localhost+2.pem')}\n`);

  // 创建 Vite 中间件(读取你提供的扩展配置)
  const vite = await createViteServer({
    configFile: './vite.h2.extend.js'
  });

  // http2 安全服务器,allowHTTP1 以兼容 http/1.1 客户端
  const server = http2.createSecureServer(
    {
      key: fs.readFileSync(path.resolve('./localhost+2-key.pem')),
      cert: fs.readFileSync(path.resolve('./localhost+2.pem')),
      allowHTTP1: true
    },
    async (req, res) => {
      try {
        const url = req.url;

        // 优先交给 Vite 中间件处理(模块、静态资源、HMR 路由等)
        vite.middlewares(req, res, async (err) => {
          if (err) {
            vite.ssrFixStacktrace(err);
            res.writeHead(500);
            res.end(err.message);
            return;
          }

          // 对于 HTML 请求,注入 transformIndexHtml
          if (!url.includes('.') || url.endsWith('.html')) {
            let html = fs.readFileSync(path.resolve('./index.html'), 'utf8');
            html = await vite.transformIndexHtml(url, html);
            res.writeHead(200, { 'Content-Type': 'text/html' });
            res.end(html);
          }
          // 其它请求已由 vite.middlewares 处理或交给下游返回 404
        });
      } catch (e) {
        vite.ssrFixStacktrace(e);
        res.writeHead(500);
        res.end(e.message);
      }
    }
  );

  server.listen(port, () => {
    // 打印 Local 与 Network(所有 IPv4)地址,风格与 Vite 一致
    const networkAddrs = getNetworkAddresses();
    console.log('✅ Vite HTTP/2 server is running!\n');
    console.log(`   ➜ Local:   https://localhost:${port}/`);
    if (networkAddrs.length) {
      for (const addr of networkAddrs) {
        console.log(`   ➜ Network: https://${addr}:${port}/`);
      }
    } else {
      console.log(`   ➜ Network: https://<no-network-ip-found>:${port}/`);
    }

    // HMR 端口(vite.h2.extend.js 中生成的端口)
    const hmrPort = vite.config?.server?.hmr?.port || 24678;
    console.log(`\n   🔥 HMR WS:  wss://localhost:${hmrPort}/\n`);
  });

  server.on('error', (err) => {
    console.error('❌ Server error:', err);
  });
}

startServer().catch((err) => {
  console.error('❌ Failed to start Vite HTTP/2 server:', err);
  process.exit(1);
});

🪄 package.json 脚本配置

在 scripts 中添加新的启动命令:

JSON
{
  "scripts": {
    "dev": "vite",
    "dev:h2": "node vite-server-http2.mjs"
  }
}

🚀 启动方式

执行命令:

Bash
npm run dev:h2

终端输出类似:

INI
🟢 Starting custom Vite HTTP/2 server on https://localhost:12443 ...

🔑 Using certificate: E:\fork-project\code\gpaas_ui\localhost+2.pem

[vite] HMR WebSocket will use port 24678
✅ Vite HTTP/2 server is running!

   ➜ Local:   https://localhost:12443/
   ➜ Network: https://192.168.96.60:12443/

   🔥 HMR WS:  wss://localhost:24678/

打开浏览器访问:

👉 https://localhost:12443

若首次访问提示证书不受信任,请先信任 mkcert 根证书即可。

注:如果希望本机网络IP支持https受信访问,通过终端输入 ipconfig 查看网路ip地址,生成证书需要添加本机网络ip地址如:

Bash
mkcert localhost 127.0.0.1 192.168.96.40

✅ 功能总结

功能描述
✅ HTTPS使用 mkcert 本地证书
✅ HTTP/2基于 Node.js 原生 http2 模块
✅ 动态端口自动检测端口冲突并递增
✅ HMR 热更新独立 WSS 端口,支持 Vite 模块热替换
✅ 静态文件从项目根目录读取并注入 HTML

📘 小结

该方案的优势在于:

  • 与原有 vite.config.js 完全解耦,不会干扰正常 npm run dev;
  • 可复用 mkcert 本地信任证书;
  • 支持真实 HTTP/2 通信测试,更贴近生产环境;
  • 仍然保留 HMR 热更新,开发体验不受影响。

六、在浏览器中验证证书生效

1. 打开浏览器访问,显示安全图标:

INI
https://localhost

2. 点击证书信息,查看颁发机构为 mkcert,浏览器信任证书 ✅。

3. DevTools → Network → Protocol,查看协议为 h2,说明 HTTP/2 生效。


七、进阶:多个项目共享证书

可以在全局统一证书目录:

Bash
mkdir -p ~/.mkcert
cd ~/.mkcert
mkcert localhost 127.0.0.1

在各项目配置时统一引用:

INI
ssl_certificate     ~/.mkcert/localhost.pem;
ssl_certificate_key ~/.mkcert/localhost-key.pem;

八、mkcert 常见问题

问题原因解决办法
浏览器仍提示“不安全”根证书未被信任重新执行 mkcert -install
Firefox 不识别需单独导入到 Firefox 信任库执行 mkcert -install 后重启 Firefox
VSCode Live Server 报错路径错误或端口被占用检查文件路径与端口占用情况
Node 启动失败权限问题尝试使用 sudo 或非 443 端口

九、总结

使用 mkcert,可以轻松让本地开发环境支持 HTTPS 与 HTTP/2,避免安全策略限制,完美模拟线上环境。
配合 Nginx、Node.js、VSCode Live Server 等多种服务,你可以在本地构建高保真、安全的开发体验。


🧩 结语

HTTPS 已成为前端开发的基础环境要求,而 mkcert 让我们摆脱复杂的证书配置,像写代码一样优雅地构建安全环境。
在 AI、WebRTC、PWA 时代,安全上下文是新一代 Web 的起点。动手启用 HTTPS 吧,让你的本地环境更接近未来。

标签: HTTP2 HTTPS mkcert
最后更新:2025年10月10日

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

最新 热点 随机
最新 热点 随机
Vue 3.6「无虚拟 DOM」时代开启:深入解读 Vapor Mode 的革命性变革 2025 最推荐的 uni-app 技术栈:unibest + uView Pro 高效开发全攻略 前端开源工具 PinMe:极简部署体验分享 架构评估方法 ATAM:系统性洞察架构质量的利器 软件系统架构评估与质量属性分析 AI 大模型开发:如何实现数据向量化
Webpack 实战:Code Splitting 优化页面加载性能前端开源工具 PinMe:极简部署体验分享AI 产品前端技术全解析:模型可视化与流式响应实践前端内存泄露防范及编码攻略DApp开发前端技术全解析:技术选型、功能实现与开发步骤Web Workers:释放浏览器多线程的魔力
移动端微信分享弹出遮罩层js效果 🧩 E2E 测试实战:Playwright 介绍与使用,对比 Cypress 的优劣势与生态选择 bootstrap-datetimepicker日期时间选择插件中文说明 架构模式全景图:从单体到云原生的演进与思考 移动端调试神器: eruda介绍 时间日期格式化处理js类库:momentJS
最近评论
渔夫 发布于 6 天前(11月05日) 学到了,感谢博主分享
沙拉小王子 发布于 8 年前(11月30日) 适合vue入门者学习,赞一个
沙拉小王子 发布于 8 年前(11月30日) 适合vue入门者学习,赞一个
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8

COPYRIGHT © 2025 蓝戒博客_智构苍穹-专注于大前端领域技术生态. ALL RIGHTS RESERVED.

京ICP备12026697号-2