Closed sindresorhus closed 7 years ago
@sindresorhus: That appears to be a bug on your machine. On mine it works fine:
ls
spits out the size kind of weird (in raw bytes, floored), it's actually 33.2MB:
npm ls
:
/Users/Ari/Developer/.tmp
βββ¬ ava@0.8.0
βββ arr-flatten@1.0.1
βββ arrify@1.0.1
βββ¬ ava-init@0.1.3
β βββ arr-exclude@1.0.0
β βββ pify@2.3.0
β βββ¬ pinkie-promise@2.0.0
β β βββ pinkie@2.0.1
β βββ¬ read-pkg-up@1.0.1
β β βββ¬ find-up@1.1.0
β β β βββ path-exists@2.1.0
β β βββ¬ read-pkg@1.1.0
β β βββ¬ load-json-file@1.1.0
β β β βββ¬ parse-json@2.2.0
β β β β βββ¬ error-ex@1.3.0
β β β β βββ is-arrayish@0.2.1
β β β βββ¬ strip-bom@2.0.0
β β β βββ is-utf8@0.2.1
β β βββ path-type@1.1.0
β βββ the-argv@1.0.0
β βββ¬ write-pkg@1.0.0
β βββ¬ write-json-file@1.2.0
β βββ¬ sort-keys@1.1.1
β βββ is-plain-obj@1.1.0
βββ¬ babel-core@5.8.34
β βββ babel-plugin-constant-folding@1.0.1
β βββ babel-plugin-dead-code-elimination@1.0.2
β βββ babel-plugin-eval@1.0.1
β βββ babel-plugin-inline-environment-variables@1.0.1
β βββ babel-plugin-jscript@1.0.4
β βββ babel-plugin-member-expression-literals@1.0.1
β βββ babel-plugin-property-literals@1.0.1
β βββ babel-plugin-proto-to-assign@1.0.4
β βββ babel-plugin-react-constant-elements@1.0.3
β βββ babel-plugin-react-display-name@1.0.3
β βββ babel-plugin-remove-console@1.0.1
β βββ babel-plugin-remove-debugger@1.0.1
β βββ babel-plugin-runtime@1.0.7
β βββ¬ babel-plugin-undeclared-variables-check@1.0.2
β β βββ leven@1.0.2
β βββ babel-plugin-undefined-to-void@1.1.6
β βββ babylon@5.8.34
β βββ bluebird@2.10.2
β βββ convert-source-map@1.1.2
β βββ core-js@1.2.6
β βββ¬ detect-indent@3.0.1
β β βββ get-stdin@4.0.1
β β βββ minimist@1.2.0
β βββ esutils@2.0.2
β βββ fs-readdir-recursive@0.1.2
β βββ globals@6.4.1
β βββ¬ home-or-tmp@1.0.0
β β βββ os-tmpdir@1.0.1
β β βββ user-home@1.1.1
β βββ is-integer@1.0.6
β βββ js-tokens@1.0.1
β βββ json5@0.4.0
β βββ¬ line-numbers@0.2.0
β β βββ left-pad@0.0.3
β βββ lodash@3.10.1
β βββ¬ minimatch@2.0.10
β β βββ¬ brace-expansion@1.1.2
β β βββ balanced-match@0.3.0
β β βββ concat-map@0.0.1
β βββ¬ output-file-sync@1.1.1
β β βββ¬ mkdirp@0.5.1
β β βββ minimist@0.0.8
β βββ path-exists@1.0.0
β βββ path-is-absolute@1.0.0
β βββ private@0.1.6
β βββ¬ regenerator@0.8.40
β β βββ¬ commoner@0.10.4
β β β βββ¬ commander@2.9.0
β β β β βββ graceful-readlink@1.0.1
β β β βββ¬ detective@4.3.1
β β β β βββ acorn@1.2.2
β β β β βββ defined@1.0.0
β β β βββ glob@5.0.15
β β β βββ iconv-lite@0.4.13
β β β βββ q@1.4.1
β β βββ¬ defs@1.1.1
β β β βββ¬ alter@0.2.0
β β β β βββ stable@0.1.5
β β β βββ ast-traverse@0.1.1
β β β βββ breakable@1.0.0
β β β βββ simple-fmt@0.1.0
β β β βββ simple-is@0.2.0
β β β βββ stringmap@0.2.2
β β β βββ stringset@0.2.1
β β β βββ tryor@0.1.2
β β β βββ¬ yargs@3.27.0
β β β βββ camelcase@1.2.1
β β β βββ¬ cliui@2.1.0
β β β β βββ¬ center-align@0.1.2
β β β β β βββ¬ align-text@0.1.3
β β β β β β βββ¬ kind-of@2.0.1
β β β β β β β βββ is-buffer@1.1.0
β β β β β β βββ repeat-string@1.5.2
β β β β β βββ lazy-cache@0.2.7
β β β β βββ right-align@0.1.3
β β β βββ decamelize@1.1.2
β β β βββ¬ os-locale@1.4.0
β β β β βββ¬ lcid@1.0.0
β β β β βββ invert-kv@1.0.0
β β β βββ window-size@0.1.4
β β β βββ y18n@3.2.0
β β βββ esprima-fb@15001.1001.0-dev-harmony-fb
β β βββ¬ recast@0.10.33
β β β βββ ast-types@0.8.12
β β βββ through@2.3.8
β βββ¬ regexpu@1.3.0
β β βββ esprima@2.7.1
β β βββ regenerate@1.2.1
β β βββ regjsgen@0.2.0
β β βββ¬ regjsparser@0.1.5
β β βββ jsesc@0.5.0
β βββ repeating@1.1.3
β βββ resolve@1.1.6
β βββ shebang-regex@1.0.0
β βββ slash@1.0.0
β βββ source-map@0.5.3
β βββ¬ source-map-support@0.2.10
β β βββ source-map@0.1.32
β βββ to-fast-properties@1.0.1
β βββ trim-right@1.0.1
β βββ try-resolve@1.0.1
βββ¬ babel-plugin-espower@1.1.0
β βββ array-find@1.0.0
β βββ¬ escallmatch@1.4.2
β β βββ deep-equal@1.0.1
β β βββ esprima@2.7.1
β β βββ¬ espurify@1.5.0
β β β βββ isarray@1.0.0
β β βββ indexof@0.0.1
β βββ¬ espower@1.2.1
β β βββ¬ escodegen@1.7.1
β β β βββ esprima@1.2.5
β β β βββ estraverse@1.9.3
β β β βββ¬ optionator@0.5.0
β β β β βββ deep-is@0.1.3
β β β β βββ fast-levenshtein@1.0.7
β β β β βββ levn@0.2.5
β β β β βββ prelude-ls@1.1.2
β β β β βββ type-check@0.3.1
β β β β βββ wordwrap@0.0.2
β β β βββ source-map@0.2.0
β β βββ is-url@1.2.1
β β βββ isarray@0.0.1
β βββ xtend@4.0.1
βββ babel-runtime@5.8.34
βββ bluebird@3.1.1
βββ¬ chalk@1.1.1
β βββ ansi-styles@2.1.0
β βββ escape-string-regexp@1.0.4
β βββ¬ has-ansi@2.0.0
β β βββ ansi-regex@2.0.0
β βββ strip-ansi@3.0.0
β βββ supports-color@2.0.0
βββ¬ co-with-promise@4.6.0
β βββ¬ pinkie-promise@1.0.0
β βββ pinkie@1.0.0
βββ¬ core-assert@0.1.3
β βββ buf-compare@1.0.0
βββ¬ debug@2.2.0
β βββ ms@0.7.1
βββ deeper@2.1.0
βββ¬ empower@1.1.0
β βββ array-filter@1.0.0
β βββ array-foreach@1.0.1
β βββ array-map@0.0.0
β βββ array-some@1.0.0
β βββ¬ define-properties@1.1.2
β β βββ foreach@2.0.5
β βββ¬ object-create@0.1.0
β βββ¬ object-define-property@0.1.0
β βββ function-bind@0.1.0
β βββ has@0.0.1
βββ¬ empower-core@0.2.0
β βββ call-signature@0.0.2
βββ figures@1.4.0
βββ fn-name@2.0.1
βββ¬ globby@4.0.0
β βββ¬ array-union@1.0.1
β β βββ array-uniq@1.0.2
β βββ¬ glob@6.0.2
β βββ¬ inflight@1.0.4
β β βββ wrappy@1.0.1
β βββ inherits@2.0.1
β βββ once@1.3.3
βββ has-generator@1.0.0
βββ is-generator-fn@1.0.0
βββ¬ is-observable@0.1.0
β βββ symbol-observable@0.1.0
βββ is-promise@2.1.0
βββ¬ loud-rejection@1.2.0
β βββ signal-exit@2.1.2
βββ max-timeout@1.0.0
βββ¬ meow@3.6.0
β βββ¬ camelcase-keys@2.0.0
β β βββ camelcase@2.0.1
β β βββ map-obj@1.0.1
β βββ minimist@1.2.0
β βββ¬ normalize-package-data@2.3.5
β β βββ hosted-git-info@2.1.4
β β βββ¬ is-builtin-module@1.0.0
β β β βββ builtin-modules@1.1.0
β β βββ semver@5.1.0
β β βββ¬ validate-npm-package-license@3.0.1
β β βββ¬ spdx-correct@1.0.2
β β β βββ spdx-license-ids@1.1.0
β β βββ¬ spdx-expression-parse@1.0.2
β β βββ spdx-exceptions@1.0.4
β βββ¬ redent@1.0.0
β β βββ¬ indent-string@2.1.0
β β β βββ repeating@2.0.0
β β βββ strip-indent@1.0.1
β βββ trim-newlines@1.0.0
βββ object-assign@4.0.1
βββ observable-to-promise@0.1.0
βββ¬ plur@2.1.2
β βββ irregular-plurals@1.1.0
βββ¬ power-assert-formatter@1.3.2
β βββ acorn@2.6.4
β βββ acorn-es7-plugin@1.0.11
β βββ array-reduce@0.0.0
β βββ eastasianwidth@0.1.1
β βββ estraverse@4.1.1
β βββ googlediff@0.1.0
β βββ object-keys@1.0.9
β βββ¬ stringifier@1.2.1
β β βββ array-reduce-right@1.0.0
β β βββ traverse@0.6.6
β βββ type-name@1.1.0
βββ power-assert-renderers@0.1.0
βββ¬ pretty-ms@2.1.0
β βββ¬ is-finite@1.0.1
β β βββ number-is-nan@1.0.0
β βββ parse-ms@1.0.0
β βββ plur@1.0.0
βββ require-from-string@1.1.0
βββ¬ resolve-cwd@1.0.0
β βββ resolve-from@2.0.0
βββ serialize-error@1.1.0
βββ set-immediate-shim@1.0.1
βββ¬ source-map-support@0.4.0
β βββ¬ source-map@0.1.32
β βββ amdefine@1.0.0
βββ¬ squeak@1.3.0
β βββ console-stream@0.1.1
β βββ¬ lpad-align@1.1.0
β βββ longest@1.0.1
β βββ lpad@2.0.1
βββ¬ time-require@0.1.2
β βββ¬ chalk@0.4.0
β β βββ ansi-styles@1.0.0
β β βββ has-color@0.1.7
β β βββ strip-ansi@0.1.1
β βββ date-time@0.1.1
β βββ¬ pretty-ms@0.2.2
β β βββ parse-ms@0.1.2
β βββ text-table@0.2.0
βββ¬ update-notifier@0.5.0
βββ¬ configstore@1.4.0
β βββ graceful-fs@4.1.2
β βββ¬ osenv@0.1.3
β β βββ os-homedir@1.0.1
β βββ uuid@2.0.1
β βββ¬ write-file-atomic@1.1.4
β β βββ imurmurhash@0.1.4
β β βββ slide@1.1.6
β βββ xdg-basedir@2.0.0
βββ is-npm@1.0.0
βββ¬ latest-version@1.0.1
β βββ¬ package-json@1.2.0
β βββ¬ got@3.3.1
β β βββ¬ duplexify@3.4.2
β β β βββ end-of-stream@1.0.0
β β β βββ¬ readable-stream@2.0.5
β β β βββ core-util-is@1.0.2
β β β βββ isarray@0.0.1
β β β βββ process-nextick-args@1.0.6
β β β βββ string_decoder@0.10.31
β β β βββ util-deprecate@1.0.2
β β βββ infinity-agent@2.0.3
β β βββ is-redirect@1.0.0
β β βββ is-stream@1.0.1
β β βββ lowercase-keys@1.0.0
β β βββ nested-error-stacks@1.0.2
β β βββ object-assign@3.0.0
β β βββ prepend-http@1.0.3
β β βββ¬ read-all-stream@3.0.1
β β β βββ¬ pinkie-promise@1.0.0
β β β βββ pinkie@1.0.0
β β βββ timed-out@2.0.0
β βββ¬ registry-url@3.0.3
β βββ¬ rc@1.1.5
β βββ deep-extend@0.4.0
β βββ ini@1.3.4
β βββ minimist@1.2.0
β βββ strip-json-comments@1.0.4
βββ semver-diff@2.1.0
βββ string-length@1.0.1
So I'm really not sure why you're seeing that. Maybe file a bug report with npm?
Actually, it is only ~16.5 MB
, @ariporad's number includes dev-dependencies. You need to delete node_modules
and run
$ npm install --production
If you create a new project and just do this:
$ npm init
# default for every prompt
$ npm i babel-core babel-preset-es2015 babel-preset-stage-2
I get a relatively svelte 6.8 MB
.
Adding babel-plugin-espower
brings me to 9.8 MB
. That seems like a pretty significant jump. @twada - Any ideas how we can reduce this?
Adding babel-runtime@6.X.X
does bump me up to 14 MB
, but that is due to massive duplication of babel-runtime@5.X.X
. It gets copied into the node_modules folder of every babel-plugin-transform-*
. This is expected, since current babel plugins are written in ES6, compiled with babel@5
, and maintain a dev-dependency on babel-runtime@5
. This really does not hurt your install times though, since all those duplicates are definitely coming from the cache (babel-runtime
is not re-downloaded 20 times).
2.5 MB
for the remaining 30 some dependencies we have seems pretty reasonable.
@jamestalmage: that's strange, I did go above and beyond my usual intelligence level and create a new project to install AVA, but I'll try again when I'm home.
What are we hoping to achieve here? With changing dependencies this is a never ending struggle.
That said, looks like all Babel dependencies require babel-runtime@^5
, whereas we explicitly install ^6
. There's FIFTY copies of babel-runtime@5.8.35
.
Presumably we could downgrade to ^5
for the time being and we'd save a lot space. In my testing that takes us from 77MB to 29MB.
Of course there's other dependencies doing weird stuff, like fsevents
which pulls in 7MB just for node-pre-gyp.
To measure I did a fresh install from NPM (in an empty directory) and ran du -k -d 1 node_modules | sort -n -r
. Also check out snyk-resolve which shows the actual dependencies, not deduped.
@novemberborn There are some things that can be done even if the worst offender, Babel and fsevents, are out of our control. Many packages include junk like tests or examples directory, etc. I did a PR marathon a few years ago for Yeoman on 100+ different packages adding a "files" property to their package.json to reduce the total disk size of the dependency tree. That helped a lot. Pretty much have this still open for when I have time to do the same here.
Pretty much have this still open for when I have time to do the same here.
Sure, fair enough. Somebody should write a tool for that :stuck_out_tongue_winking_eye:
Also thinking about it more I'm doubtful we can change our babel-runtime
version. Presumably the runtime transformer plugin builds against v6, not v5.
Also thinking about it more I'm doubtful we can change our babel-runtime version. Presumably the runtime transformer plugin builds against v6, not v5.
Actually if we have a dependency which merely reexports babel-runtime
it would allow npm to dedupe babel-runtime@5
instead.
Actually if we have a dependency which merely reexports babel-runtime it would allow npm to dedupe babel-runtime@5 instead.
I thought about that. Actually, I think it would be better if Babel did that (all the Babel 6 plugins should depend on a differently named module that exports babel-runtime@5
). That way everyone benefits.
Actually, I think it would be better if Babel did that (all the Babel 6 plugins should depend on a differently named module that exports babel-runtime@5). That way everyone benefits.
:+1:
Is detecting Node v6 possible or an option? Would we still want babel to be part of ava when the environment is ES2015-compliant?
@jokeyrhyme AVA still injects features that have not yet landed in ES2015 or ES2016, such as async/await
. Additionally, it uses Babel for internal transforms (enhancing assertions with power-assert for instance).
I don't know if it's possible to correctly detect the Node version, but that'd be at runtime, not at install time. The team could remove the ES2015 preset when all supported Node versions support it, but that could take a while.
@jfmengels we might be able to install babel in a pre/post-install npm hook, and only install exactly the transforms needed to get us from the current version of node to stage-2 or whatever our threshold is. That would mean fewer dependencies for newer Nodes?
@jokeyrhyme That's unfortunately not an option for so many reasons. Some of the best features of AVA require Babel, so I don't see why anyone would want to drop it for some minor space savings. The biggest Babel size issue is about to get fixed anyways https://github.com/babel/babel/pull/3438.
If you want to help out with this, I'd suggest you find packages in the dependency tree that includes junk like test/examples/etc folders and ask them (or better yet do a PR) to use the files
property in package.json.
Here's a list of packages we depend on that doesn't have a files entry or .npmignore. Please help us reduce the size of AVA by submitting PRs to those packages adding a files
property in package.json.
Tip: $ npm i -g npm-home
and then just write nh package-name
to go to a specific package.
.npmignore
.npmignore
files
entry in package.json
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
files
entry in package.json
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
files
entry package.json
The list was generated with:
β― package-config-checker | grep β | sed 's/^ *β/- [ ]/g'
It may also be worth thinking about install time as well as size. See #841 -- on my machine, AVA's install took ~50.1s. I wonder how much of that is I/O (in which case it will be fixed by addressing the size issue) vs. dependency resolution (in which case the deep nesting itself is also a cause) vs. network traffic (a bit of both, since package requests are made individually).
Another option is to pull out some of the larger deps that only cater to certain use cases into optional plugins, although I suspect the core team would prefer to avoid additional config.
The real issue here is that npm
is just slow at this. npm install ava
creates hundreds of http requests that just get 3XX
responses. It can't even do much of it in parallel, because it needs to resolve which version of direct dependencies will be used, before it can start querying one level deep for transitive dependencies.
I don't see us dropping lots of dependencies. The only dependencies that would be easy to replace, are also ones that are not really going to cut down on download times.
Also, I really don't think comparing cleared cache download times is that valuable. I'm much more concerned with download times when we have mostly cache hits. (AVA is still pretty bad by that metric as well, but it's not as extreme).
Hello. I have been checking the list of packages, and found out that many of them already have a closed PR, specially from feross and substack authors.
I submit an updated list here with some packages edited in bold, the ones with a new PR and the ones that have an .npmignore
. I also wrote the state of the related PR for each one.
The reason and previous discussions on why the PRs were not accepted can be found in feross/is-buffer#12
.npmignore
.npmignore
files
entry in package.json
.npmignore
.npmignore
.npmignore
file.npmignore
.npmignore
file.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
files
entry in package.json
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
file.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
.npmignore
files
entry in package.json
https://github.com/siddharthkp/cost-of-modules is also a nice tool:
$ cost-of-modules --no-install --less
Calculating...
ββββββββββββββββββββββββββββββββββ¬βββββββββββββββ¬βββββββββ
β name β children β size β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β babel-preset-stage-2 β 57 β 23.66M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β babel-core β 35 β 15.96M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β babel-preset-es2015-node4 β 33 β 11.36M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β chokidar β 130 β 5.44M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β babel-runtime β 2 β 3.82M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β babel-plugin-espower β 9 β 2.33M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β babel-plugin-ava-throws-helper β 6 β 1.18M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β jest-snapshot β 10 β 0.87M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β bluebird β 0 β 0.58M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β meow β 25 β 0.30M β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β + 66 modules β β β
ββββββββββββββββββββββββββββββββββΌβββββββββββββββΌβββββββββ€
β 76 modules β 345 children β 44.53M β
ββββββββββββββββββββββββββββββββββ΄βββββββββββββββ΄βββββββββ
With npm 5.3, in a temp directory:
β― npm init --yes
β― npm i ava
β― npx cost-of-modules --no-install --less
npx: installed 16 in 2.28s
Calculating...
βββββββββββββ¬βββββββββββββββ¬βββββββββ
β name β children β size β
βββββββββββββΌβββββββββββββββΌβββββββββ€
β ava β 750 β 46.04M β
βββββββββββββΌβββββββββββββββΌβββββββββ€
β 1 modules β 413 children β 17.22M β
βββββββββββββ΄βββββββββββββββ΄βββββββββ
The final size matches what Finder reports. I think that's pretty good! Plus, installation times are a lot better with npm 5.
Whilst we can always improve this, I don't think there's much use in keeping this issue open.
Latest master (b79fdfd8b0e5632eae338b563af1c3be29fecbca), when installed with npm@3.5.2, is 68 MB. Most of that is Babel stuff.
We should look into ways we can reduce the size.
(Output from DaisyDisk)
Turns out every single Babel package includes a dependency on
babel-runtime
and for some reason it's not deduped by npm@3, not even withnpm dedupe
: