6.4 xxx is not a constructor,npx命令,webpack严格遵循导入导出,★★webpack学习小记,source-map无追踪

本文深入探讨Webpack与Babel的高级配置技巧,包括解决xxisnotaconstructor问题、npx命令使用、TreeShaking按需打包、代码分割、动态import支持及polyfill配置。旨在帮助开发者掌握前端构建工具的核心知识点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、xxx is not a constructor 问题两种情况
1.1、在尝试es5的require方式导入模块,发现打包时出现,Vue is not a constructor
在比对大佬的代码后,发现不同就是大佬使用的是es6的import引入Vue而我是require,
故尝试安装babel最新插件让webpack支持es6语法。
安装三大核心插件

    "@babel/core": "^7.4.5",
    "babel-loader": "^8.0.6",
    "babel-preset-env": "^1.7.0",

果然,经打包,Vue运行正常。

1.2、还有可能是模块未module.export导出

2、npx命令
可以运行存在于当前目录下的安装包相关命令。 比如 npx webpack -v 查看版本号

3、webpack严格遵循导入导出模块
2019年6月4日15:57:57 下午就犯了个错,浏览器还是报 xx is not a constructor 当时就懵了,后来倒回去看视频资料,才发现我忘记将模块导出。所以 webpack根本找不到你导出的模块。但是webpack会将你导入的模块重新命名成a,b,c,d等,所以排错比较困难。好在解决了。

4、学习webpack4的配置,由浅入深。
1、面向过程
2、面向对象
3、js引入模块概念
4、webpack找到index.js入口文件进行打包
5、entry output配置出入相关,publicPath
6、module rules:[]配置相关正则test,再指定use
7、use可对象可数组,具体分析,实战得真知。
8、厂商前缀postcss.config.js看文档。
9、importLoaders无效,用postcss-import
10、自动生成html,html-webpack-plugin // 检测生成的js,并script化
11、清理dist目录,{ clean-webpack-plugin }
12、如何自动刷新webpack,–watch node端 webpack-dev-server(热加载配置)
13、hotmoudlereplacement 热加载。
14.1、babel转义,babel-loader(通信),@babel/core(babel核心库),@babel/preset-env(转义,再配置 .babelrc 或者options中加入"presets": ["@babel/preset-env"]即可,
14.2、为了兼容低版本浏览器对新特性api的不支持。@babel/polyfill(需import '@babel/polyfill’到入口index.js文件内)
14.3、且根据api适配打包,配置参数要变化,如下:
在这里插入图片描述

关于第14点的总结:

如果只是业务代码:
babel-loader @babael/core是必须的
@babel/preset-env 是转义es6语法,在loader配置项引入"@babel…,",或文件注入都可以。
在这里插入图片描述
若要兼容低版本浏览器,就需要@babel/polyfill,它可以适配es6新api。
polyfill的使用需要在index.js入口文件,import ‘@babel/polyfill’,
默认是适配全部api(打包完体积非常大)。故要使用按需适配需要配置参数。主要是use里的options中的presets,或者.babelrc文件配置
在这里插入图片描述
useBuiltIns: ‘usage’ 开启即可

如果是第三方库项目代码
先注释掉入口文件的import “@babel/polyfill”(会污染全局变量)
需要根据以下官网安装库开发的相关插件

https://www.babeljs.cn/docs/babel-plugin-transform-runtime

且配置大概如下:
在这里插入图片描述
上述的所有配置过程,均可以通过创建.babelrc配置
在这里插入图片描述
在这里插入图片描述
注: .babelrc不能放注释,需要绝对干净,这点和.env.development一样

15.1、Tree Shaking按需打包导出过的方法。只支持静态引入,即esModule模块import引入,export检测是否导出。dev需配置optimization:{usedExports:true},package.json配置sideEffects:[]
Tree Shaking开发环境的配置:

// 1、webpack.config.js 部分配置:
mode: 'development',
devtool: 'cheap-module-eval-source-map',
optimization: {
	usedExports: true
}

// 2、在package.json 部分配置
sideEffects: ["@babel/polyfill", "*.css"] // 对polyfill和css后缀文件不进行shaking
sideEffects: false, // 无第三方模块,全部文件shaking

// 注: development模式下,打包文件仅会提示哪些use(便于production之前的观察),不会改变原代码。

Tree Shaking生产环境的配置(mode: “production”)

// 1、webpack.config.js 部分配置:
	mode: 'production',
	devtool: 'cheap-module-source-map'
	
注:production模式下optimization配置项可以不需要,官方已配置好。
	
// 2、在package.json 部分配置
	sideEffects: "..."  //必须配置。

15.2、 tree Shaking和polyfill的usedBuiltIn。前者是对模块是否导出的适配,后者是es6的api转义成es5的适配。
16、publicPath是公共路径,比如域名等等。
17、webpack-merge第三方插件
18、webpack是基于node环境运行的的,所以写法采用commonjs。而入口文件的编译是webpack做的,所以支持es6写法
19.1、Code Splitting 配置项optimization:{splitChunks:{chunks:‘all’}}(这是同步模块的分割。异步模块可以无需配置,webpack自动会分割)。
19.2 注:代码分割和webpack无关。
20、解决Support for the experimental syntax ‘dynamicImport’ isn’t currently enabled问题,需要安装实验语法babel-plugin-dynamic-import-webpack第三方插件 ,在.babelrc下添加"plugins": [“dynamic-import-webpack”]
21、但 dynamic-import-webpack不支持模板注释的写法(比如/* webpackChunkName: subarea */),故删除掉该插件。取而代之找官方提供的插件。
22、为了适配异步模块的实验语法支持,官方提供了babel import dynamic插件
23、默认splitChunks默认是仅支持异步模块分割,且配置了cacheGroups参数使异步模块打包入vender组内。(默认是async,若开启同步模块分割,需要将chunks: ‘all’)
24、vendors组test的是node_module下的库,所以,它是第三方模块插件的打包组。

在这里插入图片描述
25、 cacheGroups: {vendors:{…}}打包的模块和cacheGroups的配置参数是配合使用的。如果未定义组的规则,那么即便检测到同步或异步模块需分割,无分割适配组,也不能分割成功、
26、js懒加载是es实验语法import的结果,异步模块均为懒加载。
27、首屏渲染利用率问题,以及preloading,prefetching,以魔法注释来写生效,后者较优。

// 当首屏渲染结束,且网络带宽闲置时,prefetch开始加载。
import(/* webpackPrefetch: true */ './click.js').then(异步代码)
// preload是和主文件一起加载。
import(/* webpackPreload: true */ './click.js').then(异步代码)

5、devtool: ‘source-map’ 文件报错时无法追踪映射地址。
经尝试,devtools: ‘eval-source-map’ 包括其他eval属性的sourceMap都可以追踪映射地址。
在这里插入图片描述
inline-source-map也可以,只要不生成map.js映射文件的sourceMap模式都可以。

<think>好的,用户遇到了“ReferenceError: document is not defined”的错误,并且提到可能与在非浏览器环境中操作DOM有关。我需要仔细分析这个问题,并给出解决方案。 首先,用户的问题是在Node.js或非浏览器环境中出现这个错误。根据经验,这个错误通常是因为在Node.js环境中使用了浏览器特有的API,比如document对象。Node.js没有内置的DOM环境,所以当代码尝试访问document或window时就会抛出这个错误。 接下来,我需要回顾用户之前的对话历史。用户之前询问的是如何在D3.js、React和Three.js中绘制节点,这些都是在浏览器环境中运行的库。可能用户在尝试在Node.js环境下运行前端代码,或者混淆了前后端的环境。 用户提供的引用中提到了Express路由和浏览器引擎的差异,但这些可能与当前问题关联不大。不过,引用[2]讨论了不同浏览器对clientHeight的支持,这可能暗示用户之前在处理DOM元素时遇到了兼容性问题,但现在的问题是在Node.js中访问DOM导致的错误。 需要确定用户的具体使用场景。比如,用户是否在服务器端渲染(SSR)中使用前端库?或者在Node.js脚本中误用了DOM操作?常见的情况可能包括: 1. 在Node.js中直接运行前端代码,比如使用D3.js或jQuery操作DOM。 2. 使用服务器端渲染框架(如Next.js)时,没有正确处理浏览器特定的代码。 3. 在测试环境中(如Jest)运行涉及DOM的测试用例,而没有配置模拟环境。 接下来,我需要解释错误的原因:在Node.js环境中,没有document对象,因此任何直接调用document的方法都会导致错误。例如,使用document.getElementById或React的某些渲染方法在服务器端执行时,如果没有适当处理,就会出错。 解决方案方面,可以分几种情况: 1. **代码运行环境区分**:明确区分前端和后端代码,确保DOM操作只在浏览器中执行。 2. **条件判断**:在可能执行于Node.js的代码中添加环境判断,避免调用浏览器API。 3. **使用模拟库**:在测试或SSR中使用如jsdom来模拟DOM环境。 4. **框架特定解决方案**:比如在Next.js中使用动态导入,或Effect钩子确保代码仅在客户端运行。 用户可能需要具体的代码示例,比如如何在React中避免服务器端渲染时的document访问,或者如何在测试中配置jsdom。同时,需要提醒用户注意第三方库可能隐含的DOM操作,比如某些图表库可能在导入时立即访问DOM,导致错误。 还需要检查用户是否在Node.js中错误地引入了前端库,比如在服务器端脚本中导入Three.js或D3的DOM相关部分,这也会导致问题。建议用户检查他们的导入语句,并确保只在浏览器环境中使用这些库。 最后,总结解决方案,强调环境区分的重要性,并提供不同场景下的处理方式,帮助用户根据具体情况选择合适的解决方法。</think>根据您的技术背景和之前探讨的可视化方案,我们针对$ReferenceError: document\ is\ not\ defined$错误进行专业分析: ### 错误本质解析 该错误表明代码尝试在Node.js环境中访问浏览器专属的DOM API,坐标系为: $$ \exists env \in \{ Node.js \}, \forall x \in DOM\ API,\ x \notin env $$ ### 核心解决方案矩阵 #### 方案一:环境隔离(推荐) ```typescript // 客户端专用模块 client-utils.ts export const safeDOM = { getElement: (id: string) => typeof document !== 'undefined' ? document.getElementById(id) : null }; // 服务端安全调用 import { safeDOM } from './client-utils'; const element = safeDOM.getElement('canvas-container'); ``` #### 方案二:动态加载(Next.js最佳实践) ```tsx // 使用Next.js动态导入 import dynamic from 'next/dynamic'; const ThreeScene = dynamic( () => import('../components/ThreeScene'), { ssr: false } ); // 页面组件 export default () => <ThreeScene nodes={nodes} />; ``` #### 方案三:SSR兼容模式 ```javascript // 通用代码适配方案 const isBrowser = () => ![typeof window, typeof document].includes('undefined'); class NodeRenderer { constructor() { if (isBrowser()) { this.initWebGL(); // 调用Three.js/D3.js初始化 } } } ``` ### 常见错误模式对照表 | 错误模式示例 | 修复方案 | 数学表达 | |------------|---------|---------| | `document.querySelector()` | 环境检测包装 | $$ f(x) = \begin{cases} document.query(x) & \text{if } env=Browser \\ \emptyset & \text{otherwise} \end{cases} $$ | | `window.innerWidth` | 使用React Hook | $$ w = useSyncExternalStore(subscribe, getSnapshot) $$ | | 直接导入Three.js | 动态加载 | $$ \frac{\partial Library}{\partial Env} \bigg|_{SSR} = 0 $$ | ### 高级调试技巧 1. **依赖树分析**: ```bash # 检查依赖链 npx madge src/index.tsx --circular ``` 2. **Webpack配置检测**: ```javascript // webpack.config.js externals: { 'three': 'THREE' // 避免服务端打包Three.js } ``` 3. **内存分析工具**: ```javascript const { performance } = require('perf_hooks'); performance.mark('dom-start'); ``` ### 扩展解决方案(参考您之前的可视化需求) 对于需要服务端预计算的Three.js场景: ```typescript // 服务端安全计算 const calculateLayout = (nodes: IMysqlNode[]) => { // 使用纯数学计算替代DOM操作 return nodes.map(node => ({ ...node, x: node.size[0] * Math.cos(node.angle), y: node.size[1] * Math.sin(node.angle) })); }; ``` [^1]: Next.js官方文档关于动态导入的说明 [^2]: Three.js服务端渲染最佳实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值