getify / FPO

FP library for JavaScript. Supports named-argument style methods.
MIT License
448 stars 25 forks source link

Support ES6 exports for tree shaking #1

Open neeharv opened 7 years ago

neeharv commented 7 years ago

This looks great! I was wondering about how one could either use only the functions needed via tree shaking, or will the build process allow a custom build to be generated with a few functions?

getify commented 7 years ago

fpo.js currently is 17.9k, but gzips down to 3.8K and that's without any minification yet (since Uglify still isn't finished with its ES6 support). I expect it'll be under 3k with minification+gzip.

As such, its size seems pretty small already and I'm not sure much will be gained by complicating the process (requiring extra build steps, etc) to eek out a few less bytes.

That said, I'm not strongly opposed to the notion of allowing some customization/optimization. I just don't want to force any user to have to transpile/build the lib out of the box if they want to just grab a file and go.

So at a minimum, I think the default fpo.js will stay as UMD, built with all functions. But a build tool or npm-publish process certainly could in theory transpile to an ES6 modules or subset-of-methods build. I would accept design ideas on the best way to approach this while leaving the core build unaffected.

Out of curiosity, which subset of methods do you anticipate wanting? I had already considered offering a supplemental build which removes all the FPO.std.* methods, but again, that won't save really that much, maybe 0.8K-gzipped at most.

neeharv commented 7 years ago

Not a specific subset per se, but only pull in what is required. I think there is a difference between transpilation and bundling wrt what we enforce on end users, and we can achieve the best of both worlds by doing the following -

  1. Each function resides in its own module
  2. We use rollup to bundle them all up into one and keep the current UMD semantics of the final final
  3. We also upload an /es/ folder that has the an index.js which re-exports all the modules
  4. In package.json we set the jsnext:main key to point to this es folder
  5. This would allow newer packagers like webpack / rollup to do tree shaking from this module, and there is no need for the client to transpile it since the contest of each module are transpiled anyway
getify commented 7 years ago

I know this is the "standard" way that projects seem to approach it. But I really strongly dislike the management of a hundred separate files. The other reason I am not sold on moving to ES6 modules as the authoring format is that the situation is still in flux in Node (and will be for at least a year, they say). For me, ES6 modules is a target, not the source.

I would vastly prefer to have the build process build an "ES6 modules tree" from the source as it stands. I can see that as basically a customized parsing tool that either:

The former is harder, but more canonical. The latter is pretty straightforward, and I think might already be possible with 5-to-6, or at worst a customization of it.

justsml commented 5 years ago

The esm drama and turbulence is finally calm enough to transition most projects. The biggest hurdle I had with my Functional Promises library was finding a relatively configurable bundling tool & workflow, plus some extra fields needed in package.json to help override default import/require behavior.

In the past few months I switched from Webpack to Rollup because (at the time) it was hard to configure both babel and a minifier which supports anything >= ES6.

Another benefit of an ES6 bundle is the size. Mine came down from 7Kb to ~2.5Kb gzipped, partly by eliminating some superfluous babel generated code (for well-supported ES6 features.)

Check out my Rollup config for producing 3 targeted bundles: UMD, CJS and ESM: https://github.com/functional-promises/functional-promises/blob/dbff6aef306ce9c14d8d6dd73f8d7d119406583b/rollup.config.js#L26-L141

Let me know if you want me to help on this one Kyle. 🚀