Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Just: A library of dependency-free JS utilities that do just do one thing (github.com/angus-c)
96 points by arash_milani on July 16, 2016 | hide | past | favorite | 74 comments


Javascript library/toolkit modularisation do not goes this way. Mout, async or lodash are using a proper scheme to require('just/thefuction/youneed') and it's fine (no rollup will ever be needed). Polluting npm with dozen of one-liner is not a good idea (never forget left-pad)

* https://github.com/caolan/async/blob/master/CHANGELOG.md

* http://moutjs.com/


> Polluting npm with dozen of one-liner is not a good idea (never forget left-pad)

The size or scope of left-pad wasn't the issue, the ability to unpublish modules which were depended on was [1]

http://blog.npmjs.org/post/141905368000/changes-to-npms-unpu...


In NPM registry, yes. But in Node.JS ecosystem, it was left-pad's scope combined with inability of the community to adopt seasoned sysadmins' tools, like custom repositories to build artifacts without ever needing to touch network (which is somewhat difficult to execute when you have dozens to hundreds of dependencies for a trivial project).


I don't think the number of dependencies per individual project is a critical factor when setting up an internal npm mirror for all your projects (e.g. with Nexus [1] where I work) or vendoring dependencies per project (e.g. `npm shrinkwrap --dev && shrinkpack` [2]) - you're either doing it or you aren't.

[1] http://books.sonatype.com/nexus-book/reference/npm.html

[2] https://github.com/JamieMason/shrinkpack


// Object.map: returns a new object with the predicate applied to each value

That is not what a predicate is.


Might it not be appropriate to explain what a predicate is, since you don't agree with her definition?


It's common knowledge and you can easily look it up. https://en.wiktionary.org/wiki/predicate

Copied here nevertheless:

> 2. (logic) A term of a statement, where the statement may be true or false depending on whether the thing referred to by the values of the statement's variables has the property signified by that (predicative) term.

> 3. (computing) An operator or function that returns either true or false.


Maybe it is common knowledge for you. I could have looked it up, but I don't like seeing non constructive criticism.


It is valid to simply point out mistakes like these. It only takes a few seconds of effort, a few mins to fix and move on from. Instead we want to make this simple statement an emotional battleground and berate OP for not doing the author's brainwork.


it may be valid but it assumes everyone reading the comment knows what a predicate is in this context.


I'd say it makes no such assumption - in fact it tells the reader that it's not valid. The reader may then choose to educate him or herself as necessary.


Highlighting a factually incorrect statement is not criticism. Criticism assumes a different point of view. Granted he could have put it as a GitHub issue, but how about we avoid anti-intellectualism.


Criticism assumes a different point of view.

It doesn't, really. Criticizing poor choice of terminology is still criticism.


It is entirely constructive.

I just prefer brevity more than you do. But you would've still downvoted me even if i'd provided a link, no?


The point of making a comment is not showing off your knowledge, it's being useful to the reader.

You comment was not useful (or at least not as useful as it could be).

Put in more effort next time - a comment is written once, but read many times.


I think being part of a discussion sometimes requires some basic knowledge of the basic. Otherwise, if you need every concept explained to you, well, it's not a discussion, but a lecture. After all, if I deem it common knowledge and you do not, how do I know where is the limit of your knowledge base?

IMHO, people in the technical industry should first try to find knowledge by themselves, and ask only when it is not easily accessible. If you keep asking questions which you can find answers by Googling, hmm, how do you even survive in this industry? That is, if you're not in management, of course.


It was very useful to me. It told me the author of this library doesn't know what a predicate is.


Same could be said of the author to put more effort into their writing pieces before they publish a piece that will be read many times...


It's a fine line between brevity and rudeness.


I agree. I believe by explaining what it is, the entire community benefits.


An explanation often helps and rarely hurts. Especially online.


That is not what constructive is.


> It's common knowledge

In mathematics sure, but not everyone has had the same level of exposure to mathematics in software.


Serious programmers should know the definition. Its used widely in APIs.


I dare you to out of the blue ask your boss the definition of a predicate, and then respond with this comment.


> 1. (grammar) The part of the sentence (or clause) which states something about the subject or the object of the sentence.

It's likely OP was using this definition, which in a programming context is effectively synonymous with "unary function".

Not trying to restart any discussion here, just wanted to clarify for any future visitors.


This fails to recognize that the smallness of npm modules is intimately related to the proliferation of dependencies. The idea behind the node module-design paradigm is that packages should be small and many, instead of large and few like (for example) in C++. That makes sense because you only use what you need, but it kind of falls apart because the "small" packages you import carry with them 50 other "small" packages. Also because you lose the shortcut for vetting your dependencies which is to vet the people who wrote them. That's a half-assed approach to vetting code you rely on, but the alternative seems to be to do nothing at all.

So these modules are small, but anything that uses them is going to contribute to the proliferation of dependencies just as much as ever.


Modules like this make your dependency tree wider, not deeper, though. Modules with lots of deps add dependencies exponentially.


Hmm?

    // extend
    Object.assign({}, { foo: 'bar' }, { baz: 'qui' });
   
    // pluck
    [{ a:1, b:1 }, { a:2, b:2 }].map( obj => obj["a"] )
   
    // filter obj
    Object.keys(obj).reduce( ( result, key) => { 
       const value = obj[key];

       if ( value < 6 ) {
           result[key] = value
       }

       return value;
    }, {})
    
    // map obj
    Object.keys(obj).reduce( ( result, key) => { 
       result[key] = obj[key] + 1;
       return value;
    }, {})

    // template
    const data = { a:1, b: { c: 1 }, d: 2 };
    `some ${data.a}, ${data.b.c}`;

    // unique
    [1,2,2,3,4,4,5].filter( ( value, index, self ) => self.indexOf( value ) === index )

    // last
    [1,2,3].slice(-1)[0]

    // union
    [1,2,3,4].concat( [6,7,8,9] ).filter( ( value, index, self ) => self.indexOf( value ) === index ).sort( ( a,b ) => a-b )


If you wrapped that "unique" implementation in some kind of reusable construct, it would be even easier to use, and it would be easy to replace with a more efficient implementation. Hmm.


That's true, but you also increase your technical debt and decrease readability by people not familiar with the library.


I would cheerfully argue that repeating non obvious code that could easily be wrapped in a documented function with an obvious name raises technical debt considerably more than causing someone to briefly wonder what a function called 'unique' that operates on an array does.


All of these are available in Lodash, both as one package with no dependencies and a plethora of individual micropackages with very small dependencies.


When I looked at pulling in a "micropackage" from Lodash it had so many dependencies that had dependencies (3-4 levels deep sometimes) that instead of being ~15-20 lines of JavaScript at most, it ended up being 300-400 lines, if I remember correctly.

Ended up writing my own mini-routine instead. If I ever need enough of Lodash to care I'll just import the whole thing, which is the only way to get lazy evaluation anyway.


Lodash v4 reduced the deps of its individual modularized method packages.

It also offers modules inside the primary package now, e.g. require('lodash/chunk').

There's babel and webpack plugins to make cherry-picking and bundle size optimizations a breeze too.

https://github.com/lodash/babel-plugin-lodash

https://github.com/lodash/lodash-webpack-plugin


I've been using Rollup for bundle size optimizations, and I believe it will work with the lodash internal packages.


Neither Rollup nor Webpack 2 will tree-shake Lodash properly. The best option at the moment is babel-plugin-lodash.


Crap. I've already banished Babel from my toolchain -- the Babel ES6 shim throws a warning in Firefox about modifying the prototype of an object, and from what I can tell that will kill or limit both V8 and SpiderMonkey optimizations from that point on.

Back to plan A: Don't use Lodash in client code unless I'm willing to use the whole thing (so that I can get the chaining optimizations, which cherry picking doesn't support anyway).


There's no hard requirement for babel-polyfill or babel-runtime.

Babel works great without shims in modern enviros (I don't use shims in my projects).


Here is the author's motivation: "It felt wrong installing half of npm even for basic utilities, so I made JUST, a family of dependency-free modules" [1]

1: https://twitter.com/angustweets/status/754375515159441408


Something i can relate to. It just feels wrong to do a npm install for something very basic and see half a linux installation happening in the console...


It does nothing to address the underlying issue of people relying on NPM packages where there is little-to-no developer maturity to do with stable APIs and ongoing support.

I'll never criticise anyone for releasing OSS but ultimately he just becomes the things that half of NPM relies on and the vicious cycle continues.


Also, is it possible to install a non-trivial npm package without deprecated warnings?



I applaud the concept, but also don't have too many qualms about installing lodash's single function packages, since they typically only have a couple of requirements and are battle tested.


Only one function as a module, Seriously?

There are 10 modules that you need to imports if you are using 10 functions. I think it's unnecesary


And it would be. The use case is when you need one function and want as small an import as possible.


JavaScript has always been uniquely tied to the web, where page load times matter and serving a bunch of unnecessary data to a user can have a significantly negative impact. I think there is a balance to be struck with how we architect our libraries. In fact, ES6 module imports already go a long way in addressing these issues. Take a look at http://rollupjs.org for how efficient module bundling can be done through the use of ES6


Apparently you missed the leftpad drama a couple of months ago.

(It was ridiculous then, and it is ridiculous now)


How did the JavaScript community come to this?


What do you mean?

Somebody wanted to write code in a particular way and extended the language with a couple of utilities for doing so, then decided to publish it for others to use.

I don't see the problem. Could you elaborate?


By being filled with many early to mid level developers that jump on every novel craze.


That's not constructive...

I agree. WTF? LoDash was here all along... What is this discussion about?


What's the purpose of having a module like just-template when ES6 already supports templated strings? The only difference I see based on the example is that instead of using a template string literal, you call a function with an additional data argument.


That you might want to allow user-defined templates and that the package is ES5-compatible are two I can think of.


Unlike template strings this module could be used cross-browser (via browserify/webpack etc).


I don't get it. Does array-last* has any sense? If someone needs to include a package for last() so the code is more bugproof and stable, I don't know what to expect in more complex algorithms..

This, like many stuff I see in the javascript world, is overegineering.

* https://github.com/angus-c/just/blob/master/packages/array-l...


Can't put the blame of one bad package on the whole community. If there is a bad package don't use it. I've seen lots of well engineered packages with zero dependencies.

E.g typescript. Entire compiler and language server. No dependencies.

Es6 is a decent library out of the box. I always only add a dependent if it's something not trivial.

A lot of the shitty packages came out before tree shaking was a thing.

There is an argument. Should you just have a large hash table of functions that you reference. Those in the bandwagon go for the one function packages.


Can't wait to put these on my microservice so people can concatenate strings more conveniently in the cloud /s


JUST MAKE A DATABASE-INDEXED GLOBAL PACKAGE SPACE WITH ON-DEMAND FETCHING BY DEFAULT AND PRE-FETCHING POSSIBLE FOR ALL NEW LANGUAGES ALREADY!


`map` and `filter` should take their functional argument first, then data second.


In a perfect world, map and filter would extend the Array prototype, which is how the language was designed to be extended.

That aside, to me, putting the data argument first would seem to make the code more readable.


map and filter are already builtins anyway, so it's kind of a moot point.

It sure is confusing why the author implemented these functions...


Cross-browser usage? Map and filter aren't in IE8, which is still in wider use than a lot of people would like to pretend.


Well, what browsers you support is obviously going to depend strongly on your particular site and use case. I work on a consumer-facing site for a national broadcaster which sets very aggressive browser support (oldest IE we support is IE11) which works fine for us.

Regardless, any sort of environment where you can do `import extend from 'just-extend';` is going to (have a way) support map and filter.


>> Regardless, any sort of environment where you can do `import extend from 'just-extend';` is going to (have a way) support map and filter.

That is not true for the now-fairly-common use case that browserify/webpack satisfy. I write code with ES6 module syntax and build with browserify (& babelify) to target the browser. But I still need to pull in modules like lodash.map/lodash.filter if I want to target IE8.

(I could use es5-shim but that makes for less portable code).


Just use Ramda, it's a utility library that "gets the argument order correct", and supports currying and other nice FP concepts.

http://ramdajs.com/

http://fr.umio.us/why-ramda/



It makes it look nicer in Coffeescript to have the function last, but yes, I agree.


Why?


Because then you can curry/partially apply functions independent of your data.

It's _not_ because it's convention everywhere else.

(I realize that only really makes sense if you know why it makes sense, so this video gives a pretty good explanation in ~30 minutes - https://www.youtube.com/watch?v=m3svKOdZijA)


Because that's the convention everywhere else.


Right, but that's not the convention in Node. Anonymous functions always go last.


Publishing a single function as a package... Isn't it the reason why npm modules all have so many fucking dependencies?




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

Search: