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

Razzle 自定义 Webpack 配置实现 Vendor Bundle 分包实战(with-vendor-bundle 示例深度解析)

发布时间:2026/9/24 9:47:55 来源:云帆数科 栏目:资讯中心
Razzle 自定义 Webpack 配置实现 Vendor Bundle 分包实战(with-vendor-bundle 示例深度解析)
前端构建工具前端构建后端【免费下载链接】razzle✨ Create server-rendered universal JavaScript applications with no configuration项目地址https://gitcode.com/gh_mirrors/ra/razzle点击查看免费下载导读本篇技术指南以 examples/with-vendor-bundle 示例为核心完整讲解如何在 Razzle 的零配置体系之上通过razzle.config.js的modifyWebpackConfig钩子深度定制底层 webpack 配置把 React、ReactDOM 等第三方依赖抽离为独立 vendor 分包并同步改造服务端 HTML 模板与开发期错误覆盖层路径。读完本文你将掌握一套可直接复制的Razzle 手动 vendor bundle实战方案理解 Razzle 配置钩子的调用时机、assets manifest 的生成规则以及为什么开发与生产环境需要不同的脚本标签写法。示例概览与运行方式该示例位于仓库 examples/with-vendor-bundle其package.json依赖了react^17.0.1、react-dom^17.0.1、express^4.17.1构建工具链为razzle4.2.15与webpack^4.44.1。按照示例 README 提供的标准流程创建并启动npx create-razzle-app --example with-vendor-bundle with-vendor-bundle cd with-vendor-bundle yarn start启动后项目在http://localhost:3000通过src/index.js中的process.env.PORT || 3000提供服务。除yarn start开发模式外示例package.json还提供yarn build生产构建与yarn start:prod以NODE_ENVproduction node build/server.js运行生产构建产物等脚本可用于验证 vendor 分包在生产构建中的真实效果。思路为什么要把第三方依赖拆成 vendor 分包这个示例的核心思想源自 Twitter Lite 的高性能 React PWA 实践Paul Armstrong 的 Medium 文章把 React、ReactDOM 这类极少变动、体积巨大的第三方库从业务代码中独立出来单独打成一份 vendor bundle。带来的收益包括缓存友好vendor 分包只有在依赖升级时才会产生新的内容 hash业务代码每次发布产生的 hash 变化不会波及 vendor 文件浏览器可以长期命中缓存的 vendor 资源体积可控业务 bundle 中不再重复打包第三方依赖首屏需要传输的业务字节显著减少便于长期优化vendor 文件可以进一步配合defer加载、CDN 预置等手段做性能调优。示例 README 中有一句点睛之笔m.twitter.com 本身并不做服务端渲染所以这套服务端渲染 vendor 分包的构建工具链甚至比 Twitter Lite 的构建方案更进一步。第一步通过 modifyWebpackConfig 钩子改造 webpack 配置Razzle 的核心设计是零配置可用、按需可覆盖。razzle.config.js是 Razzle 约定的配置文件源码层面由 packages/razzle/config/paths.js 中的appRazzleConfig: resolveApp(razzle.config.js)指定路径当文件存在时packages/razzle/config/loadRazzleConfig.js 会加载它随后 packages/razzle/config/createConfigAsync.js 在生成完整 webpack 配置后会调用其中的modifyWebpackConfig({ env, webpackConfig, webpackObject, options, paths })钩子让你拿到最终配置对象并自由修改。示例的 examples/with-vendor-bundle/razzle.config.js 完整代码如下use strict; module.exports { modifyWebpackConfig(opts) { const config opts.webpackConfig; // Change the name of the server output file in production if (opts.env.target web) { // modify filenaming to account for multiple entry files config.output.filename opts.env.dev ? static/js/[name].js : static/js/[name].[hash:8].js; // add another entry point called vendor config.entry.vendor [ require.resolve(react), require.resolve(react-dom), // ... add any other vendor packages with require.resolve(xxx) ]; config.optimization { splitChunks: { // Chunk splitting optimiztion chunks: all, // Switch off name generation, otherwise files would be invalidated // when more chunks with the same vendors are added name: false, }, }; } return config; }, };关键点一只在 web 目标上生效opts.env.target用于区分 Razzle 的两套独立 webpack 构建web客户端与node服务端。服务端构建在 createConfigAsync.js 中被设计为单 entryserver: [paths.appServerIndexJs]并限制单 chunkLimitChunkCountPlugin因此 vendor 拆分只对客户端有意义。示例用if (opts.env.target web)把全部改造限定在客户端配置上避免破坏服务端 bundle。关键点二多 entry 下必须自定义输出文件名Razzle 默认的客户端输出文件名只针对单一 entry 设计开发为static/js/bundle.js之类生产带 contenthash。一旦新增第二个 entryvendor[name]占位符就成了必需品。示例按环境区分开发环境static/js/[name].js无 hash便于 HMR 与调试生产环境static/js/[name].[hash:8].js8 位内容 hash用于缓存失效控制。关键点三vendor entry 与 splitChunks 的配合config.entry.vendor [ require.resolve(react), require.resolve(react-dom), // ... add any other vendor packages with require.resolve(xxx) ];这里用require.resolve把 React 与 ReactDOM 的入口模块显式声明为新的 vendor entrywebpack 会据此把这两个包及其内部依赖图完整提取到独立的 vendor chunk 中。需要追加其他第三方包时只需按注释所示继续追加require.resolve(xxx)。同时示例覆盖了config.optimization.splitChunksconfig.optimization { splitChunks: { chunks: all, name: false, }, };注释说明了name: false的动机关闭自动命名后当更多 vendor chunk 加入时不会因为同名冲突导致既有文件失效文件内容不变则 hash 不变缓存即可复用。值得注意的是Razzle 默认对 dev 与 prod 分别内置了splitChunksConfigs见 createConfigAsync.js其中cacheGroups.default与vendors均被禁用因此示例是在默认关闭 vendor 缓存组的基础上改用显式 entry 全局chunks: all的方式实现同样的目标。钩子执行时机说明从 createConfigAsync.js 的调用顺序可以确认modifyWebpackConfig在 webpack 基础配置entry、output、loader、plugin、optimization全部组装完毕之后执行且用户配置中的钩子最后调用插件钩子在前、用户钩子在后。因此你可以像示例一样直接改写config.output、config.entry、config.optimization无需关心底层配置如何生成。返回的config即最终生效的 webpack 配置。第二步在服务端 HTML 模板中按顺序引入多个脚本vendor 分包后构建产物不再只有一份client相关文件而是client、vendor等多个入口同时 Razzle 还会通过 webpack-manifest-plugin 生成 assets manifest。服务端必须显式把这些脚本按正确顺序写入 HTML。示例 README 给出的模板改造如下与示例源码 examples/with-vendor-bundle/src/server.js 的renderApp思路一致README 中为便于讲解直接内联了三组脚本标签// server.js // ... server .disable(x-powered-by) .use(express.static(process.env.RAZZLE_PUBLIC_DIR)) .get(/*, (req, res) { const markup renderToString(App /); res.send( !doctype html html lang head meta http-equivX-UA-Compatible contentIEedge / meta charSetutf-8 / titleWelcome to Razzle/title meta nameviewport contentwidthdevice-width, initial-scale1 ${assets.client.css ? link relstylesheet href${assets.client.css} : } ${process.env.NODE_ENV production ? script src${assets.manifest.js} defer/script : script src${assets.manifest.js} defer crossorigin/script} ${process.env.NODE_ENV production ? script src${assets.vendor.js} defer/script : script src${assets.vendor.js} defer crossorigin/script} ${process.env.NODE_ENV production ? script src${assets.client.js} defer/script : script src${assets.client.js} defer crossorigin/script} /head body div idroot${markup}/div /body /html ); });这里的关键信息assets来自process.env.RAZZLE_ASSETS_MANIFEST即构建生成的assets-manifest.json该环境变量在 packages/razzle/config/env.js 中被注入manifest 文件本身由 createConfigAsync.js 中的ManifestPlugin按 entry 名生成。新增的vendorentry 会自然出现在 manifest 中所以assets.vendor.js可直接取到 vendor 文件的 URL脚本顺序至关重要manifest→vendor→client。webpack runtimemanifest 部分必须先加载然后 vendor 提供 React/ReactDOM 等运行时依赖最后才是业务代码开发与生产使用不同的属性生产模式用script src... defer/script开发模式额外加crossorigin。原因在于开发模式下客户端 bundle 由 webpack-dev-server 运行在http://localhost:3001跨端口HTML 页面localhost:3000通过 CORS 加载脚本crossorigin属性是错误覆盖层与 source map 正确工作所必需的。示例源码 examples/with-vendor-bundle/src/server.js 还封装了cssLinksFromAssets与jsScriptTagsFromAssets两个辅助函数用assets[entrypoint].css/js数组自动生成标签可复用同一套逻辑处理任意数量的入口与 CSS 文件。第三步用 REACT_DEV_BUNDLE_PATH 保住开发期错误覆盖层体验完成上述两步后开发环境下 React 的真实代码被搬到了 vendor bundlestatic/js/vendor.js里。如果不对 Razzle 做额外说明其内置的 webpack-hot-dev-client见 packages/razzle-dev-utils/webpackHotDevClient.js通过react-error-overlayErrorOverlay.startReportingRuntimeErrors把运行时错误渲染成覆盖页面error overlay而非输出到控制台而该机制需要知道 React 开发版 bundle 的位置。解决办法是在项目根目录创建.env文件写入REACT_DEV_BUNDLE_PATH/static/js/vendor.js这个相对路径指向开发模式下 vendor bundle 的公开路径。示例 README 明确说明通过这一行配置Razzle 就能把运行时错误管道进漂亮的错误覆盖层而不是退化成控制台日志——这是开发者体验DX层面的关键细节容易在手动改配置时被忽略。验证与运行以上三步全部完成后的效果验证方式yarn start启动开发服务器后访问http://localhost:3000浏览器 Network 面板应能看到static/js/vendor.js、static/js/client.js以及 webpack runtime 脚本分别作为独立请求加载。改用生产链路验证缓存效果yarn build yarn start:prod构建产物中会生成带 8 位 hash 的static/js/vendor.[hash:8].js且client与vendor的 hash 相互独立——后续只改动业务代码重新构建时vendor 文件 hash 保持不变这正是 vendor 分包实现长期缓存复用的核心收益。小结一份可复制的 Razzle 分包清单回顾整个示例在 Razzle 中实现 vendor 分包只需三步改构建在 razzle.config.js 的modifyWebpackConfig中为 web 目标新增config.entry.vendor并用[name]文件名与splitChunks配置保证多 entry 输出正确、缓存稳定改模板在服务端 HTML 中按manifest → vendor → client的顺序输出脚本并区分开发加crossorigin与生产纯defer两种写法保体验在.env中设置REACT_DEV_BUNDLE_PATH/static/js/vendor.js让开发期错误覆盖层继续正常工作。这三步分别对应构建配置层、服务端渲染层与开发工具层的配合体现了 Razzle零配置起步、配置钩子精准干预的设计哲学默认约定帮你跑起来modifyWebpackConfig这类钩子让你在需要时拥有对底层 webpack 的完整控制权钩子的完整参数与执行顺序可查阅 packages/razzle/config/createConfigAsync.js 与 packages/razzle/config/loadRazzleConfig.js。如果你想在自己的 Razzle 项目中应用此方案直接对照示例的三个文件改造即可。赞分享前端构建工具前端构建后端【免费下载链接】razzle✨ Create server-rendered universal JavaScript applications with no configuration项目地址https://gitcode.com/gh_mirrors/ra/razzle点击查看免费下载相关推荐Solar Pro Preview 社区支持与贡献指南如何参与模型改进与反馈Solar Pro Preview 社区支持与贡献指南如何参与模型改进与反馈 Solar Pro Preview 是一款高效的 220 亿参数大型语言模型专razzle-plugin-bundle-analyzer为 Razzle 应用接入 webpack-bundle-analyzer 包体积分析razzle plugin bundle analyzer为 Razzle 应用接入 webpack bundle analyzer 包体积分析 本指南围绕前端构建工具前端构建后端Webpack DLL 分包构建实战DllPlugin 与 output.library 将 vendor 与 app 分离dll-app-and-vendor 示例详解Webpack DLL 分包构建实战DllPlugin 与 output.library 将 vendor 与 app 分离dll app and vend前端构建开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

Flet FilePickerFile 详解:文件选择结果的数据结构、字段语义与跨平台实战
Flet FilePickerFile 详解:文件选择结果的数据结构、字段语义与跨平台实战

前端跨平台桌面应用移动开发 【免费下载链接】flet Build realtime web, mobile and desktop apps in Python only. No frontend experience required. 项目地址: https://gitcode.com/gh_mirrors/fl/flet 点击查看 免费下载 FilePickerFile 是 Flet(Py… · 2026/9/24 9:47:49

芯片测试座选型必须先做样品验证的四大物理依据
芯片测试座选型必须先做样品验证的四大物理依据

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 9:47:37

SemIf Phase 1 方法全解:用开放模型实现无生成读取的类型化语义决策,冻结评估矩阵与形状匹配基准
SemIf Phase 1 方法全解:用开放模型实现无生成读取的类型化语义决策,冻结评估矩阵与形状匹配基准

【免费下载链接】SemIf Semantic ifs from open models, on a 3090 at home. Independent; not affiliated with Jev or TypeSafe. 项目地址: https://gitcode.com/gh_mirrors/op/SemIf 点击查看 免费下载 SemIf(前身 OpenJev)是一套独立的开… · 2026/9/24 9:47:24

【轨物方案】AI 给建议,人拍板:我们做电力行业 Agent 的三条设计原则
【轨物方案】AI 给建议,人拍板:我们做电力行业 Agent 的三条设计原则

