1. 浏览器端require is not defined错误解析作为一名长期奋战在前端开发一线的工程师我深知模块化开发中这个经典错误的困扰。当你在本地开发环境中一切运行正常但打包部署到浏览器后却突然抛出Uncaught ReferenceError: require is not defined时那种挫败感我深有体会。这个错误看似简单实则涉及前端工程化的核心概念——模块规范兼容性问题。1.1 模块系统的演进与现状JavaScript的模块化发展经历了漫长的过程。在ES6之前社区主要采用以下几种方案IIFE模式通过立即执行函数实现作用域隔离AMD规范RequireJS为代表的异步模块定义CommonJSNode.js采用的同步模块加载方案而现代前端开发中我们主要面对的是两种主流规范CommonJS (CJS)语法require()导入module.exports/exports导出特点同步加载主要用于Node.js环境示例// 导入 const fs require(fs) // 导出 module.exports { myFunction }ES Modules (ESM)语法import/export特点静态分析支持异步加载浏览器原生支持示例// 导入 import fs from fs // 导出 export default { myFunction }1.2 错误产生的根本原因当浏览器环境中出现require is not defined错误时本质上是因为环境不兼容浏览器原生环境没有实现CommonJS规范转换缺失打包工具未能将CJS语法正确转换为浏览器可识别的代码配置错误TypeScript或打包工具配置不当导致语法残留我曾在一个企业级项目中遇到过这样的情况开发团队混合使用了React和Node.js编写的工具函数库由于打包配置不当导致生产环境频繁报错。经过深入排查发现问题出在一个被忽视的第三方工具库内部使用了require语法。1.3 快速诊断错误类型根据我的经验可以通过以下特征快速定位问题根源错误特征可能原因解决方案方向报错指向业务代码手写了require/module.exports替换为ESM语法报错指向node_modules第三方库使用CJS配置打包工具转换开发正常生产报错环境配置不一致检查生产构建配置直接运行TS/JS文件未经过打包处理使用打包工具构建2. 六大典型场景深度解析2.1 代码中直接使用CommonJS语法这是我在代码审查中最常发现的问题特别是从Node.js转向前端开发的工程师容易犯这个错误。错误示例// 错误1直接使用require const utils require(./utils) // 错误2混合使用ESM和CJS import React from react const ReactDOM require(react-dom)解决方案统一使用ESM语法import utils from ./utils import ReactDOM from react-dom动态导入使用import()替代require// 正确方式 const loadModule async (name) { const module await import(./modules/${name}) // 使用模块 }注意事项使用ESLint配置no-require规则防止误用团队代码规范中明确禁止在前端代码中使用CJS语法对于历史遗留代码建议逐步迁移而非一次性重写2.2 TypeScript配置问题这个问题在TS项目中尤为常见我曾在三个不同的团队中发现过这个配置错误。错误表现源代码中没有显式的require编译后的JS文件中出现了require语句浏览器运行时报错根本原因tsconfig.json中module选项默认为CommonJS导致TS编译器将import/export转换为require/module.exports。正确配置{ compilerOptions: { target: ESNext, module: ESNext, moduleResolution: Bundler, esModuleInterop: true, strict: true } }关键点解释module: ESNext保留ESM语法不转换moduleResolution: Bundler适配现代打包工具esModuleInterop: true改善CJS和ESM互操作性2.3 Vite项目中的CJS转换Vite作为新一代构建工具对CJS的支持有其特殊性。我在迁移一个Webpack项目到Vite时曾踩过这个坑。问题特征开发环境正常生产构建后报错错误指向node_modules中的依赖解决方案// vite.config.js import { defineConfig } from vite export default defineConfig({ build: { commonjsOptions: { transformMixedEsModules: true, include: [/node_modules/] } }, optimizeDeps: { include: [cjs-dep1, cjs-dep2] } })深度解析Vite开发环境使用ESBuild处理依赖生产环境使用Rollup某些CJS依赖需要显式声明才能被正确处理transformMixedEsModules选项处理混合模块性能考量过多的CJS转换会影响构建速度建议优先选择ESM版本的依赖对于大型CJS依赖考虑外部化(external)2.4 Webpack配置要点虽然Webpack 4已经内置了对CJS的支持但配置不当仍会导致问题。常见错误配置// webpack.config.js module.exports { externals: { // 错误排除了需要转换的CJS依赖 cjs-dep: cjsDep } }正确配置module.exports { externals: { // 只排除通过CDN引入的依赖 cdn-dep: CDNDep }, module: { rules: [ { test: /\.js$/, exclude: /node_modules\/(?!(cjs-dep1|cjs-dep2)\/).*/, use: babel-loader } ] } }性能优化技巧使用include限定需要转换的模块范围避免全量转换node_modules对大型库考虑预构建2.5 Rollup的特殊处理Rollup原生仅支持ESM对CJS需要额外处理。我在开发一个组件库时曾因此浪费了两天时间。必要插件npm install rollup/plugin-commonjs rollup/plugin-node-resolve配置示例// rollup.config.js import commonjs from rollup/plugin-commonjs import nodeResolve from rollup/plugin-node-resolve export default { plugins: [ nodeResolve(), commonjs({ include: /node_modules/, transformMixedEsModules: true }) ] }高级技巧使用namedExports处理不规范的CJS模块对于循环依赖需要特殊配置考虑输出多种格式(ESM/UMD)2.6 CDN引入的全局变量这个问题在混合使用CDN和打包工具时常见。我见过一个项目同时通过CDN和npm引入jQuery导致的问题。错误模式script srchttps://cdn.example.com/react.js/script// 错误重复引入 import React from react正确做法配置externals// webpack.config.js module.exports { externals: { react: React } }直接使用全局变量// 直接使用CDN提供的全局变量 const { useState } React版本一致性检查确保CDN版本与类型定义匹配考虑使用window.前缀明确来源添加版本校验逻辑3. 工程化最佳实践3.1 统一模块规范策略基于多年项目经验我总结出以下规范前端项目强制使用纯ESM禁用CJS语法配置ESLint规则检查使用支持ESM的测试工具通用库开发源码使用ESM编写构建输出ESM和CJS双格式package.json配置module和main字段Node.js后端新项目推荐使用ESM旧项目逐步迁移注意__dirname等CJS特性的替代方案3.2 构建配置模板Vite TypeScript模板// vite.config.ts import { defineConfig } from vite import checker from vite-plugin-checker export default defineConfig({ plugins: [ checker({ typescript: true }) ], build: { target: esnext, commonjsOptions: { include: [/node_modules/] } } })Webpack现代配置// webpack.config.js module.exports { experiments: { outputModule: true // 输出ESM格式 }, externalsType: module, module: { rules: [ { test: /\.m?js$/, resolve: { fullySpecified: false // 放宽ESM严格解析 } } ] } }3.3 渐进式迁移策略对于大型遗留项目我推荐以下迁移路径评估阶段使用madge分析模块依赖图识别关键CJS依赖制定分阶段计划基础设施准备配置双模式支持设置类型检查建立CI验证逐步迁移从叶子模块开始逐个文件迁移及时更新依赖验证与优化性能基准测试包大小分析运行时验证4. 深度排查指南4.1 错误分析工具链源码分析grep -r require( src/查找显式使用AST分析工具识别隐式依赖构建产物检查source-map-explorer分析产物搜索构建后的require调用依赖审计npm ls分析依赖树检查关键依赖的模块格式4.2 高级调试技巧断点调试// 在可疑位置添加调试代码 console.log(typeof require) debugger运行时分析使用浏览器开发者工具检查调用栈捕获错误对象的完整信息环境模拟// 测试环境模拟浏览器全局对象 delete globalThis.require4.3 性能与兼容性权衡转换成本评估大型CJS库的转换开销树摇(Dead Code Elimination)效率浏览器兼容矩阵目标浏览器对ESM的支持度需要polyfill的特性缓存策略模块缓存对性能的影响长期缓存配置5. 未来展望与升级路径5.1 ECMAScript模块演进顶级await简化异步模块初始化JSON模块原生支持JSON导入Wasm模块更好的WebAssembly集成5.2 构建工具发展趋势原生ESM优先工具链全面转向ESMBundle-less开发基于ESM的即时编译Wasm构建性能关键部分的优化5.3 架构建议微前端适配模块系统在微前端中的设计Isomorphic代码同构应用的模块策略渐进式增强优雅降级方案经过多年实践我深刻体会到模块系统是前端工程化的基石。正确处理require is not defined这类问题不仅能解决眼前错误更能帮助团队建立规范的模块化开发体系。记住好的模块设计应该像乐高积木——标准化的接口灵活的组合清晰的边界。
企业数字化 ERP 产品动态
相关推荐
分布式系统与集群架构的核心区别与实践指南 1. 分布式系统与集群的本质区别在技术架构领域,"分布式"和"集群"这两个术语经常被混为一谈,但它们的核心设计理念和应用场景存在本质差异。我曾在多个大型系统架构中同时应用这两种技术方案,深刻体会到理解它们的区别对架… · 2026/11/3 8:38:28
从Function Calling到MCP:构建标准化的AI工具服务协议 1. Function Calling 的三堵墙:没有协议、没有边界、没有生命周期 如果你和我一样,是从 Function Calling 开始接触 AI 工具链的,大概率会在某个项目做到三分之二时感到不对劲:模型确实能输出结构化的 JSON 参数,你在代… · 2026/11/3 8:37:28
Web前端自动化测试实战:Playwright与Cypress对比 1. Web前端自动化测试的本质与挑战前端自动化测试的核心价值在于用机器代替人工执行重复性验证工作。作为一名经历过多个大型前端项目的老兵,我深刻体会到自动化测试不是简单的"录制回放",而是一套需要精心设计的工程体系。现代前端项目面临三… · 2026/11/3 8:37:28
STM32L4A6RG与MAX14431BAEE+的SPI隔离通信方案设计与实现 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:00:46
SPI隔离通信实战:MAX14431与MKV42F256VLH16设计调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:00:46
PIC18F86J11与MAX14431BAEE+隔离SPI设计实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:00:46
STM32L162ZE与MAX14431BAEE+的SPI隔离链路设计与调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:00:46
STM32L081CB与MAX14431BAEE+的隔离SPI通信设计与实现 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 9:00:46
流量与温度传感器输出信号选型指南:从原理到避坑实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 8:59:45
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46