Writing JS libraries less than 1TB size

A small guide to create extra small libraries

No longer funny, but still the current picture

That post is inspired by idea of nano-libraries created by Andrey Sitnik (e.g. nanoid, nanoevents and nanodelay)

Introduction

Last time I am really crazy about libraries sizes in NPM. Do you think it’s OK? Let me take off your rose colored glasses.

Just look at the stats of the most popular package that just creates deep clone of objects. You can find it here.

And its size is here. It is really huge for package with only one function. That’s why I made nanoclone that does the same thing (excepting cloning circular objects, I’ll complete it later). Look at the nanoclone size:

It’s 51 times smaller and works with no problems.

And I want to share my experience in creating extra small libraries and tell you how to join our nano-hype 😎

Minimize, control or don’t use at all external dependencies

If you want to create nano-library, you should use external dependencies only in 2 cases:

  • You can’t deal without specific packages like path-to-regexp or anything else that works correct, is good tested and small-sized.
  • It’s another nano-library that won’t greatly increase your library size.

Another helpers like clone/deepmerge/etc (btw my friend Nikolay also made nanomerge, enjoy it) in case you did not find lightweight analogues should be written by you.

Somebody will say “utils.js are evil” but this proposition does not apply to nano-libraries

No builders and transpilers

Wait, what??? Yes, if you want to have really tiny library, you should not use webpack, rollup, babel and another tools that modify your code. Because the most part of your bundle size will be filled with specific bundler functions, babel polyfills and other trash.

Use rollup only if you have external dependencies and want let your library to be included as <script> from CDN. But if you have not dependencies, you can store all code in one file and you don’t need to use rollup more.

So, what about uglifying? Uglify won’t give you a great impact for extra small libraries. When I wrote nanoclone, rollup with only uglify plugin even increased the file size.

File sizes comparison. Uglified one has extra 9B
Note by Jacob Groß

Using ES6+ features

The answer is NO. To save maximum browser compability and not to use transpilers that’ll increase library size you should write ES5 only code.

I know that ES6 features are awesome but syntax sugar like spread operator or async/await is not supported by IE. Using transpilers is so expensive.

It also applies imports/exports usage. Use require instead of ES6-modules. It will also let people use your library with Node.js that doesn’t support imports (only in v9.0+ with — experimental-modules flag but how many people use that? Node v4 LTS will be expired only in August of 2018).

Use special tools to control your size

I use size-limit to control my libraries size. It’s a small utility that checks your file size with all dependencies and gzip and throws errors when you are outside the limit you’ve set. It also has — why flag to display size of your library parts

Size-limit example

Sometimes I use bundlephobia to check package sizes before install them.

You can see bundle size and download time for other versions

If you are on VSCode, I also recommend import cost plugin. It displays size of imported code

import-cost demo

Conclusion

So, the rules to make extra small libraries:

  • No external dependencies (excepting very important packages or another nano-libraries)
  • No bundlers and transpilers used (but you may use rollup to let your library to be included as <script>)
  • No ES6 features used (imports/exports are a part of ES6 too!)

Hope that post was useful and interesting for you :)

Special thanks to Andrey Sitnik for the idea and motivation.

Post scriptum

I started a challenge — write my own lodash where no one method is over 1KB size. If you are interested: