首页/新闻资讯/正文详情

Razzle 单端口暴露:用 devServer 代理合并客户端与服务端端口的完整实战指南

发布时间:2026/9/23 14:21:51 来源:云帆数科 栏目:资讯中心
Razzle 单端口暴露:用 devServer 代理合并客户端与服务端端口的完整实战指南
前端构建工具前端构建后端【免费下载链接】razzle✨ Create server-rendered universal JavaScript applications with no configuration项目地址https://gitcode.com/gh_mirrors/ra/razzle点击查看免费下载Razzle 在开发模式下默认同时启动两个服务运行在3001端口的 webpack-dev-server负责客户端 bundle 与 HMR以及运行在3000端口的 Express 服务器负责 SSR 与页面渲染。本文以仓库中的with-single-exposed-port示例为核心讲解如何通过razzle.config.js的modifyWebpackConfig钩子改写 devServer 的代理配置让两个服务对外只暴露一个端口同时深入 nginx 反向代理子路径场景覆盖config.devServer.public、sockPath与CLIENT_PUBLIC_PATH的组合用法。读完本文你将掌握 Razzle 开发服务器底层配置的修改方式并能在 Docker、内网穿透、子路径部署等真实环境中落地单端口方案。示例背景为什么需要单端口暴露在 examples/with-single-exposed-port/README.md 的 Idea behind the example 一节中示例的目标非常明确在开发模式razzle start下修改 Razzle 底层 webpack-dev-server 的 proxy 配置把 devServer 代理到 Express 服务器上从而实现对外只暴露一个端口。从源码看Razzle 开发模式的双端口模型定义在 packages/razzle/config/createConfigAsync.jsconst portOffset clientOnly ? 0 : 1; const devServerPort (process.env.PORT_DEV parseInt(process.env.PORT_DEV, 10)) || (process.env.PORT parseInt(process.env.PORT, 10) portOffset) || 3000 portOffset;也就是说Express 服务器默认监听3000参见 src/index.js 中const port process.env.PORT || 3000;而客户端 devServer 默认在PORT 1即3001端口。当应用被部署到仅开放一个端口的环境如 Docker 容器只映射一个端口、企业防火墙只放行一个端口时这个双端口模型就成了阻碍。本示例给出的解法就是保留双服务内部通信但在 devServer 上配置代理让浏览器只访问3001一个端口即可完成页面渲染与 HMR 热更新。快速开始创建并运行示例按照示例 README 的安装指引该段由yarn update-examples自动维护属官方生成内容执行npx create-razzle-app --example with-single-exposed-port with-single-exposed-port cd with-single-exposed-port yarn start然后在浏览器中访问 http://localhost:3001/ 。注意访问的正是3001 端口devServer 端口而不是默认的 3000——这正是代理生效后的效果。示例工程的package.jsonexamples/with-single-exposed-port/package.json中提供了完整的脚本{ scripts: { start: razzle start --verbose, build: razzle build, test: razzle test --envjsdom, start:prod: NODE_ENVproduction node build/server.js } }其中start:prod用于生产模式构建后直接由build/server.js启动此时不需要 devServer自然也就不存在双端口问题——单端口方案只针对razzle start的开发场景。核心方案通过 modifyWebpackConfig 改写 devServer 代理示例的核心配置位于 examples/with-single-exposed-port/razzle.config.js完整内容如下use strict; module.exports { modifyWebpackConfig(opts) { const config opts.webpackConfig; if (opts.env.target web opts.env.dev) { config.devServer.proxy { context: () true, target: http://localhost:3000 }; config.devServer.index ; } return config; }, };逐项拆解这段配置的作用modifyWebpackConfig(opts)Razzle 暴露的核心配置钩子接收opts对象其中opts.webpackConfig是 Razzle 内部生成好的 webpack 配置opts.env.target取值web客户端或node服务端opts.env.dev表示是否为开发模式。修改后必须return config交还给 Razzle。if (opts.env.target web opts.env.dev)仅在客户端目标 开发模式下生效避免影响生产构建与服务端 bundle。config.devServer.proxy直接为 webpack-dev-server 配置代理。context: () true表示所有请求都命中代理规则http-proxy-middleware的 context 语义target: http://localhost:3000将请求转发到 Express 服务器。config.devServer.index 关键细节。默认情况下 devServer 会优先响应/路径的 index 内容导致代理规则失效将其置空字符串后/请求也会进入代理由 Express 完成 SSR 渲染并返回完整 HTML。这个钩子的可修改对象来源于 Razzle 在 packages/razzle/config/createConfigAsync.js 中初始化的 devServer 配置config.devServer { compress: true, headers: { Access-Control-Allow-Origin: * }, historyApiFallback: { disableDotRule: true }, hot: true, host: dotenv.raw.HOST, port: devServerPort, };你可以在钩子中基于这份初始配置继续叠加任意 webpack-dev-server 支持的选项如public、sockPath、proxy等这也正是 Razzle 设计modifyWebpackConfig的意图。示例工程使用的 webpack-dev-server 为 v3 系列见 package.json 中webpack-dev-server: ^3.11.2因此本示例的index、proxy写法基于 v3 的配置语义Razzle 在 createConfigAsync.js 中已针对 v3/v4 两代配置做了分支兼容升级时需留意配置项迁移。配套的服务端与客户端代码为了让代理链路完整可读示例的 Express 服务器src/server.js负责 SSR 渲染通过renderToString(App /)生成 HTML并用RAZZLE_ASSETS_MANIFEST中的产物清单注入 CSS 与 JS 标签src/index.js 是入口监听PORT默认 3000并包含服务端 HMR 逻辑。客户端 src/client.js 使用hydrate完成水合并启用module.hot.accept()支持热更新——HMR 的 websocket 连接同样通过 devServer 端口3001建立因此单端口方案下热更新能力不受影响。注意事项razzle.config.js 不会被转译示例 README 特别强调了一个重要约束razzle.config.js不会被 Babel 转译因此必须以原生 Node.js 兼容的 JavaScriptvanilla Node.js-compatible JavaScript编写。这意味着不能使用import/export等 ESM 语法必须使用module.exports正如示例文件开头use strict;module.exports {...}所示不能依赖 JSX 或 TypeScript 语法文件在加载时由 Node 直接执行需要保证目标 Node 版本兼容。如果你需要更复杂的配置逻辑如读取环境变量、条件分支同样要遵循这一约束写在module.exports内部。进阶场景nginx 反向代理下的子路径部署当应用运行在 nginx 反向代理的子路径如/razzle-dev/之后时情况会更复杂不仅页面请求要代理HMR 使用的 websocketsockjs-node也要被正确转发。示例 README 提供了完整的第二套配置。修改 razzle.config.jsuse strict; module.exports { modifyWebpackConfig(opts) { const config opts.webpackConfig; if (target web dev) { config.devServer.public localhost:8080 // or 80 or 443 config.devServer.proxy { context: () true, target: http://localhost:3000 }; config.devServer.sockPath /razzle-dev/sockjs-node; } return config; }, };注意示例 README 中的这段代码省略了opts.env前缀target、dev直接使用实际编写时建议与基础示例保持一致使用opts.env.target web opts.env.dev的完整写法避免引用未定义变量。三个新增配置项的作用config.devServer.public localhost:8080声明 devServer 对外可访问的主机与端口与 nginx 的listen 8080对应若走 80/443 需相应调整。它告诉 webpack-dev-server 生成资源 URL 时使用该地址同时 HMR 客户端会用此地址建立 websocket 连接。config.devServer.sockPath /razzle-dev/sockjs-node把 HMR 的 sockjs websocket 端点从默认路径改到子路径之下使其能被 nginx 的location /razzle-dev/规则覆盖转发。config.devServer.proxy与基础示例相同把所有请求代理到 3000 端口的 Express 服务器。通过 CLIENT_PUBLIC_PATH 控制客户端资源路径示例 README 配套给出了启动命令CLIENT_PUBLIC_PATHhttp://localhost:8080/razzle-dev/ yarn startCLIENT_PUBLIC_PATH是 Razzle 为开发模式客户端构建提供的PUBLIC_PATH覆盖变量。从源码看它在 packages/razzle/config/env.js 中被定义为NODE_ENV development BUILD_TARGET client时的PUBLIC_PATH并在 packages/razzle/config/createConfigAsync.js 中作为 devServerpublicPath的来源// VMs, Docker containers might not be available at localhost:3001. CLIENT_PUBLIC_PATH can override. const clientPublicPath dotenv.raw.CLIENT_PUBLIC_PATH || (IS_DEV ? http://${dotenv.raw.HOST}:${devServerPort}/ : /);源码注释直接点明了该变量的用途在 VM、Docker 容器等环境中localhost:3001可能对外不可达此时用CLIENT_PUBLIC_PATH显式覆盖资源前缀。在子路径场景中将它设为http://localhost:8080/razzle-dev/可确保客户端 bundle、HMR websocket 等资源全部从正确的子路径加载。这与config.devServer.public相辅相成前者决定产物 URL 前缀后者决定 devServer 的对外身份。nginx 配置三段 location 精确转发示例 README 给出的 nginx 配置完整复刻如下http { server { listen 8080; # or 80 or 443 server_name _; location /razzle-dev { # no /, no regex return 302 /razzle-dev/; # a / } location /razzle-dev/ { # no regex proxy_pass http://127.0.0.1:3001/; # a / proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } location /razzle-dev/sockjs-node/ { # no regex proxy_pass http://127.0.0.1:3001; # no / proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } } }配置中的三个关键设计location /razzle-dev无尾斜杠、无正则对不带尾斜杠的访问做302重定向到/razzle-dev/保证路径统一location /razzle-dev/将子路径下的常规请求代理到http://127.0.0.1:3001/注意带尾斜杠会剥离子路径前缀同时proxy_set_header Upgrade $http_upgrade与Connection upgrade两行是 websocket 升级的关键缺了它们 HMR 将无法建立连接location /razzle-dev/sockjs-node/优先级最高将 sockjs websocket 端点单独代理到http://127.0.0.1:3001注意无尾斜杠保留完整路径。nginx 的 location 匹配规则中最长前缀优先因此该规则会先于/razzle-dev/命中 sockjs 请求。三条规则配合CLIENT_PUBLIC_PATH与razzle.config.js中的public/sockPath即可在子路径场景下同时打通页面渲染与 HMR 热更新两条链路。延伸阅读与源码路径示例完整配置examples/with-single-exposed-port/razzle.config.jsdevServer 初始化与CLIENT_PUBLIC_PATH覆盖逻辑packages/razzle/config/createConfigAsync.js环境变量定义含CLIENT_PUBLIC_PATHpackages/razzle/config/env.jsRazzle 自定义 devServer 类razzle start实际使用的服务器packages/razzle/config/razzleDevServer.js同类示例修改 devServer 端口与public域名的参考实现见 examples/with-custom-devserver-options/razzle.config.jsRazzle 配置钩子总览modifyWebpackConfig等可查阅 packages/razzle/config/loadRazzleConfig.js需要提醒的是本示例的 devServer 配置基于 webpack-dev-server v3 的选项语义Razzle 本身已对 v3/v4 做了兼容见 createConfigAsync.js 的devServerMajorVersion 3分支若将示例迁移到 webpack-dev-server v4index、proxy等选项的写法与位置需按 v4 的迁移文档调整。单端口方案的核心思路——用modifyWebpackConfig改写devServer的代理、public、sockPath配合CLIENT_PUBLIC_PATH控制资源前缀——在两种版本下均适用。赞分享前端构建工具前端构建后端【免费下载链接】razzle✨ Create server-rendered universal JavaScript applications with no configuration项目地址https://gitcode.com/gh_mirrors/ra/razzle点击查看免费下载相关推荐ComfyUI-WanVideoWrapper 微调实战3 步把基础视频模型变成你的专属风格ComfyUI WanVideoWrapper 微调实战3 步把基础视频模型变成你的专属风格 装好 ComfyUI WanVideoWrapper 之后用人工智能大模型媒体生成如何快速上手ESP32开发Arduino核心框架完整指南如何快速上手ESP32开发Arduino核心框架完整指南 想要快速开始ESP32物联网开发吗Arduino ESP32项目为你提供了完整的解决方案。这个开源嵌入式物联网驱动开发SkyPilot 端口开放实战指南从 Jupyter 到多端口服务的公网暴露与安全管控SkyPilot 端口开放实战指南从 Jupyter 到多端口服务的公网暴露与安全管控 导读 在 SkyPilot 上任务的运行环境默认处于隔离网络中外部后端任务调度MLOps集群管理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

Python从零实现FP-growth算法:FP树构建、可视化与购物篮分析实战
Python从零实现FP-growth算法:FP树构建、可视化与购物篮分析实战

简介:这份资源面向数据挖掘与机器学习初学者及需要落地关联规则分析的开发者,围绕FP-growth频繁模式增长算法提供Python实现与FP树可视化工具,可用于购物篮分析、频繁项集挖掘与大型数据库模式发现等场景。压缩包共11个文件、约480KB&#xf… · 2026/9/23 14:21:51

3个坑救活你的Google英文手写实现
3个坑救活你的Google英文手写实现

3个坑救活你的Google英文手写实现 配置环境就卡半天?别急着骂娘。 90%的开发者在Google英文搜索场景下,不是输在算法,而是输在“环境依赖”和“接口封装”上。 想搞定这个高频面试题,核心就两点: 手写实现… · 2026/9/23 14:21:51

基于CNN深度学习的大米识别实战:含图片数据集与PyTorch代码
基于CNN深度学习的大米识别实战:含图片数据集与PyTorch代码

简介:本资源是一套基于PyTorch框架的CNN大米图像识别完整项目,面向具备一定Python基础、希望入门深度学习图像分类的开发者与在校学生。项目围绕大米类别识别任务,提供从数据预处理、模型训练到可视化交互的完整链路,适合作为课程… · 2026/9/23 14:21:51

