Hacker News new | comments | show | ask | jobs | submit login
Javascript utility libraries to know in 2018 (bitsrc.io)
160 points by saifazmi 3 months ago | hide | past | web | favorite | 82 comments



The list seems to be overly reliant on GitHub stars as the main metric for measuring if a library is worth considering or not.

I wrote a checklist with some questions that can help you find potential issues with third party packages:

- [ ] Is the package licensed in a way you can use?

- [ ] Is the package's latest published version free of known security vulnerabilities? (can check with https://snyk.io/vuln/npm:moment)

- [ ] Is the package tested? (there need to be at least some unit tests)

- [ ] Is the package lightweight? (can check with https://bundlephobia.com/, this should be considered alongside the size of the problem being solved)

- [ ] Is the package dependant on no other packages? (0 dependencies = less to worry about)

- [ ] Is the package maintained? (activity in the last year, don't forget to check branches other than master)

- [ ] Is the package popular and widely used? (depended on by lots of other projects, number of stars on GitHub)

- [ ] Is the package well structured and easy to understand? (could you contribute and make changes to it quickly? you may have to!)

Once you do decide to adopt something, it's a good pattern to only import it in one place (like an internal `helper` library) and to reference that in every part of the codebase where it's needed. This is in case you decide to replace it in the future, so you only have to change one place.


That's a great checklist - I'll add to that that it's always a good idea to give a cursory glance at the source code.

For the "is it maintained" part, I like to look at issues and how they are resolved


It is also useful to see how many point releases they do or if their idea of maintenance is rewriting the whole thing every time somethings comes up.


> don't forget to check branches other than master

Curious what the thinking is on this. It's true that development could be happening on a branch other than master, but if that's the case I would expect that to be set as the main branch. Maybe master is used only for releases, but that's still a good way to check activity.


My thinking is that commonly activity on master halts for months/years because a v.NEXT is being worked on, so it's worth checking if that's the case and whether it's worth waiting for the new version or adopting the alpha/beta.


Fair point. That does happen sometimes :)


I love moment, but it's age is starting to show.

The way it's designed makes code splitting and tree shaking extremely difficult, and the difficulty removing large chunks of the library (i'm looking at you locales) is annoying at best. It's also a pretty heavy library on it's own anyway, as it needs to implement quite a lot of code for legacy browsers that isn't really needed if you are only targeting evergreen browsers (and possibly IE 10-11).

As an alternative, I always recommend "date-fns"[0]. it got a mention in the article, but not nearly enough of one!

https://github.com/date-fns/date-fns


>>> I love moment, but it's age is starting to show.

according to https://github.com/moment/moment/blob/develop/CHANGELOG.md#0... the 0.3.0 release was from 2011.

it's barely 7 years ago. And I'm non counting the fact that the current version is 2.22.2 (so there are at least 2 major ones).

How... how can you tell it's aging?!


Hopefully I can explain your downvotes a bit. The JavaScript ecosystem is in an entirely different place now. ES6 has made it feasible to write cleaner, more concise code, and Webpack has allowed library consumers to "naively" import a whole library but the algorithm known as 'tree-shaking' will remove any unused code, which can be especially valuable when a library has a few purposes which are somewhat orthogonal, and each requires has its own large codebase, aka Moment.


Because not all things "age" at the same rate. (1 month old milk is old, a 1 month old can of tomato paste is far from old)

