πŸ“œ ⬆️ ⬇️

How ESLint reacts to the situation with the removal of packages from NPM

After the situation with the removal of packages from NPM, which affected a huge number of users of the packages babel , jscs and many others (you can read about this here: β€œA discussion about the Internet” ), many Open Source developers started to talk about future NPM and JS ecosystems in general.

Opinions are divided:


But the teams of large Open Source packages, on which a huge number of tickets in github fell, seriously thought about how to prevent this situation in the future. Those projects that are often used in CI were particularly affected, since it was CI users who first of all noticed problems with missing dependencies. One of these projects is ESLint , which has about 70,000 installations per day , most of which are in CI assemblies.

The decision of the ESLint development team was quite radical, but quite working. They decided to publish the ESLint package with all dependencies. That is, when downloading the ESLint archive, the npm utility also downloads the entire working node_modules for the required version of ESLint.
')
More about this change: β€œESLint v2.5.0 released” .

The very first thought that came to my mind after I learned this news was about performance. What will happen with the installation of ESLint? Will it become faster or slower. A small experiment showed that installing a package with built-in dependencies takes more time. In the case of ESLint - for 2 seconds (~ 25%):

npm install eslint@2.4.0 6.22s user 2.68s system 108% cpu 8.207 total npm install eslint@2.5.0 7.70s user 4.16s system 109% cpu 10.864 total 

Full output
 $ rm -Rf node_modules && time npm install eslint@2.4.0 && rm -Rf node_modules && time npm install eslint@2.5.0 eslint@2.4.0 node_modules/eslint β”œβ”€β”€ path-is-absolute@1.0.0 β”œβ”€β”€ ignore@2.2.19 β”œβ”€β”€ pluralize@1.2.1 β”œβ”€β”€ path-is-inside@1.0.1 β”œβ”€β”€ globals@8.18.0 β”œβ”€β”€ estraverse@4.2.0 β”œβ”€β”€ strip-json-comments@1.0.4 β”œβ”€β”€ esutils@2.0.2 β”œβ”€β”€ progress@1.1.8 β”œβ”€β”€ text-table@0.2.0 β”œβ”€β”€ user-home@2.0.0 (os-homedir@1.0.1) β”œβ”€β”€ is-resolvable@1.0.0 (tryit@1.0.2) β”œβ”€β”€ shelljs@0.5.3 β”œβ”€β”€ json-stable-stringify@1.0.1 (jsonify@0.0.0) β”œβ”€β”€ resolve@1.1.7 β”œβ”€β”€ debug@2.2.0 (ms@0.7.1) β”œβ”€β”€ doctrine@1.2.0 (esutils@1.1.6, isarray@1.0.0) β”œβ”€β”€ optionator@0.8.1 (fast-levenshtein@1.1.3, type-check@0.3.2, levn@0.3.0, wordwrap@1.0.0, deep-is@0.1.3, prelude-ls@1.1.2) β”œβ”€β”€ mkdirp@0.5.1 (minimist@0.0.8) β”œβ”€β”€ require-uncached@1.0.2 (resolve-from@1.0.1, caller-path@0.1.0) β”œβ”€β”€ chalk@1.1.1 (escape-string-regexp@1.0.5, supports-color@2.0.0, has-ansi@2.0.0, strip-ansi@3.0.1, ansi-styles@2.2.0) β”œβ”€β”€ concat-stream@1.5.1 (inherits@2.0.1, typedarray@0.0.6, readable-stream@2.0.6) β”œβ”€β”€ espree@3.1.3 (acorn@3.0.4, acorn-jsx@2.0.1) β”œβ”€β”€ is-my-json-valid@2.13.1 (jsonpointer@2.0.0, generate-function@2.0.0, xtend@4.0.1, generate-object-property@1.2.0) β”œβ”€β”€ inquirer@0.12.0 (ansi-regex@2.0.0, strip-ansi@3.0.1, ansi-escapes@1.3.0, figures@1.5.0, rx-lite@3.1.2, through@2.3.8, cli-width@2.1.0, run-async@0.1.0, cli-cursor@1.0.2, string-width@1.0.1, readline2@1.0.1) β”œβ”€β”€ table@3.7.8 (slice-ansi@0.0.4, tv4@1.2.7, xregexp@3.1.0, strip-ansi@3.0.1, string-width@1.0.1, bluebird@3.3.4) β”œβ”€β”€ js-yaml@3.5.5 (esprima@2.7.2, argparse@1.0.7) β”œβ”€β”€ glob@6.0.4 (inherits@2.0.1, inflight@1.0.4, once@1.3.3, minimatch@3.0.0) β”œβ”€β”€ file-entry-cache@1.2.4 (object-assign@4.0.1, flat-cache@1.0.10) β”œβ”€β”€ es6-map@0.1.3 (d@0.1.1, es6-symbol@3.0.2, event-emitter@0.3.4, es6-iterator@2.0.0, es6-set@0.1.4, es5-ext@0.10.11) β”œβ”€β”€ escope@3.6.0 (esrecurse@4.1.0, es6-weak-map@2.0.1) └── lodash@4.6.1 npm install eslint@2.4.0 6.22s user 2.68s system 108% cpu 8.207 total eslint@2.5.0 node_modules/eslint npm install eslint@2.5.0 7.70s user 4.16s system 109% cpu 10.864 total 

To include dependencies in the archive, the bundledDependencies setting for package.json is used (for more information, β€œpackage.json bundledDependencies” ). Setting this simple: takes an array of package names that will be included in the published archive.

To automate the process of publishing dependencies, ESLint uses a small bundle-dependencies package that simply builds bundledDependencies from dependencies and writes them to package.json.

In fact, this approach is somewhat contrary to the ideas of NPM, because the bundledDependencies option was invented to include in the archive those dependencies that are not published in the NPM registry.

We at JSCS have not yet decided what we will do. It will be interesting to observe how other development teams of Open Source projects will react to the situation with NPM (and whether they will react). Let's see if this approach will take root or if there are other alternatives.

UPD: Because of the problems that have appeared, changes associated with bundledDependencies have been rolled back in ESLint. Read more: "npm shrinkwrap fails> = 2.5.0" .

Source: https://habr.com/ru/post/280206/


All Articles