过去一年,“Agent”成了技术圈出现频率最高的词之一。但在电力、能源这类严肃行业里,真正的问题是:一个 AI 智能体要怎样设计,客户才敢把它放进生产流程?放在标书制作这样“错一个字都可能废标”的场景里,这… · 2026/9/24 10:32:42

平衡球机器人实战:OpenCV视觉定位与STM32级联PID控制
平衡球机器人实战:OpenCV视觉定位与STM32级联PID控制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:32:42

STM32不掉电时钟方案:DS1302+纽扣电池实战记录
STM32不掉电时钟方案:DS1302+纽扣电池实战记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:28:58

Kornia 修复四元数奇点处 NaN/Inf 梯度:`quaternion_exp_to_log` 与 `euler_from_quaternion` 的边界防护实现解析
Kornia 修复四元数奇点处 NaN/Inf 梯度:`quaternion_exp_to_log` 与 `euler_from_quaternion` 的边界防护实现解析

计算机视觉人工智能深度学习图像处理 【免费下载链接】kornia 🐍 Geometric Computer Vision Library for Spatial AI 项目地址: https://gitcode.com/gh_mirrors/ko/kornia 点击查看 免费下载 导读 位姿优化与刚体运动学中,四元数对数和欧… · 2026/9/24 10:28:58

鸿蒙开发:ArrayList,可不会让UI更新哦
鸿蒙开发:ArrayList,可不会让UI更新哦

前言有同学遇到了一个问题&#xff0c;他是使用ArrayList来存储的数据&#xff0c;在动态给集合添加数据后&#xff0c;UI并未更新&#xff0c;代码如下&#xff1a;import { ArrayList } from kit.ArkTS;Entry Component struct Index {State numItems: ArrayList<string&g… · 2026/9/24 10:28:51

用NanoVNA调NFC天线匹配:从S11到读卡距离全面提升
用NanoVNA调NFC天线匹配:从S11到读卡距离全面提升

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:28:45

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介&#xff1a;这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源&#xff0c;围绕YOLOv8实现渔船作业监控系统&#xff0c;可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件&#xff0c;约24.21MB&#xff0c;以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介&#xff1a;面向时间序列数据建模的一维卷积神经网络完整实现&#xff0c;适合深度学习入门者及需要快速验证时序模型的研究者&#xff0c;能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小&#xff0c;只有3KB&#xff0c;内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L&#xff0c;而是舌尖上的L最近在几个方言群和语音教学社群里&#xff0c;反复看到有人发一句&#xff1a;“也说字母L&#xff1a;柔软的长舌”。初看以为是英语发音课笔记&#xff0c;点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

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

企业微信二维码