calmm-js / partial.lenses

Partial lenses is a comprehensive, high-performance optics library for JavaScript
MIT License
917 stars 36 forks source link

Rollup support #66

Closed polytypic closed 7 years ago

polytypic commented 7 years ago

Being able to take advantage of the superior "tree shaking" of Rollup would be nice. Here is, BTW, a sample boilerplate for TypeScript+React with Rollup.

polytypic commented 7 years ago

Build via Rollup has now been implemented.

It does help to make the build a bit smaller, but it doesn't really seem to help to eliminate any more dead code. The problem is that modules in JS can have side-effects and any exports whose evaluation might perform a side-effect cannot be trivially eliminated. A definition like export const foo = wrap(bar) can't be just trivially eliminated, because wrap might perform a side-effect. To eliminate such code requires a proper optimizing compiler to analyze for side-effects and Rollup can't do that yet.

polytypic commented 7 years ago

Addition: Partial Lenses now uses /*#__PURE__*/ annotations supported by UglifyJS. This means that with the combination of using Rollup and UglifyJS, you will only get what you use from Partial Lenses. IOW, dead-code elimination is effective with that combination.

kzc commented 7 years ago

Impressive! I never envisioned the uglify pure annotation would be used for anything but down-levelled class IIFEs from within ES5 transpilers like babel and typescript.

kzc commented 7 years ago

The end users of this library may be able to get better uglify results for their rollup bundled applications with the following uglify options:

uglifyjs -c passes=3,toplevel
polytypic commented 7 years ago

@kzc Thanks! Adding passes as

    process.env.NODE_ENV === "production" && uglify({
      compress: {
        passes: 3
      }
    })

in rollup.config.js to the rollup-plugin-uglify plugin, above uglify, seemed to reduce bundle size a bit in a test project. I didn't analyze where that reduction came from. Some of it might also be due to Ramda with pure annotations.

kzc commented 7 years ago

Did you also try toplevel in your test project?

    compress: {
        passes: 3,
        toplevel: true,
    }

toplevel is good for applications, not for libraries.

polytypic commented 7 years ago

Yes, I tried toplevel as:

    process.env.NODE_ENV === "production" && uglify({
      compress: {
        passes: 3
      },
      toplevel: true
    })

(which I believe is the correct place for the option) and also inside the compress object. It didn't seem to have an effect. If I guess correctly, the way Rollup works is that there are no toplevel names in the generated bundle, so toplevel shouldn't have an effect in such a setup?

kzc commented 7 years ago

the way Rollup works is that there are no toplevel names in the generated bundle, so toplevel shouldn't have an effect in such a setup?

rollup -f es doesn't generate an IIFE wrapper. In that case toplevel would be applicable.

Regarding toplevel, if options.toplevel is set, the uglify-js@3.x minify() function sets both options.compress.toplevel and options.mangle.toplevel. uglify-js@2.x behaved differently, but you're not using that.