原由: 前端
混合TypeScript和javaScript開發,完美升級老項目,這個老項目是一個巨無霸項目,很是龐大,是集團公司的最核心項目java
遇到問題: node
webpack打包時候遇到webpack
對於曾經開發過C++,addon的我,熟悉的味道,下面有一些v8的字符出現,感受應該是v8層面出現了問題c++
報錯解決: git
任何報錯,先看第一個報錯,解決頂部的報錯。github
問題定位: web
JS堆棧跟蹤,javaScript heap out of memory ,內存不足面試
隱約記得,v8對使用內存的限制,64位系統是1.4G,32位系統是0.7G,Buffer屬於C++層面,不會被限制。可是長度會被限制,當Buffer被建立時候就會被判斷長度npm
https://github.com/nodejs/node/blob/master/lib/buffer.js#L90-L101
node.js官網對長度的文檔描述:
這種簡單問題不作闡述,繼續
項目以前純js開發,如今接入ts,爲何一樣的電腦,以前能夠運行,如今卻內存不足?
答案:
解決辦法:
Node.js的8.0版本以上能夠這樣調整
export NODE_OPTIONS=--max_old_space_size=4096
也可使用自動化、工程化配置插件
increase-memory-limit
因爲一些部署服務器上的配置未知,在測試事後,我選擇了後者,編寫了新的構建命令,這樣達到效果。
難道作API工程師,不可能的,個人原則,使用第三方庫,框架必須看它的 源碼實現,包括Node.js
increase-memory-limit
源碼只有幾十行代碼
#!/usr/bin/env node const path = require('path'); const glob = require('glob'); const fs = require('fs'); const maxOldSpaceSize = process.env.LIMIT || 10240; const cwd = process.cwd() + path.sep; glob(path.join(cwd, "node_modules", ".bin", "*"), function (err, files) { files.forEach(file => { // readFileSync will crash on non-files. Skip over these let stat = fs.lstatSync(fs.realpathSync(file)); if (!stat.isFile()) { return; } if (file.indexOf('increase-memory-limit') >= 0) { return; } // build scripts will hand in LIMIT via cross-env // avoid updating it while we are running it if (file.indexOf('cross-env') >= 0) { return; } let contents = fs.readFileSync(file).toString(); let lines = contents.split('\n') let patchedContents = ""; for (var index = 0; index < lines.length; index++) { var line = lines[index]; if (line.startsWith("if [") || line.startsWith("@IF") || line.indexOf ('has_node') !== -1) { patchedContents += line + "\n"; } else { patchedContents += line.replace(/node(\.exe)?\b(?: \-\-max\-old\-space\-size\=[0-9]+)?/, `node$1 --max-old-space-size=${maxOldSpaceSize}`) + "\n"; } } fs.writeFileSync(file, patchedContents); console.log(`'${file.replace(cwd, "")}'`, "written successfully."); }); });
它依賴glob這個庫
https://www.npmjs.com/package/glob
首先讀取LIMIT配置
而後拿到node啓動的命令路徑(配置path.sep針對跨平臺,cwd返回的路徑作處理分隔)
var glob = require("glob")
經過glob這庫,傳入路徑和配置後,拿到包含文件數組,而後讀取文件流信息而且toString()
最核心的源碼文件就是下面這個
patchedContents += line + "\n"; } else { patchedContents += line.replace(/node(\.exe)?\b(?: \-\-max\-old\-space\-size\=[0-9]+)?/, `node$1 --max-old-space-size=${maxOldSpaceSize}`) + "\n"; } } fs.writeFileSync(file, patchedContents); console.log(`'${file.replace(cwd, "")}'`, "written successfully.");
經過正則將讀取的文件流信息,匹配相應的配置後,替換內容後同步寫入(由於必須同步寫入!!!不然項目沒法啓動,不能異步此處)
目前有一個系列寫做計劃,面試成長系列和踩坑成長系列同步進行,喜歡的話點個在看,關注下公衆號:前端巔峯。