Angular应用添加多Web Worker时出现JavaScript堆内存不足编译错误
Angular多Web Worker编译时JavaScript堆内存不足的解决办法
问题场景
在Visual Studio Code中为Angular应用添加4个Web Worker后,编译阶段出现JavaScript堆内存不足错误。Web Worker调用代码示例如下:
async executeWorker1() { return new Promise((resolve, reject) => { if (typeof Worker !== 'undefined') { const worker = new Worker(new URL('../workers/app.some1.worker', import.meta.url)); worker.onmessage = ({ data }) => { // receiving values... worker.terminate(); resolve(true); }; worker.postMessage(/* passing values... */); } else { reject(false); } }); } async executeWorker2() { return new Promise((resolve, reject) => { if (typeof Worker !== 'undefined') { const worker = new Worker(new URL('../workers/app.some2.worker', import.meta.url)); worker.onmessage = ({ data }) => { // receiving values... worker.terminate(); resolve(true); }; worker.postMessage(/* passing values... */); } else { reject(false); } }); } async executeWorker3() { return new Promise((resolve, reject) => { if (typeof Worker !== 'undefined') { const worker = new Worker(new URL('../workers/app.some3.worker', import.meta.url)); worker.onmessage = ({ data }) => { // receiving values... worker.terminate(); resolve(true); }; worker.postMessage(/* passing values... */); } else { reject(false); } }); } async executeWorker4() { return new Promise((resolve, reject) => { if (typeof Worker !== 'undefined') { const worker = new Worker(new URL('../workers/app.some4.worker', import.meta.url)); worker.onmessage = ({ data }) => { // receiving values... worker.terminate(); resolve(true); }; worker.postMessage(/* passing values... */); } else { reject(false); } }); }
编译时错误日志:
⠧ Generating browser application bundles (phase: building)... <--- Last few GCs ---> [4952:00000204555A4F50] 103198 ms: Mark-sweep (reduce) 2030.4 (2079.1) -> 2030.4 (2078.6) MB, 694.2 / 0.1 ms (average mu = 0.162, current mu = 0.000) allocation failure GC in old space requested [4952:00000204555A4F50] 103895 ms: Mark-sweep (reduce) 2030.4 (2078.6) -> 2030.4 (2077.9) MB, 697.3 / 0.1 ms (average mu = 0.088, current mu = 0.000) last resort GC in old space requested <--- JS stacktrace ---> FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 1: 00007FF659FC79CF v8::internal::CodeObjectRegistry::~CodeObjectRegistry+114207 2: 00007FF659F56096 DSA_meth_get_flags+65542 3: 00007FF659F56F4D node::OnFatalError+301 4: 00007FF65A88B1EE v8::Isolate::ReportExternalAllocationLimitReached+94 5: 00007FF65A8757CD v8::SharedArrayBuffer::Externalize+781 6: 00007FF65A718B9C v8::internal::Heap::EphemeronKeyWriteBarrierFromCode+1468 7: 00007FF65A725849 v8::internal::Heap::PublishPendingAllocations+1129 8: 00007FF65A72281A v8::internal::Heap::PageFlagsAreConsistent+2842 9: 00007FF65A715479 v8::internal::Heap::CollectGarbage+2137 10: 00007FF65A714542 v8::internal::Heap::CollectAllAvailableGarbage+130 11: 00007FF65A7136BF v8::internal::Heap::AllocateExternalBackingStore+2143 12: 00007FF65A731340 v8::internal::FreeListManyCached::Reset+1408 13: 00007FF65A7319F5 v8::internal::Factory::AllocateRaw+37 14: 00007FF65A74399E v8::internal::FactoryBase<v8::internal::Factory>::AllocateRawArray+46 15: 00007FF65A7465DA v8::internal::FactoryBase<v8::internal::Factory>::NewFixedArrayWithFiller+74 16: 00007FF65A746833 v8::internal::FactoryBase<v8::internal::Factory>::NewFixedArrayWithMap+35 17: 00007FF65A54CBE3 v8::internal::HashTable<v8::internal::EphemeronHashTable,v8::internal::ObjectHashTableShape>::EnsureCapacity<v8::internal::Isolate>+243 18: 00007FF65A56475C v8::internal::ObjectHashTableBase<v8::internal::EphemeronHashTable,v8::internal::ObjectHashTableShape>::Put+556 19: 00007FF65A5695FD v8::internal::JSWeakCollection::Set+173 20: 00007FF65A475602 v8::internal::CompilationCache::IsEnabledScriptAndEval+7586 21: 00007FF65A918EE1 v8::internal::SetupIsolateDelegate::SetupHeap+494417 22: 00007FF65A913B9C v8::internal::SetupIsolateDelegate::SetupHeap+473100 23: 00007FF65A9128EB v8::internal::SetupIsolateDelegate::SetupHeap+468315 24: 00000204583649CF
已尝试设置NODE_OPTIONS=--max-old-space-size=10240、升级Node.js到v18.16.1,但问题未解决。
解决方案
1. 确保Node内存参数正确生效
PowerShell中设置环境变量的命令有误,应使用:
$env:NODE_OPTIONS="--max-old-space-size=10240"
执行后验证参数是否生效:
node -e "console.log(v8.getHeapStatistics().heap_size_limit/(1024*1024))"
输出应接近10240MB,否则说明参数未正确加载。
2. 直接给Angular CLI指定内存参数
如果环境变量方式无效,修改package.json中的构建脚本,直接为Node进程指定内存:
"scripts": { "build": "node --max-old-space-size=10240 ./node_modules/@angular/cli/bin/ng build" }
之后执行npm run build即可。
3. 优化Web Worker调用代码
四个Worker调用逻辑高度重复,封装为通用函数减少代码冗余,同时帮助构建工具优化编译流程:
async executeWorker(workerPath: string, payload: any) { return new Promise((resolve, reject) => { if (typeof Worker !== 'undefined') { const worker = new Worker(new URL(workerPath, import.meta.url)); worker.onmessage = ({ data }) => { // 统一处理接收的数据 worker.terminate(); resolve(true); }; worker.postMessage(payload); } else { reject(false); } }); } // 调用示例 async executeWorker1() { return this.executeWorker('../workers/app.some1.worker', { /* 传入参数 */ }); } async executeWorker2() { return this.executeWorker('../workers/app.some2.worker', { /* 传入参数 */ }); }
4. 优化Web Worker内部代码
检查每个Worker文件,移除不必要的依赖、大体积资源或重复代码。如果Worker需要引入第三方库,尽量使用动态导入减少初始编译压力:
// 在Worker内部使用动态导入 async function init() { const { someHeavyLib } = await import('some-heavy-lib'); // 使用库处理任务 } init();
5. 调整Angular构建配置
修改angular.json中的构建选项,启用构建优化并调整缓存策略:
"architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "buildOptimizer": true, "optimization": true, "cache": true, // 其他配置 } } }
内容的提问来源于stack exchange,提问作者Sukanta Roy
相关产品推荐
相关产品推荐

