netlify / cli

Netlify Command Line Interface
http://cli.netlify.com
MIT License
1.58k stars 358 forks source link

chore: netlify-cli package install-size analysis #3302

Closed iChenLei closed 3 years ago

iChenLei commented 3 years ago

TL;DR

Too many big-size binary npm package in dependencies list, so netlify-cli's install size is very huge.

List all netlify-cli(v6.8.6) deps

package install-size semver
@netlify/build install size ^18.7.4
@netlify/config install size ^15.5.1
@netlify/framework-info install size ^5.9.1
@netlify/local-functions-proxy install size ^1.1.1
@netlify/plugin-edge-handlers install size ^1.11.22
@netlify/plugins-list install size ^3.6.0
@netlify/routing-local-proxy install size ^0.31.0
@netlify/zip-it-and-ship-it install size 4.20.0
@oclif/command install size ^1.6.1
@oclif/config install size ^1.15.1
@oclif/errors install size ^1.3.4
@oclif/parser install size ^3.8.4
@oclif/plugin-help install size ^3.0.0
@oclif/plugin-not-found install size ^1.1.4
@oclif/plugin-plugins install size ^1.9.3
@octokit/rest install size ^18.0.0
@sindresorhus/slugify install size ^1.1.0
@ungap/from-entries install size ^0.2.1
ansi-styles install size ^5.0.0
ascii-table install size 0.0.9
backoff install size ^2.5.0
better-opn install size ^2.1.1
body-parser install size ^1.19.0
boxen install size ^5.0.0
chalk install size ^4.0.0
chokidar install size ^3.0.2
ci-info install size ^3.0.0
clean-deep install size ^3.0.2
cli-ux install size ^5.5.1
concordance install size ^5.0.0
configstore install size ^5.0.0
content-type install size ^1.0.4
cookie install size ^0.4.0
copy-template-dir install size ^1.4.0
debug install size ^4.1.1
decache install size ^4.6.0
del install size ^6.0.0
dot-prop install size ^6.0.0
dotenv install size ^10.0.0
env-paths install size ^2.2.0
envinfo install size ^7.3.1
execa install size ^5.0.0
express install size ^4.17.1
express-logging install size ^1.1.1
filter-obj install size ^2.0.1
find-up install size ^5.0.0
flush-write-stream install size ^2.0.0
folder-walker install size ^3.2.0
from2-array install size ^0.0.4
fuzzy install size ^0.1.3
get-port install size ^5.1.0
gh-release-fetch install size ^2.0.0
git-repo-info install size ^2.1.0
gitconfiglocal install size ^2.1.0
hasbin install size ^1.2.3
hasha install size ^5.2.2
http-proxy install size ^1.18.0
http-proxy-middleware install size ^1.0.0
https-proxy-agent install size ^5.0.0
inquirer install size ^6.5.1
inquirer-autocomplete-prompt install size ^1.0.1
is-docker install size ^2.0.0
is-plain-obj install size ^3.0.0
isexe install size ^2.0.0
jwt-decode install size ^3.0.0
lambda-local install size ^2.0.0
listr install size ^0.14.3
locate-path install size ^6.0.0
lodash install size ^4.17.20
log-symbols install size ^4.0.0
make-dir install size ^3.0.0
memoize-one install size ^5.2.1
minimist install size ^1.2.5
multiparty install size ^4.2.1
netlify install size ^8.0.0
netlify-headers-parser install size ^4.0.1
netlify-redirect-parser install size ^11.0.2
netlify-redirector install size ^0.2.1
node-fetch install size ^2.6.0
node-version-alias install size ^1.0.1
oclif-plugin-completion install size ^0.6.0
omit.js install size ^2.0.2
open install size ^7.0.0
ora install size ^5.0.0
p-event install size ^4.2.0
p-filter install size ^2.1.0
p-map install size ^4.0.0
p-wait-for install size ^3.0.0
parallel-transform install size ^1.2.0
parse-github-url install size ^1.0.2
parse-gitignore install size ^1.0.1
path-exists install size ^4.0.0
path-key install size ^3.1.1
path-type install size ^4.0.0
prettyjson install size ^1.2.1
pump install size ^3.0.0
raw-body install size ^2.4.1
resolve install size ^1.12.0
semver install size ^7.3.4
source-map-support install size ^0.5.19
static-server install size ^2.2.1
strip-ansi-control-characters install size ^2.0.0
tempy install size ^1.0.0
through2-filter install size ^3.0.0
through2-map install size ^3.0.0
to-readable-stream install size ^2.1.0
toml install size ^3.0.0
update-notifier install size ^5.0.0
uuid install size ^8.0.0
wait-port install size ^0.2.2
winston install size ^3.2.1
write-file-atomic install size ^3.0.0
As Business Competitors, vercel's cli install size is: package install-size
vercel install size

vercel cli is only 81mb, and netlify cli is 330mb+. .....

What a crazy big install-size ! That's why netlify user complained about this issue. https://github.com/netlify/cli/issues/494 [Huge increase in install size]. The core issue is netlify-cli rely on some binary npm package which size is too big. For example, @netlify/routing-local-proxy -> install size . This binary file size is more than ~50mb. Replace lodash with lodash/fp or lodash.xx is not useful for reduce package install-size, beacuse it's only ~1.3mb.

Alternative solution

Rewriten netlify-cli in golang, I think these binary netlify private package is also writen in golang, and then pack it as npm package, distribute it via npmjs.org. So netlify user only need install a single platform-specific golang binary file. I know this is impossiable, rewriten is a huge work and stop the cli iteration.

So how about developer experience ? sorry, nobody cares.

cc @erezrokah @ehmicky

ehmicky commented 3 years ago

Hi @iChenLei,

Thanks for reporting this issue.

Netlify CLI has lots of features and therefore lots of dependencies. I do agree though that we should strive for a smaller package size. I also agree that 330MB is a lot.

However, the developer experience is mostly only impacted by how long it takes to run npm install netlify-cli, which is rather minor IMHO.

Also, this is not an easy fix. As your correctly pointed out with the long table, the total installation size does not come so much from specific dependencies than from the number of dependencies we use. However, most of those dependencies are providing Netlify CLI with essential features.

One potential action item i could see would be to make @netlify/plugin-edge-handlers optional, which is something we've been discussing.

Happy to hear what @erezrokah also thinks about this. :thinking:

iChenLei commented 3 years ago

Thanks for reply, @netlify/plugin-edge-handlers | @netlify/routing-local-proxy | @netlify/zip-it-and-ship-it | @netlify/build , I'm curious why these package install-size is so huge. It looks like same with esbuild(writen in golang, and compile different platform-specific binary artifacts ?).

iChenLei commented 3 years ago

Anyway, I'm just making a fuss . Skip it , and continue your great work for netlify-cli. Thanks

xmedeko commented 3 years ago

I just need to deploy a small static site (a few kB). If would be nice to have some lite version of netlify-cli for netlify API calls like init, deploy, etc. (i.e. without dev server and others).

jtojnar commented 2 years ago

Switching to https://gitlab.com/lepovirta/netlify-deployer made the deploys by CI significantly faster for me.

XhmikosR commented 2 years ago

@ehmicky Like I mentioned in #494, this is NOT only an issue of package size.

It's a fundamental security issue: you make all of the people who consume netlify-cli trust 1300+ packages and hundreds of different developers!

The supply chain attacks are real, and the only solution is to reduce the packages you depend on. If you do that, then size and install time will also improve.

Also, the disk churn is serious with each netlify-cli release:

C:\Users\xmr\Desktop>node -v && npm -v
v16.13.1
8.1.2

C:\Users\xmr\Desktop>npm i -g netlify-cli
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated rollup-plugin-inject@3.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated flatten@1.0.3: flatten is deprecated in favor of utility frameworks such as lodash.
npm WARN deprecated node-pre-gyp@0.13.0: Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future

added 1374 packages, and audited 1375 packages in 47s

108 packages are looking for funding
  run `npm fund` for details

16 vulnerabilities (9 moderate, 7 high)

The above is with a clean npm cache on my Windows 10 VM, which admittedly might be a little on the slow side, but you get my point.

Size is one important factor. Disk churn another. Install time is also important. Security is the most important, though.

EDIT: heck, packagephobia has trouble showing results anymore for netlify-cli...

erezrokah commented 2 years ago

Thanks for the additional context @XhmikosR.

I agree the security aspect is more important than the package size.

We've recently dropped oclif from the codebase which helped and are also in the process of converting the codebase to ES Modules so we can upgrade our dependencies to latest versions.

As for the npm audit results - unfortunately they are not very helpful as they contain too much noise. It's hard to know which of the reported vulnerabilities are actually exploitable in the context of the CLI. There's more about that here and here.

We use a shrinkwrap file, which means once we publish the CLI you'd always get the same dependencies when you install it using npm (with yarn you should use your own lock file). That pins the dependencies users get when installing the CLI, so they don't implicitly get minor/patch updates due to semver ranges.

We also highly encourage submitting any security issue you find by following our policy.

XhmikosR commented 2 years ago

I've submitted a few PRs the last couple weeks reducing the deps etc.

I've pinpointed the root cause for the biggest size increase in netlify-cli. It comes from multiple typescript versions. See https://github.com/netlify/zip-it-and-ship-it/pull/951 for more info.

This affects quite a few packages that depend on @netlify/zip-it-and-ship-it.

A few wins so far:



So, with the above zip-it-and-ship-it change I get these results for netlify-cli:

Before: 240 MB (251.943.583 bytes)
After:  188 MB (197.329.508 bytes)
1351 -> 1349 packages

I'm sure we can get this even more down. I have a few more suggestions for later.