Lodash (#1 in this article) is just as old or older than Moment, however I wouldn't call lodash "aging" simply because it has adapted to the new paradigms in the javascript ecosystem and works very VERY well with them (to the point that I'd argue lodash is a pretty good example of how to work with these tools).

Moment still does a great job at what it does, and it's in no way getting "worse" over time (quite the opposite!), however because of some choices made during it's development, it can't easily take advantage of newer developments in the javascript ecosystem.

JS has changed significantly, and is still changing. I'd argue that JS became a "real" programming language over the last 10 years, and because of that a lot of things created in that time aged much quicker than they should have.

Like I (briefly) pointed out in my comment, things like tree shaking, module bundling, code splitting, minification, and the tooling and ecosystem around them have changed drastically in the last 5 years. Now moment will still work great with those things, but it doesn't take advantage of them. And that means that alternatives end up getting a leg up because they do take advantage of them.

Something like `date-fns` is designed with tree-shaking in mind, so if I only want to use the part of it that "humanizes" a time range, i'll only get that code. If I want to provide multiple locales for multiple users, but only have each user download their own locale at runtime, I can do that easily. Not to mention that browser support has changed in the last few years, so most people no longer need to support IE 7, 8, 9, etc... And that means that the code that moment has built up to support those browsers isn't needed on newer ones, but again it's difficult or impossible to build it without that to save size.

To continue the analogy I used at the start of my comment, I'd say moment is week old milk. It's not bad yet, but I wouldn't buy it from the store like that in most cases. Moment is great, I do use it in 2 projects at work because it was the best tool for the job for a long time, and it still works fantastically. However if I'm starting a new project now, i'm most likely going to reach for something else.

Not because it's "newer" or because it's the hot thing right now, but because in all honesty the API of a date management library isn't all that complicated, and switching isn't a large cost. And when those other libraries can provide benefits that moment can't, i don't have much of a reason to stay with these "older" libraries.


I stumbled across Luxon, also under the Moment umbrella, not too long ago and I think it's pretty slick. It feels a lot more natural to use.


I saw that for the first time today elsewhere in this thread, and I really like it!


Please review and contribute your views on the TC39 Temporal proposal. There’s a polyfill to play with now...

https://github.com/tc39/proposal-temporal


This is fantastic, however it doesn't really completely replace the reasons for using something like date-fns.

Stuff like a "time-range" (both a "computer" value, and a "humanized" one like "10 minutes ago"), and other nice to haves.

There's no reason this can't be a good base going forward though! And for what it does cover, I really like the API.


There is an Intl.RelativeTimeFormat proposal as well: https://github.com/tc39/proposal-intl-relative-time/blob/mas...


This looks like a step in the right direction. I can't seem to find a polyfill though -- do you have a link to that?


The one open PR is a self described "first go" at a polyfill.

https://github.com/tc39/proposal-temporal/pull/57


It is also sneakily mutable at times. Some methods will mutate the original object - the cause of a few bugs I've investigated recently


Why do [time] libraries all seem to make this mistake? I think I fixed the same concurrency bug due to misuse of Java’s date parser at four different companies (one of them I didn’t even work for).

Use one object to hold configuration and another to hold state.


I usually copy/paste the functions I need :P


I get it that the author works for Bit, but it's really not necessary to throw in their own product both at the beginning and as an "honorable mention" at the end. It's much more genuine to just say "hey, we make this and want you to know about it" and carry on.


Agreed, this seems to be written as marketing first, education second. Good content marketing puts the priority on learning first. If the Bit folks are reading this and interested in improving, I suggest reading Kathy Sierra's book and watching her talks.

https://www.amazon.com/Badass-Making-Awesome-Kathy-Sierra/dp...

https://www.youtube.com/watch?v=r4dNaflEgP4


Hacker News should have stronger antibodies to content marketing.

This one is even easier to spot because it recommends lodash in 2018


The only issue I have with lodash is that a typical npm install for any significant project that I've worked on will pull in approximately 87 different copies of it, up and down the dependency tree, of nearly every release that is still accessible.

A standard library that wasn't so anemic would be a grand thing.


Do you think there's a better alternative or are you addressing that lodash is pretty old now?


Lodash has two values, a bunch of utility functions and it works cross browser. The most common utility functions are now standard issue in es6+. And a transpilation build process is a superior way of dealing with cross browser incompatibilities. Babel + browserlist + caniuse all work seamlessly to ensure you only have the polyfills and browser support you need, vs the one-size-fits-all approach of lodash.

There's probably a handful of functions in lodash that are still useful but why take on the security risk and maintenance of another package dependency if you can just copy a couple ten-liners into your own utils folder? It's not like the world is going to come up with a more performant debounce anytime soon.

I guess lodash also relies on jquery which is in the same boat. es6+ has stolen a lot of its thunder and target-aware transpilation is a better approach to cross browser support


I have more nuanced takes on lodash too but I'm putting them in another reply to separate them from the big picture stuff I already mentioned.

Lodash also differs from the standard lib's implementation, notably it's too permissive. Take this example:

const uhoh = null

_.forEach(uhoh, () => {})

uhoh.forEach(() => {})

lodash's forEach has no problem running on a falsey value (it gives you back the value) whereas standard lib leads you to a TypeError.

Two thoughts here. The standard lib forces the programmer to think more about types, which is a good thing. Second is that lodash's more loosey goosey approach acts as vendor lock-in. In two years, when there's 60 lines and 3 files of separation btwn uhoh's assignment and the _.forEach invocation, you won't know whether it's expected to be null or not. So you won't know if you should replace the code with

uhoh.forEach(...)

or

(uhoh || []).forEach(...)


The standard library. There's a few things missing in ES8, but not a huge amount.

Also sugar.js is dead. I maintain http://agavejs.org, an ES8 based replacement, which is stil going.


The standard library has replaced much of lodash's array utilities but seeing as you can import lodash functions into your project piecemeal it's still useful for the odd utility function here and there.


Ramda.


Agreed. For the rest of you, some explanation:

Ramada.js is geared around making partial function application easy to do. In general, the utitility functions accept any helper callbacks first, and input data last, and automatically generate a partially applied function if you skip any trailing arguments.

For those of you coming from the Java / C++ / Simula 67 culture, this level of brevity may take some getting used to :-)

Ramda does a really good job of helping you “Stop Writing Classes”, composing functions instead.


Damned auto-corrupt on my iPad :-(

(Ramada)


Worth mentioning that moment was recently rewritten from scratch by one of the maintainers, and thus luxon[0] was born.

[0] https://moment.github.io/luxon/


That's not very accurate. One of the maintainers (but not the creator) decided to create Luxon from scratch, but it's still not as mature as moment and lacks some features in comparison.

Source: https://moment.github.io/luxon/docs/manual/why.html


According to its documentation, its been created by one of the maintainers, not the author.

Read "a disclaimer" here: https://moment.github.io/luxon/docs/manual/why.html


Thanks, fixed it.


Is it faster?


I feel like this speaks volumes about JavaScript. The need to have all these libraries to do relatively ordinary tasks which ought to be easy enough with a good standard library.


No matter what you include, someone always comes and says this broad useless generalization. What of this looks like it should be standard? https://cdn-images-1.medium.com/max/1600/1*opTXAh1ohEAVpBM4W...


If you take your line of reasoning to it's logical conclusion, you could argue that JS should not have a standard library. Yes there will always be critics but it doesn't mean that some options aren't better than others.

The small JS and node standard libraries and extensive NPM module universe are both a strength and a weakness. It means developers can do things in JS that they can't in other languages and vice versa.

I guess its a matter of preference and right tool for the job. When I started with JS, I was excited by the number of modules and ease of use. I feel like I've grown tired of that and would rather have a decent standard library so I can focus on coding rather than finding the right module and managing my package.json/yarn/npn/webpack.


You don't need to take this to non-logical extreme. Node standard library is in no way limited, I guess we just see the world differently.

I'd never prefer one 'true' way (aka opinionated bs) to organic ecosystem competition.


Why do I have to know like 30 libraries that all do the same thing? I'm just gonna stick with lodash until for some reason I can't anymore.


is it just me or is this basically, "this project has a lot of stars, so, you should know it!". Seems like vanity metrics have absolutely ruined the internet. If these are useful to you, great, but just because something has a lot of stars/likes/thumbs upseses doesn't mean they're required learning/knowing.


Social proof is very important. But it's easily gamed. It's a shame that projects needs x stars and y collaborators for anyone to consider using it. We'll eventually end up with star inflation, and "get 100 stars for $10" services.


>"this project has a lot of stars, so, you should know it!"

This is how the industry works these day, and beginners coming from bootcamps are told to pick a framework that way.

The more stars , the better.


No left-pad or is-number? Disappointed.


That was the first library, Underscore or Lodash.


lodash and moment are poor choices to showcase. lodash is mostly moot with ES6 and beyond. date-fns is a cleaner version of moment.


I disagree about lodash being "moot".

There are tons of things that lodash still provides that can't be easily replicated.

Just in the last month or so I've used throttle, debounce, uniqBy, memoize, get, and i'm sure more.

Sure, things like map, filter, find, reduce, etc... are made obsolete, and `Object.values` is a huge win to iterating objects or arrays with the same code, but lodash is far from useless.

And the way the library is structured, pulling in just one or 2 functions is fairly lightweight if you are using a bundler like webpack/rollup.


> Sure, things like map, filter, find, reduce, etc... are made obsolete

Not really. `_.map` for example works on Objects, and property access is very nice.

`_.map(object, 'myProperty.mySubProperty')`

vs

`Object.values(object).map(i => i.myProperty ? i.myProperty.mySubProperty : undefined)`


Yeah the iteratee shorthand stuff in lodash is massively convenient, however I'm starting to shy away from it in favor of more "obvious" approaches like your second example.

Although that being said, for deep property access like you have, i still reach for lodash's `get`, or more recently i'm beginning to use the new stage-1 proposal for "optional chaining" (also known as null-conditional operator in C#) [0].

That turns your second example into:

    Object.values(object).map(i => i.myProperty?.mySubProperty)
And honestly I might even reach for destructuring depending on the use case:

    Object.values(object).map(({myProperty}) => myProperty?.mySubProperty)
As nice as lodash's syntax is, it can be confusing for those who don't know it, and even I need to step back sometimes when I see it used heavily somewhere and almost replay what is happening in my head.

[0] https://github.com/tc39/proposal-optional-chaining


Object.values doesn't work in IE11, that can bite you really hard with “enterprise“ customers.


Luckily there are fairly simple polyfills that can be used for that (including using babel's preset-env system to configure it based on browser support!)


There are still heaps of tiny but useful utility functions in Lodash (`fromPairs`, `takeWhile`, ...). Sure those are trivial to code yourself, but with recent bundlers' tree-shaking abilities, it's just better practice to import a thoroughly tested version instead.


What about lodash's lazy evaluation/chaining/shortcut fusion? I don't think the ES6 standard library offers any alternative to it?


Not that this is mindblowing or anything, but I found this useful: https://github.com/coatue-oss/react2angular

After webpack-ifying our old-ass angularjs app, we're slowly replacing features with React components :)


This is so totally useful to me. I have a meeting in an hour with my team about how we're going to approach this


Somebody using 'sugar'? It is not clear to me when or how this library is used...


Me too. Maybe it's cause I've only been developing for a year, but I'm not sure what a 'native object' is and there don't seem to be any good definitions


I just came to comment that Math.JS is a real gem. Kudos to the authors. Incredibly flexible to add deep functionality to. I used it to build a custom spreadsheet application and wow'ed the heck out of my client.


JavaScript general utility: lodash and jQuery. For dates and currency: Moment.js and the numeral.js but I don't consider then "general utility" so much as "not infrequently needed."


You probably don't need jQuery unless you're supporting old browsers. Ajax has been 'replaced' by fetch, DOM updates are straightforward with querySelector, class manipulation is easy using classList, and animation can be done in CSS. jQuery is still useful for some UI elements like date pickers or orderable lists, but there are significant accessibility issues around most plugins.

If you're using something to transpile (eg Babel) your code then you don't really need anything like lodash. es6 has most of the array and object functions you typically want, like map, reduce, filter, Array.from(), etc.

Date formating with Moment.js is really nice, but it's big (30kb) so if you're only using a small part of the functionality it might be better to use Luxon (https://moment.github.io/luxon/index.html) as that should be tree-shakable using Webpack.


DOM methods are less convenient compared to jQuery. Also I think it makes sense to support browsers at least 5-7 years back so it is too early to deprecate jQuery.

But I don't like that it is huge and not modular. And that it is not strict in argument checking and accepts anything without throwing any errors.


Ramda is a nice alternative to lodash and underscore. If you like the Haskell style of creating tiny helper functions by partially applying functions, Ramda is great.


Is it faster?


While I admire what Ramda, Fantasy Land and such try to achieve, current Javascript runtimes just don't support that. Maybe javascript should be kept as C of Web and compile Reason or Purescript to Javascript.


tail call optimization is supposed in some runtime, but even without, the vast majority of fantasy land-style lib usage doesn't require it or any other special optimizations, really.

Otherwise you should stop using lodash too.


Ramda works pretty well for me, even (especially?) on IE11.


What is it that they don't support?


i strongly suggest JS user to learn and use mout. A lightweight & simple alternative to lodash/underscore (and a spiritual successor of mootools)


> A lightweight & simple alternative to lodash/underscore

Lodash full is 24kb. Mout is 450kb...

Not light weight at all. The advantage is that its modular so your bundles would only include the libraries you require. Oh wait lodash does that. So Lodash is a more lightweight alternative to mout...


a spiritual successor of mootools

After "smooshgate" I don't think that's a plus point.


Is it faster?


I think it is better to stop using this "~~ in 2018" style of writing. It is not like everything in CS gets obsolete every year. For example, Berkeley sockets are still used today as well as many other libraries. So you don't have to switch to some other libraries only because it was written several years ago and you don't have to use arrow functions instead of `function` keyword only because it is 2018.


Nobody is implying anything before 2018 is obsolete, but that these libraries that the author is showing are still alive and well and actively maintained/improved.

Sure, a js library from 2008 will still work great now, however it might not work well with new module bundlers, or it might do something that is consitered "code smell" in newer JS engines which could impact performance.

Newer doesn't mean "better", but it's still useful information to have.


what are the arguments against moment/lodash being included in the "javascript stdlib" or the language itself? im sure there are good reasons, curious what they are.


I kinda have the opposite question: I've honestly never understood lodash's popularity. Even before ES6, so much of it seemed to be just slightly different syntax for things that already exist.

I mean, clearly I'm missing something, lots of devs seem to love it and that can't be for no reason; but every time I've encountered it in code I'm maintaining it's been trivially replaceable with vanilla methods, which makes me wonder what the point of including it in the project in the first place was.


Functions like unionBy, intersectionBy, differenceBy, groupBy, mergeWith, mapValues, flatten already exist in JavaScript? Not even listing all the basic functions not available before ES5/ES6 (find, filter, some, every, Object.keys, Object.values…).

This lib is popular because nobody wants to rewrite these functions manually.


You might try replacing Lodash with Ramda. You have to get your head around “partial function application” (if you haven’t already), at which point all the bits for processing arrays and associative arrays via FP techniques really starts to gel.

E.g. - https://ramdajs.com/docs/#find

    Var find_default = R.find( R.prop( ‘default’ ) )
    Var list = [
        { name: ‘Abe’, default: false }, 
        { name: ‘Bob’, default: true },
        { name: ‘Chuck’ }
    ]
    Find_default( list )
    //. -> { name: ‘Bob’, default: true }
(Apologies for gratuitous caps and periods my iPad is forcing in)


i'd say that lodash really did give a lot of great stuff pre es6. old habits die hard.


I find myself frequently using it for debounce, throttle, isEmpty, cloneDeep and memoize.


For moment.js, it's already standard, we have very cool methods available from a date object (toLocaleString, toLocalDateString, ....) + the Intl global object




Applications are open for YC Winter 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: