Coder Social home page Coder Social logo

andarist / babel-plugin-annotate-pure-calls Goto Github PK

View Code? Open in Web Editor NEW
92.0 2.0 8.0 101 KB

This plugins helps with annotating top level functions calls with #__PURE__ comment.

JavaScript 100.00%
babel plugin pure side-effects uglifyjs minify

babel-plugin-annotate-pure-calls's Introduction

babel-plugin-annotate-pure-calls

npm version Build Status npm

This plugins helps with automatic #__PURE__ annotation insertion. It add the comment to top level call expressions and new expressions in assignment contexts (those are considered by the plugin as side effect free). This helps UglifyJS to perform dead code elimination more efficiently and therefore reduces the bundle sizes for the consumers.

NOTE: It might break your code, so the caution is advised. Target audience for the plugin are libraries, which in vast major of use cases do not introduce side effects in top level calls. That doesn't mean that application bundles cannot benefit from the plugin.

Pure calls

// pure call
var inc = add(1)

// clearly impure - no assignment context
mutate({ prop: 'value' })

Top level calls

Top level call (in terms of this plugin) is one that gets executed during script initialization. So it is every call located at the root of a file, but also a call in an IIFE that gets executed at startup (including nested ones).

var a = topLevelCall()

b = function() {
  noTopLevelCall()
}

topLevelIIFEs = (function() {
  var c = (function() {
    var d = (function() {
      var e = topLevelCall()
    })()
  })()
})()

Installation

npm install --save-dev babel-plugin-annotate-pure-calls

Usage

Via .babelrc (Recommended)

.babelrc

{
  "plugins": ["annotate-pure-calls"]
}

Via CLI

babel --plugins annotate-pure-calls script.js

Via Node API

require('babel-core').transform('var inc = add(1)', {
  plugins: ['annotate-pure-calls'],
})

Usage with babel@6

The plugin works with babel@6, you might see unmet peer dependency warning though. If you want to get rid of it, please install @babel/[email protected].

Similar projects

babel-plugin-annotate-pure-calls's People

Contributors

andarist avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

babel-plugin-annotate-pure-calls's Issues

Provide option to annotate only whitelisted identifiers

Note - the option should be able to handle renamed imports like this:

{ whitelist: [ 'taggedTemplateLiteral', { identifier: 'css' , source: 'emotion'  } ] }

So even if css gets some other local specifier (i.e. createCss), the plugin should be able to annotate createCss.

This would help people with annotating their bundles more safely.

Note that for the applications it might still be better to just use pure_funcs of the UglifyJS.

Review

@kzc

As for babel-plugin-annotate-pure-calls perhaps you could add some more documentation to its README explaining the use cases where it should and should not be used.

Already added some more documentation, but I certainly intend to work on that more soon.

The case result I cited was quite unexpected to me. I'm not convinced your revised example would be problem-free either.

Could you describe why the revised example might not be problem-free?

Perhaps this Babel plugin can only be used on pure functional libraries were every single function (internal or external) is known to be pure beforehand?

That is certainly the safest use case for this plugin, but I believe that's not the only one. I think that even effectful (in assignment contexts) calls can be annotated quite safely, if the result is not used by the program there is really high chance that side-effects of the call itself are also not relevant. This is an assumption ofc, but I think if in such example:

var unused = sideEffects()

those side effects are still needed for the program it is a sign that its weirdly/poorly structured program and should be restructured.

I wouldnt be too cautious before running this plugin (assuming the plugin working as expected) even on my applications' code (and im not hardcore fp purist). Ofc results need to be always verified and tested.

Minor bug with comment handling

https://github.com/Andarist/babel-plugin-annotate-pure-calls/blob/master/src/index.js#L6-L10

I have a comment in my code that looks like this:

/* eslint-disable babel/new-cap */

and it seems to be triggering this error:

ERROR in [redacted].js
Module build failed: TypeError: [redacted].js: Cannot read property 'some' of null
    at isPureAnnotated ([redacted]/node_modules/babel-plugin-annotate-pure-calls/lib/index.js:19:26)
    at annotateAsPure ([redacted]/babel-plugin-annotate-pure-calls/lib/index.js:26:7)
    at PluginPass.callableExpressionVisitor ([redacted]/babel-plugin-annotate-pure-calls/lib/index.js:111:3)

Skip callable expressions used as callees

Followup to #1 (comment)

Because of the situation described in the linked issue this:
input code

var b = fn(arg1())(arg2())(arg3())

actual code

var b = /*#__PURE__*/fn( /*#__PURE__*/arg1())( /*#__PURE__*/arg2())( /*#__PURE__*/arg3());

should produce this expected code

var b = /*#__PURE__*/fn(arg1())(arg2())( /*#__PURE__*/arg3());

Optimize ArrowFunctionExpression with implicit return

Input code

wait100 = new Promise(resolve => setTimeout(resolve, 100));

Actual output

wait100 = /*#__PURE__*/new Promise(resolve => /*#__PURE__*/setTimeout(resolve, 100));

Expected output

wait100 = /*#__PURE__*/new Promise(resolve => setTimeout(resolve, 100));

Upgrade peer dependency to @babel/core 7

Currently when using this plugin in a project that has @babel/core v7 installed, we get the following warning message

npm WARN [email protected] requires a peer of [email protected] || ^7.0.0-0 but none is installed. You must install peer dependencies yourself.

Agreed, it is only a warning. Though it would be nice if you could fix it.

Consider adding always effectful built-ins + configuration for them

Input code

var unusedTimerId = setInterval(function () {
  pingAPI()
})

Even though setInterval is used in assignment context and its result remain unused, its probably not desired to annotate (and therefore drop during minification) it.

Same applies for other timers and possibly some other built-ins.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.