如何增加EsLint内存以避免JavaScript堆耗尽?

时间:2019-01-30 12:53:37

标签: javascript eslint heap-memory

我正在尝试在一个非常大型javascript文件上运行EsLint,并且该过程内存不足。为了让您了解我在文件上运行了Cloc的文件大小,这是输出:

$ cloc app.js 
       1 text file.
       1 unique file.                              
       0 files ignored.

github.com/AlDanial/cloc v 1.80  T=12.81 s (0.1 files/s, 42499.8 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
JavaScript                       1           4255          23744         516524
-------------------------------------------------------------------------------

文件重23MB。

$ ls -lAh app.js 
-rw-r--r-- 1 miguelangel staff 23M Jan 28 11:58 app.js

这就是说这很可能不是EsLint中的内存泄漏。我在Github.com上看到过EsLint内存泄漏的一些问题。我认为情况并非如此。

文件之所以如此之大,是因为它是串联许多其他Javascript模块的结果。我的目的是尝试查找任何未使用的代码。这个项目的代码库显然在不受控制的情况下增长了,我正试图脱颖而出。因此,我尝试在整个代码库的串联上运行EsLint's no-unused-vars rule。这是我的EsLint配置文件:

.eslintrc.js

module.exports = {
    "env": {
        "browser": true,
        "commonjs": false,
        "es6": true
    },
    "parserOptions": {
        "ecmaVersion": 2015
    },
    "rules": {
        "no-unused-vars": [
            "warn"
        ]
    }
};

该项目既不是Node也不是AMD项目,因此我认为必须将整个代码库放在一个文件中,以免出现误报。

问题是,尝试对此文件运行EsLint会导致JavaScript heap out of memory错误。

$ eslint app.js 

<--- Last few GCs --->

[60451:0x104002200]    43814 ms: Mark-sweep 1395.7 (1424.1) -> 1395.2 (1423.6) MB, 5719.6 / 0.0 ms  (+ 0.1 ms in 28 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 5755 ms) (average mu = 0.148, current mu = 0.037) alloca[60451:0x104002200]    49447 ms: Mark-sweep 1397.4 (1424.1) -> 1396.9 (1425.6) MB, 5569.8 / 0.0 ms  (+ 0.1 ms in 11 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 5598 ms) (average mu = 0.081, current mu = 0.011) alloca

<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0x3275f3d4fb7d]
Security context: 0x14c691f9d969 <JSObject>
    1: /* anonymous */ [0x14c6f1b7b981] [/usr/local/lib/node_modules/eslint/node_modules/acorn/dist/acorn.js:~2868] [pc=0x3275f40f5843](this=0x14c6b794c669 <Parser map = 0x14c603088f11>)
    2: /* anonymous */ [0x14c6f1b7b111] [/usr/local/lib/node_modules/eslint/node_modules/acorn/dist/acorn.js:2190] [bytecode=0x14c691fecb01 offset=968](this=0x14c6b794c669 <...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0x10003ace0 node::Abort() [/usr/local/bin/node]
 2: 0x10003aeb1 node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
 3: 0x10018c8cf v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 4: 0x10018c870 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
 5: 0x10047b188 v8::internal::Heap::UpdateSurvivalStatistics(int) [/usr/local/bin/node]
 6: 0x10047cc01 v8::internal::Heap::CheckIneffectiveMarkCompact(unsigned long, double) [/usr/local/bin/node]
 7: 0x10047a4c4 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
 8: 0x100479236 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
 9: 0x100481826 v8::internal::Heap::AllocateRawWithLightRetry(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
10: 0x100481b5c v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
11: 0x100461562 v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/usr/local/bin/node]
12: 0x100653464 v8::internal::Runtime_AllocateInNewSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
13: 0x3275f3d4fb7d 
Abort trap: 6

如何增加EsLint对内存的访问权限?

5 个答案:

答案 0 :(得分:3)

默认情况下,Node.js将内存限制设置为接近1.5 GB。您可以通过--max_old_space_size键来增加它(例如,--max_old_space_size=4096使用4 GB)。

要使用该密钥,您需要知道ESLint主文件的路径,并通过以下方式将其作为脚本调用:

node --max_old_space_size=4096 ./node_modules/eslint/bin/eslint.js app.js

答案 1 :(得分:2)

我浏览了EsLint文档,希望找到一个选项来配置它以运行更多内存。可悲的是我找不到任何东西。

但是,受到@vsemozhetbyt的回答的启发-投票赞成-我开始研究Node的配置选项,并找到了一种使用Node's NODE_OPTIONS environment variable解决此问题的方法。

  

以空格分隔的命令行选项列表。选项...的解释方式就像在命令行之前在命令行上指定了它们一样

这就是我所做的:

$ export NODE_OPTIONS="--max-old-space-size=4096"
$ echo $NODE_OPTIONS
--max-old-space-size=4096
$ eslint app.js

通过这种方式,运行EsLint的Node进程无需我每次输入EsLint都需要输入--max-old-space-size标志或Node二进制文件的路径即可完成此任务。

答案 2 :(得分:1)

从TSLint迁移到ESLint后,我遇到了相同的错误。就我而言,打字稿配置是一个瓶颈。 tslint.json文件中的这一行:

"extends": "tslint-consistent-codestyle"

通过此扩展,每个文件被分析了十几秒钟(2-3分钟后出现内存不足错误)。没有它,所有项目(数百个文件)将在几秒钟内被分析。

答案 3 :(得分:0)

如果所有有关增加节点--max_old_space_size的答案都无济于事,则值得从另一个角度来看它。 也许有太多错误,以至于Node堆实际上内存不足。

我有这种情况:

我加入了很多.js / .vue文件的大型项目。 .eslintrc中的"linebreak-style": [2, "unix"]表示行尾字符应为lf。我使用Windows,其中eol字符为crlf。默认情况下,Git将所有内容转换为crlf。因此,当我从git克隆此项目时,我看到Eslint发出了很多警告,提示Visual Studio Code中错误的eol字符,但控制台中的eslint总是以heap out of memory结尾。

在上述情况下,关于node out of memory的任何建议都无法帮助解决问题。

答案 4 :(得分:0)

我在Laravel / Vue应用程序中遇到此问题。这些细节并不重要,但是Laravel有一些文件夹,例如vendor,其中包含所有composer软件包,这意味着ES Lint正在遍历大量文件,足以炸毁堆

解决方案是先将.eslintignore文件添加到项目的根目录,例如:

/app
/bootstrap
/config
/database
/node_modules
/public
/routes
/storage
/tests
/vendor

下一步,从CLI(和GitLab-CI)执行ES Lint,如下:

node_modules/eslint/bin/eslint.js --config ./.eslintrc.json .

确保ES Lint使用正确的配置文件检查预期规则集也很重要。

您可以通过在CLI命令中添加--debug来直观地测试其中的一些内容,如果发生这种情况,您将看到它遍历了非法的文件夹和文件。我认为这是一个不错的调试步骤-在详细模式下对其进行测试。您可能会看到ES Lint遍历了不必要的文件夹或针对不正确的规则进行了测试。

我认为,此问题很容易源于ES Lint试图在运行时将大量错误加载到内存中。您可以拨入ES Lint确切是什么,而不是增加堆。