解读BDU市场报告:从份额排名看电池包断路单元的技术与商业逻辑
解读BDU市场报告:从份额排名看电池包断路单元的技术与商业逻辑

简介:全球电池包断路单元(BDU)市场正处于快速增长期,2023年市场规模约22.28亿美元,预计2029年将达71.19亿美元,年复合增长率21.36%。这份行业研究资源系统梳理了BDU的市场定义、核心驱动因素(汽… · 2026/9/23 15:13:06

AI时代向量引擎技术解析与应用实践
AI时代向量引擎技术解析与应用实践

1. 当AI焦虑遇上技术红利:我们真正该害怕什么?上周公司新来的95后程序员小张突然离职,临走前在工位上贴了张便签:"GPT-5.3要来了,代码写得比我好还不用社保,先溜为敬"。这个略显戏剧化的场景&… · 2026/9/23 15:13:06

ComfyUI-WanVideoWrapper完整教程:从一句话提示词到成片,5分钟跑通AI文生视频
ComfyUI-WanVideoWrapper完整教程:从一句话提示词到成片,5分钟跑通AI文生视频

ComfyUI-WanVideoWrapper完整教程:从一句话提示词到成片,5分钟跑通AI文生视频 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 想让一句"红熊猫站在竹子上&#xff0… · 2026/9/23 15:13:06

短消息中心业务功能详解:从信令路由到状态报告的实战指南
短消息中心业务功能详解:从信令路由到状态报告的实战指南

简介:短消息中心是移动通信网络的核心组件,这份PPT课件系统讲解其业务功能与工作流程,适合通信技术初学者、网络运维人员及备考相关课程的学员。内容覆盖短消息提交、转发、优先级处理、有效期管理、重复转发尝试、状态报告、用户鉴权、汉字短… · 2026/9/23 15:13:00

LanceDB JS SDK 的 CherryPickResult 接口详解:分支 Cherry-Pick 的结果契约与实战解析
LanceDB JS SDK 的 CherryPickResult 接口详解:分支 Cherry-Pick 的结果契约与实战解析

LanceDB JS SDK 的 CherryPickResult 接口详解:分支 Cherry-Pick 的结果契约与实战解析 【免费下载链接】lancedb Developer-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less. 项目地址: https://gitcode.com/gh_mirrors/l… · 2026/9/23 15:13:00

秋日怀人/东海陈光剑
秋日怀人/东海陈光剑

秋日怀人 [东海]陈光剑 秋风木叶下, 人间别离久。 昨夜梦见之, 眉宇韫清秋。 白日徒相望, 明月上西楼。 · 2026/9/23 15:12:52

3招搞定手机怎么下载微信面试难题实战项目解析
3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧
Win7无线热点配置工具源码解析:解决API失效的3个实战技巧

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧 Win7无线热点配置工具在Win10/11上跑不动?不是你的问题,是版本升级后 API 全变了。很多老项目里的 netsh wlan… · 2026/9/23 0:00:36

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码