Giter VIP home page Giter VIP logo

minify's Introduction

babel-minify (beta)

An ES6+ aware minifier based on the Babel toolchain.

NPM Version Travis Status CircleCI Status AppveyorCI Status Code Coverage Slack Status NPM Downloads

  • babel-minify is consumable via API, CLI, or Babel preset. Try it online - babeljs.io/repl

Historical note: babel-minify was renamed from babili.

Table of Contents

Experimental

babel-minify is an experimental project that attempts to use Babel's toolchain (for compilation) to do something in a similar vein, minification. It's currently in 0.x, so we don't recommend using it in production.

Checkout our CONTRIBUTING.md if you want to help out!

Requirements

  • node >= 6
  • babel >= 6.20.0

Why

Current tools don't support targeting the latest version of ECMAScript. (yet)

  • BabelMinify can because it is just a set of Babel plugins, and Babel already understands new syntax with our parser Babylon.
  • When it's possible to only target browsers that support newer ES features, code sizes can be smaller because you don't have to transpile and then minify.

Check out our blog post for more info!

// Example ES2015 Code
class Mangler {
  constructor(program) {
    this.program = program;
  }
}
new Mangler(); // without this it would just output nothing since Mangler isn't used

Before

// ES2015+ code -> Babel -> BabelMinify/Uglify -> Minified ES5 Code
var a=function a(b){_classCallCheck(this,a),this.program=b};new a;

After

// ES2015+ code -> BabelMinify -> Minified ES2015+ Code
class a{constructor(b){this.program=b}}new a;
Package Version Dependencies
babel-minify npm Dependency Status

Install

npm install babel-minify --save-dev

Usage

minify src -d lib
Package Version Dependencies
babel-preset-minify npm Dependency Status

Install

npm install babel-preset-minify --save-dev

Usage

note: minify is still in beta, so we don't recommend using it for production code but rather the production environment.

When testing, it's recommended to run minifiers for production so less code is sent to end-users vs. in development where it can be an issue for readability when debugging. Check out the env docs for more help.

Options specific to a certain environment are merged into and overwrite non-env specific options.

.babelrc:

{
  "presets": ["es2015"],
  "env": {
    "production": {
      "presets": ["minify"]
    }
  }
}

Then you'll need to set the env variable which could be something like BABEL_ENV=production npm run build

Individual Plugins

The minify repo is comprised of many npm packages. It is a lerna monorepo similar to babel itself.

The npm package babel-preset-minify is at the path packages/babel-preset-minify

Package Version Dependencies
babel-plugin-minify-constant-folding npm Dependency Status
babel-plugin-minify-dead-code-elimination npm Dependency Status
babel-plugin-minify-flip-comparisons npm Dependency Status
babel-plugin-minify-guarded-expressions npm Dependency Status
babel-plugin-minify-infinity npm Dependency Status
babel-plugin-minify-mangle-names npm Dependency Status
babel-plugin-minify-replace npm Dependency Status
babel-plugin-minify-simplify npm Dependency Status
babel-plugin-minify-type-constructors npm Dependency Status
babel-plugin-transform-member-expression-literals npm Dependency Status
babel-plugin-transform-merge-sibling-variables npm Dependency Status
babel-plugin-transform-minify-booleans npm Dependency Status
babel-plugin-transform-property-literals npm Dependency Status
babel-plugin-transform-simplify-comparison-operators npm Dependency Status
babel-plugin-transform-undefined-to-void npm Dependency Status

Usage

Normally you wouldn't be consuming the plugins directly since the preset is available.

Add to your .babelrc's plugins array.

{
  "plugins": ["babel-plugin-transform-undefined-to-void"]
}

Other

Package Version Dependencies
babel-plugin-transform-inline-environment-variables npm Dependency Status
babel-plugin-transform-node-env-inline npm Dependency Status
babel-plugin-transform-remove-console npm Dependency Status
babel-plugin-transform-remove-debugger npm Dependency Status

Benchmarks

Bootstrap: npm run bootstrap

Build: npm run build

Running the benchmarks: ./scripts/benchmark.js [file...] - defaults to a few packages fetched from unpkg.com and is defined in benchmark.js.

Note: All Input sources are ES5.

Benchmark Results for react.js:

Input Size: 54.79KB

Input Size (gzip): 15.11KB

minifier output raw raw win gzip output gzip win parse time (ms) minify time (ms)
babel-minify 15.97KB 71% 6.08KB 60% 1.00 1039.06
terser 15.65KB 71% 5.98KB 60% 0.93 532.19
uglify 15.6KB 72% 6KB 60% 1.09 463.69
closure-compiler 15.74KB 71% 6.04KB 60% 1.22 2361.41
closure-compiler-js 18.21KB 67% 6.73KB 55% 1.08 3381.47

Benchmark Results for vue.js:

Input Size: 282.52KB

Input Size (gzip): 77.52KB

minifier output raw raw win gzip output gzip win parse time (ms) minify time (ms)
babel-minify 104.21KB 63% 38.71KB 50% 6.09 3538.30
terser 103.12KB 63% 37.92KB 51% 6.42 1680.85
uglify 102.71KB 64% 38.08KB 51% 6.59 1662.50
closure-compiler 101.93KB 64% 38.6KB 50% 10.41 4413.06
closure-compiler-js 105.18KB 63% 39.5KB 49% 6.79 12082.80

Benchmark Results for lodash.js:

Input Size: 527.18KB

Input Size (gzip): 94.04KB

minifier output raw raw win gzip output gzip win parse time (ms) minify time (ms)
babel-minify 69.59KB 87% 24.37KB 74% 5.38 2587.27
terser 68.66KB 87% 24.31KB 74% 6.41 1913.43
uglify 68.15KB 87% 24.05KB 74% 5.89 2075.71
closure-compiler 71.05KB 87% 24.19KB 74% 6.24 4119.43
closure-compiler-js 73.51KB 86% 24.94KB 73% 5.17 9650.59

Benchmark Results for three.js:

Input Size: 1.05MB

Input Size (gzip): 212.43KB

minifier output raw raw win gzip output gzip win parse time (ms) minify time (ms)
babel-minify 535.88KB 50% 134.66KB 37% 27.24 9988.57
terser 536.16KB 50% 132.78KB 37% 28.39 3919.34
uglify 533.42KB 50% 133.21KB 37% 26.15 4025.20
closure-compiler 532.44KB 51% 134.41KB 37% 29.96 9029.19
closure-compiler-js 543.08KB 50% 136.3KB 36% 24.36 95743.77

Browser support

Babel Minify is best at targeting latest browsers (with full ES6+ support) but can also be used with the usual Babel es2015 preset to transpile down the code first.

Team

Amjad Masad Boopathi Rajaa Juriy Zaytsev Henry Zhu Vignesh Shanmugam
Amjad Masad Boopathi Rajaa Juriy Zaytsev Henry Zhu Vignesh Shanmugam
@amasad @boopathi @kangax @hzoo @vigneshshanmugam
@amasad @heisenbugger @kangax @left_pad @_vigneshh

minify's People

Contributors

38elements avatar aaronang avatar amasad avatar aslilac avatar bfred-it avatar boopathi avatar chrisvasz avatar dominator008 avatar goto-bus-stop avatar hzlmn avatar hzoo avatar j-f1 avatar jamiebuilds avatar jlhwung avatar kangax avatar kevinji avatar mathiasbynens avatar maurobringolf avatar msn0 avatar nicolo-ribaudo avatar oleksandr-kuzmenko avatar pieterbeulque avatar pksunkara avatar pmdartus avatar probins avatar sebmck avatar shinew avatar sylvesteraswin avatar vigneshshanmugam avatar xtuc 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 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

minify's Issues

Failing build because of `yield` keyword

I have errors like these when building with babel-preset-babili:

ERROR in ./src/redux/sagas/landing-menu.js
Module build failed: SyntaxError: The keyword 'yield' is reserved (1:2367)
    at Parser.pp.raise (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:1745:13)
    at Parser.pp.parseIdent (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:1464:240)
    at Parser.pp.parseExprAtom (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:1090:21)
    at Parser.pp.parseExprSubscripts (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:1023:19)
    at Parser.pp.parseMaybeUnary (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:1004:19)
    at Parser.pp.parseExprOps (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:948:19)
    at Parser.pp.parseMaybeConditional (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:930:19)
    at Parser.pp.parseMaybeAssign (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:908:19)
    at Parser.pp.parseVar (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:2743:24)
    at Parser.pp.parseVarStatement (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:2637:8)
    at Parser.pp.parseStatement (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:2437:19)
    at Parser.pp.parseBlock (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:2692:21)
    at Parser.pp.parseFunctionBody (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:1413:22)
    at Parser.pp.parseFunction (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:2770:8)
    at Parser.pp.parseFunctionStatement (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:2540:15)
    at Parser.pp.parseStatement (PROJECT_FOLDER/node_modules/acorn/dist/acorn.js:2420:19)
 @ ./src/redux/sagas/index.js 1:285-310

My .babelrc:

{
  "presets": [ "es2015", "stage-1", "react" ],
  "plugins": [
    "transform-runtime",
    "transform-decorators-legacy"
  ],
  "env": {
    "production": {
      "presets": ["babili"],
      "plugins": [
        "transform-react-inline-elements",
        "transform-react-constant-elements"
      ]
    }
  }
}

Plugin Options

I think if we aren't going to split each little thing into a plugin (overkill), we can just setup options for the smaller stuff in the packages?

We could also separate those out into different sections or files although maybe being in the same file is good too?

Oh I see we have a few options in some of the plugins already

Multiple passes?

Are there situations that we might need multiple passes for better minification ?

For example, one plugin might transform

if (a) foo (x) : foo (y);
//to
a ? foo (x) : foo (y)

and another plugin might transform

//to
foo (a ? x : y);

// or even,
x ? foo(a) : foo(b)
//to
foo (x ? a : b)

and another one could remove this as pure expression statement. or modify it differently. I'm not able to think about it.

So the order of plugins in the preset will matter, and we say (with plugins- a and b) the order is a, b, and another particular transformation might require the order to be b, a. So, should we explore multiple passes. I'm not sure if this is a problem. Just asking if there are situations that you faced like this.

Variable name collision in mangler

The following:

(function() {
  for (let x in y) y[x];
  f(() => { g() });
})();

function g() {}

mangles to:

function i() {}
    function() {
        for (var i in y) y[i];
        f(function() {
            i()
        })
    }()

The i var is conflicting.

Before Alpha Release

  • move minification plugins out of babe/babel #33
  • wrap babel-cli #49
  • guide/how to use it #50
    • as a babel preset/plugin
    • using the cli standalone

can't we just make the babel-minify executable a child.process that calls out to the babel CLI just with a --presets minify argument appended?

  • reasoning, and how it works (explanation about how babel is a compiler and optimization is just another thing that it can do just like converting es2015, it should be faster since it's the same tool and can be run as part of your babel build)

  • make sure the names aren't taken: #8 #46
  • remove minify plugins from babel/babel babel/babel#3621 and transfer any updates #75
  • publish all packages as alpha, ask for testers/help
  • transfer repo to babel org, make public
  • Online demo/try it out: #28 (would be nice to turn on/off plugins individually, time to minify)

After

  • transfer relevant PRs to move to minify
  • add greenkeeper #74

Integration Tests

Ref #33 (comment)

The benchmarks are cool, but we could reduce the size and find out we are breaking the functionality (especially for the dead code elimination plugin).

So we could be running the unit tests of the project on the minified code?

Should simplify plugin be split into many plugins?

There's a lot of one-off transformations inside the simplify plugin that don't necessarily need to be grouped together.

If they were split up into a bunch of separate plugins, each individual transformation would likely be much easier to follow and would make contributions easier.

Set hard dependency on babel.version

The preset or cli or node api when used with previous versions of babel, due to the rename bugs and evaluate bugs, we will be introducing bugs in user code that will be hard to grok that it is a bug with babel. We need to either fix this somehow for mangle and evaluate in the minifier or set hard dependency that it bails out for older versions of babel.

"Error: spawn UNKNOWN"

When trying to use the CLI version:

node_modules\.bin\babili.cmd -d .

internal/child_process.js:298
    throw errnoException(err, 'spawn');
    ^

Error: spawn UNKNOWN
    at exports._errnoException (util.js:856:11)
    at ChildProcess.spawn (internal/child_process.js:298:11)
    at Object.exports.spawn (child_process.js:367:9)
    at Object.<anonymous> (C:\temp\babilitest\node_modules\babili\lib\index.js:16:25)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)

Windows 10, Node v5.7.1 (I should probably upgrade Node, guess)

Name change to babel-minify

Ok it's changed (pkgs should be updated as of 0.2.0)

Change it back to babel-minify? Ref #8

Given that it's just a preset + plugins it makes sense to just be babel-minify so everyone understands what it is and we don't have issues trying to explain it or it's pronunciation.

And after talking with people about it (what's that?), I refer to it as the babel minifier anyway. Haven't met many people that liked the name ๐Ÿ˜› .

cli: babili
preset: babel-preset-babili

cli: babel-minify
preset: babel-preset-minify


Message from @thejameskyle:

Since I can already tell this thread will blow up:

A couple notes before you comment in this thread

Please ensure that any comment you are making on this thread is actively contributing to the discussion of a name change. Please do not go on tangents, please be respectful of others (follow the Babel CoC), and don't just keep repeating something that has been said. Be aware of strawman arguments and other logical fallacies and don't do them. Dont assert your own opinions/experiences as the opinions and experiences of the entire community. Yada yada yada be constructive, be aware, don't be mean.

Incorrect function name for methods

As you can see in the REPL

function foo() {
  function getX(o){ return o.x; }
  const obj = {
    getter: getX
  };
  return obj
}

is transformed to

"use strict";function foo(){return{getter:function getter(b){return b.x}}}

The returned function should retain its original name (getX in this case) not take on the name of the property (getter here).

This appears to work as expected outside of a function.

More optimizations

  • Remove unused args (e.g. bar in function foo(bar) { })
  • Remove space after return when possible (e.g. return [1,2,3] โ†’ return[1,2,3])
  • var result = expression(); foo.bar = result; โ†’ foo.bar = expression()
  • Better constant propagation (looks like it is in the dead-code-elimination plugin, but its a combination of both)
var b = () => {
  var x = 14;
  var y = 7 - x / 2;
  return y * (28 / x + 2);
};
var a = () => {
  var a = 14;

  return (7 - a / 2) * (28 / a + 2);
};

Naming collision in mangle plugin when using `transformFromAST`

TLDR:

(traverse + block-scoping) โ†’ AST โ†’ traverse.clearCache() โ†’ (traverseFromAST + mangle) results in a naming conflict :)

The following code:

const babel = require('babel-core');
const traverse = require('babel-traverse').default;
const mangle = require('./packages/babel-plugin-minify-mangle-names/lib/index.js');

const srcTxt = `
  function f(x) {
    for (let i = 0; i; i++) {
      let n;
      if (n) return;
      g(() => n);
    }
  }
`;

const ast = babel.transform(srcTxt, {
  code: false,
  plugins: ['transform-es2015-block-scoping'],
}).ast;

traverse.clearCache();

const code = babel.transformFromAst(ast, null, {
  plugins: [mangle],
}).code;

console.log(code);

produces this output:

function f(a) {
  var b = function (c) {
    var b = void 0;
    if (b) return {
        v: void 0
      };
    g(() => b);
  };

  for (var c = 0; c; c++) {
    var a = b(c);
    if (typeof a === "object") return a.v;
  }
}

Notice conflict between a in arguments and a in a loop block. Removing clearCache fixes it BUT then mangling is incomplete:

function f(a) {
  var _loop = function (b) {
    var b = void 0;
    if (b) return {
        v: void 0
      };
    g(() => b);
  };

  for (var b = 0; b; b++) {
    var _ret = _loop(b);

    if (typeof _ret === "object") return _ret.v;
  }
}

Update Readme

Just making a list of things that could be helpful to have.

  • how to run tests, benchmarks
  • travis + build badge
  • maybe an example for each plugin - #5

Thought: Module Inlining?

This preset already seems to do a ton of what other toolchains offer in terms of DCE, mangling, etc. What about taking that last step and having it support merging a whole graph of ES Modules dependencies into a single closure? (Prior art here being perhaps Rollup)

Unexpected UnaryExpression. Expected an Identifier

I'm seeing the above error when I have lots of nested if/else's with the occasional empty block.

Stack trace if it's useful

Error: test.js: Unexpected UnaryExpression. Expected an Identifier
    at Mangler.renameNew (foo/node_modules/babel-plugin-minify-mangle-names/lib/index.js:193:19)
    at foo/node_modules/babel-plugin-minify-mangle-names/lib/index.js:143:23
    at Array.map (native)
    at Scopable (foo/node_modules/babel-plugin-minify-mangle-names/lib/index.js:135:16)
    at NodePath._call (foo/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (foo/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (foo/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (foo/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitMultiple (foo/node_modules/babel-traverse/lib/context.js:103:17)
    at TraversalContext.visit (foo/node_modules/babel-traverse/lib/context.js:190:19)

Minimum example I could come up with (repl)

function foo() {
  var a, b, c;

  if (a) {
    if (b) {
      if (c) {}
    }
  } else {
    if (b) {
    } else {
      if (c) {}
    }
  }
}

Seems to be coming from the interaction of minify-dead-code-elimination and minify-mangle-names (both seem fine individually but fail when used together)

Error's being thrown here which suggests it might be an upstream Babel bug?

Move some testing helpers into a module

Might be a little less setup?
Something like (maybe need to split up or move arguments around):
Basically always unpad, trim

const babel = require("babel-core");
const unpad = require("utils/unpad");

export function transform(source, plugin, options) {
  return babel.transform(unpad(source),  {
    plugins: [[plugin, options]],
  }).code.trim();
}

export function expectTransform(source, expected, plugin, options = {}) {
  return expect(transform(source, plugin, options)).toBe(unpad(expected));
}

Incorrect minify-empty-function?

Why is foo(emptyFunction('how long', '?')); minified to foo(false)?

https://github.com/amasad/babel-minify/blob/0a37687f01fefeacace653d7537e132b386b79f3/packages/babel-plugin-minify-empty-function/__tests__/empty-function-test.js#L37

Is this test not final/functional? https://github.com/amasad/babel-minify/blob/0a37687f01fefeacace653d7537e132b386b79f3/packages/babel-plugin-minify-empty-function/__tests__/empty-function-test.js#L12

And where does this emptyFunction come from? It looks like it's noop inserted by other plugins, but its usage might be confusing for direct users.

Compression breaks commonmark npm package

I am using react-markdown which uses commonmark. When compiling the code with babili it breaks in some crazy way. It leads to an endless loop for both NodeJS and Chrome.

I am still investigating to narrow this down a little more.

Just wondering: Is there some special utf-8/unicode related functionality in babili?

Minify options

Since it is a preset, there won't be any options passed to the minifier.

for example,

  • mangle topLevel names
  • mangle eval accessible bindings - don't deopt because of the presense of eval
  • apply unsafe optimizations like - !== to !=, >= to <
  • drop debugger & console statements or just one of them
  • preserve fn args and fn name for code depending on fn.length & fn.name

etc...

How to support these as options to be passed to the minifier - when used as a CLI or a Preset?

Finish documenting Plugin Options

Some plugins have options already but they aren't documented in both the readme and the top level readme

babel-plugin-minify-dead-code-elimination: optimizeRawSize
babel-plugin-minify-mangle-names: mangleBlacklist
babel-plugin-minify-replace: replacements

Feature freeze / testing

Every feature we add adds uncertainty and potential regressions. Therefore, in order to get to a beta release, we need to stop adding any more features and focus instead on testing.

Here are ways you can help:

  • Try to integrate the minifier in your project
  • Find bugs and reduce them to test cases for a given package and send a PR
  • (If you can fix the bug with your PR but a test case is better than nothing)
  • Look at existing PRs and issues and either fix or add related test cases

Conditional Operator

I'm starting to implement these things. Should this be in dce or simplify ?

a === b ? true : false
a < b ? false : true
a() ? false : true
b() ? true : false
a ? b : true
a ? b : false

// out:
x === y
!(a < b)
!a()
!!b()
!a || b
!!a && b

[dce] removes Fn name when it's used within the function

INPUT

(function (require, module, exports) {
  var Hub = function Hub(file, options) {
    (0, _classCallCheck3.default)(this, Hub);
  };
  module.exports = Hub;
})(require, module, exports);

OUTPUT

(function (require, module, exports) {
  module.exports = function (file, options) {
    (0, _classCallCheck3.default)(this, Hub);
  };
})(require, module, exports);

Sub-optimal boolean returns

Input:

function isTextInputElement(elem) {
  if (!elem) {
    return false;
  }

  if (elem.nodeName === 'INPUT') {
    return !!supportedInputTypes[elem.type];
  }

  if (elem.nodeName === 'TEXTAREA') {
    return true;
  }

  return false;
}

GCC Output:

function(a){return a?"INPUT"===a.nodeName?!!supportedInputTypes[a.type]:"TEXTAREA"===a.nodeName?!0:!1:!1}

Two things to be noted:

  • if (a === b) { return true; } return false; is outputted as a === b ? !0 : !1 which can be simplified as a === b, no need to do the condition.
  • all the return values have ! in common, it is possible to factor it out. return !(a?"INPUT"===a.nodeName?!supportedInputTypes[a.type]:"TEXTAREA"===a.nodeName?0:1:1)

Add benchmarks that show transpilation + minification times

What people actually care about w.r.t. build times is usually the end-to-end time. Talking with @skevy, we were saying a typical production build pipeline will transpile and minify, which previously entailed running Babel (ex: with es2015 preset) and then Uglify. But now a pipeline could run just Babel (ex: with es2015 + babili).

The perf benchmarks currently make Uglify look way better than Babili to people who prefer 1.5-2x faster build times for roughly the same end result, but if the actual end-to-end build times that comprise transpilation and minification are faster, that'd change a lot of minds.

Minimum browser support is unclear

The README has an implicit requirement of only targeting new-enough browsers, but doesn't explicitly say what those browsers are (or what features are needed).

When it's possible to only target browsers that support newer ES features, code sizes can be smaller because you don't have to transpile and then minify.

I looked through some of the rules and only found a single mention of IE8 being unsupported.

eslint preset

It's weird that the style is single quote but then in babel/babylon/lerna it's double quote (among other things)

ModuleBuildError: Module build failed: TypeError: Cannot read property 'scope' of undefined

๐Ÿ‘‹ - getting this setup with a reasonably sized production React app using Flow. All our babel versions are up-to-date.

Ran into this error, which traces back to:

https://github.com/babel/babili/blob/master/packages/babel-plugin-minify-dead-code-elimination/src/index.js#L212

Error is thrown from the entry point of the app:

/* @flow */
import React, { Component } from 'react'
import { Provider } from 'react-redux'
import { IntlProvider } from 'react-intl'
import routes from './routes'
import store from './store'

export default class App extends Component {

  static displayName = 'App';

  render() {
    return (
      <IntlProvider locale="en">
        <Provider store={store}>
          {routes}
        </Provider>
      </IntlProvider>
    )
  }
}

Stacktrace:

ModuleBuildError: Module build failed: TypeError: /Users/brendan/src/app/src/app.js: Cannot read property 'scope' of undefined
    at ReferencedIdentifier (/Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:341:37)
    at newFn (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/visitors.js:318:17)
    at NodePath._call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitSingle (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:108:19)
    at TraversalContext.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:192:19)
    at Function.traverse.node (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:161:17)
    at traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:83:12)
    at NodePath.traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/index.js:144:25)
    at /Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:331:35
    at _loop3 (/Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:396:16)
    at Object.enter (/Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:404:23)
    at Object.newFn (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/visitors.js:318:17)
    at NodePath._call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitSingle (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:108:19)
    at TraversalContext.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:192:19)
    at Function.traverse.node (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:161:17)
    at NodePath.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:115:19)
    at TraversalContext.visitQueue (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitMultiple (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:103:17)
    at TraversalContext.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:190:19)
    at Function.traverse.node (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:161:17)
    at traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:83:12)
    at NodePath.traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/index.js:144:25)
    at PluginPass.Program (/Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:769:14)
    at /Users/brendan/src/app/node_modules/webpack/lib/NormalModule.js:138:20
    at /Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:328:11
    at /Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:201:18
    at runSyncOrAsync (/Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:114:3)
    at iterateNormalLoaders (/Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:200:2)
    at /Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:173:4
    at Storage.finished (/Users/brendan/src/app/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:39:16)
    at /Users/brendan/src/app/node_modules/graceful-fs/graceful-fs.js:78:16
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:404:3)

.babelrc:

{
  "presets": ["es2015", "react"],
  "plugins": [
    "array-includes",
    "syntax-class-properties",
    "transform-class-properties",
    "transform-flow-strip-types",
    "transform-object-rest-spread",
    "transform-react-inline-elements",
    "transform-react-pure-class-to-function",
    "transform-react-remove-prop-types"
  ],
  "env": {
    "production": {
      "presets": ["babili"],
      "plugins": [
        "transform-runtime"
      ]
    },
    "development": {
      "plugins": [
        "transform-runtime",
        ["react-transform", {
          "transforms": [{
            "transform": "react-transform-hmr",
            "imports": ["react"],
            "locals": ["module"]
          }, {
            "transform": "react-transform-catch-errors",
            "imports": ["react", "redbox-react"]
          }]
        }]
      ]
    },
    "test": {
      "plugins": [
        ["transform-runtime", { "polyfill": false }]
      ]
    }
  }
}

Possibly related to these warnings, which only appear with babili turned on:

You or one of the Babel plugins you are using are using Flow declarations as bindings.
        Support for this will be removed in version 6.8. To find out the caller, grep for this
        message and change it to a `console.trace()`.

Ran with console.trace():

ModuleBuildError: Module build failed: TypeError: /Users/brendan/src/app/src/app.js: Cannot read property 'scope' of undefined
    at ReferencedIdentifier (/Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:341:37)
    at newFn (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/visitors.js:318:17)
    at NodePath._call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitSingle (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:108:19)
    at TraversalContext.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:192:19)
    at Function.traverse.node (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:161:17)
    at traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:83:12)
    at NodePath.traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/index.js:144:25)
    at /Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:331:35
    at _loop3 (/Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:396:16)
    at Object.enter (/Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:404:23)
    at Object.newFn (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/visitors.js:318:17)
    at NodePath._call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitSingle (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:108:19)
    at TraversalContext.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:192:19)
    at Function.traverse.node (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:161:17)
    at NodePath.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:115:19)
    at TraversalContext.visitQueue (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitMultiple (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:103:17)
    at TraversalContext.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:190:19)
    at Function.traverse.node (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:161:17)
    at traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:83:12)
    at NodePath.traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/index.js:144:25)
    at PluginPass.Program (/Users/brendan/src/app/node_modules/babel-plugin-minify-dead-code-elimination/lib/index.js:769:14)

I tried implementing each plugin one-by-one, I get a similar error for babel-plugin-minify-constant-folding:

ModuleBuildError: Module build failed: TypeError: /Users/brendan/src/app/src/app.js: Cannot read property 'node' of undefined
    at Mangler.renameNew (/Users/brendan/src/app/node_modules/babel-plugin-minify-mangle-names/lib/index.js:188:26)
    at /Users/brendan/src/app/node_modules/babel-plugin-minify-mangle-names/lib/index.js:143:23
    at Array.map (native)
    at Scopable (/Users/brendan/src/app/node_modules/babel-plugin-minify-mangle-names/lib/index.js:135:16)
    at NodePath._call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitSingle (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:108:19)
    at TraversalContext.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:192:19)
    at Function.traverse.node (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:161:17)
    at NodePath.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:115:19)
    at TraversalContext.visitQueue (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitMultiple (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:103:17)
    at TraversalContext.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:190:19)
    at Function.traverse.node (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:161:17)
    at traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:83:12)
    at NodePath.traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/index.js:144:25)
    at Mangler.mangle (/Users/brendan/src/app/node_modules/babel-plugin-minify-mangle-names/lib/index.js:100:22)
    at Mangler.run (/Users/brendan/src/app/node_modules/babel-plugin-minify-mangle-names/lib/index.js:45:14)
    at PluginPass.Program (/Users/brendan/src/app/node_modules/babel-plugin-minify-mangle-names/lib/index.js:263:17)
    at newFn (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/visitors.js:276:21)
    at NodePath._call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitSingle (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:108:19)
    at TraversalContext.visit (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/context.js:192:19)
    at Function.traverse.node (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:161:17)
    at traverse (/Users/brendan/src/app/node_modules/babel-core/node_modules/babel-traverse/lib/index.js:83:12)
    at /Users/brendan/src/app/node_modules/webpack/lib/NormalModule.js:138:20
    at /Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:328:11
    at /Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:201:18
    at runSyncOrAsync (/Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:114:3)
    at iterateNormalLoaders (/Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:200:2)
    at /Users/brendan/src/app/node_modules/loader-runner/lib/LoaderRunner.js:173:4
    at Storage.finished (/Users/brendan/src/app/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:39:16)
    at /Users/brendan/src/app/node_modules/graceful-fs/graceful-fs.js:78:16
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:404:3)

But with the following config (the preset minus the two plugins that cause issues), everything works well:

      "plugins": [
        "transform-runtime",
        "babel-plugin-transform-undefined-to-void",
        "babel-plugin-transform-simplify-comparison-operators",
        "babel-plugin-transform-property-literals",
        "babel-plugin-transform-minify-booleans",
        "babel-plugin-transform-merge-sibling-variables",
        "babel-plugin-transform-member-expression-literals",
        "babel-plugin-minify-type-constructors",
        "babel-plugin-minify-simplify",
        "babel-plugin-minify-replace",
        "babel-plugin-minify-infinity",
        "babel-plugin-minify-guarded-expressions",
        "babel-plugin-minify-flip-comparisons",
        "babel-plugin-minify-constant-folding"
      ]

[dce] named class expressions to void 0

INPUT:

(function() {
  var B = class A {
    constructor(x) {
      console.log(x);
    }
  }
  self.addEventListener(function (event) {
    new B(event);
  })
})();

OUTPUT

"use strict";

(function () {
  var B = void 0;
  self.addEventListener(function (event) {
    new B(event);
  });
})();

Webpack Issues

My installed packages:

"devDependencies": {
  "babel-core": "^6.13.2",
  "babel-loader": "^6.2.5",
  "babel-plugin-transform-es2015-modules-commonjs": "^6.14.0",
  "babel-preset-babili": "0.0.1",
  "babili": "0.0.3",
  "browserify-versionify": "^1.0.6",
  "ify-loader": "^1.0.3",
  "shader-loader": "^1.2.1",
  "webpack": "^1.13.2",
  "webpack-dev-server": "^1.14.1"
}

My babel loader config:

{
  test: /\.js$/,
  exclude: /(node_modules)/,
  loader: `babel`,
  query: {
    presets: [`babili`],
    plugins: [`transform-es2015-modules-commonjs`]
  }
}

Error upon running webpack-dev-server --inline --colors:

ERROR in ./script.js
Module build failed: Error: Cannot find module 'babel-types'
    at Function.Module._resolveFilename (module.js:325:15)
    at Function.Module._load (module.js:276:25)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/home/ubuntu/workspace/node_modules/babel-preset-babili/node_modules/babel-plugin-minify-mangle-names/lib/renamer.js:14:9)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
 @ multi main

I explicitly installed babel-types, and now get this error upon re-running:

ERROR in ./script.js
Module build failed: Error: Plugin 0 specified in "foreign" provided an invalid property of "name"
    at Plugin.init (/home/ubuntu/workspace/node_modules/babel-core/lib/transformation/plugin.js:138:13)
    at Function.normalisePlugin (/home/ubuntu/workspace/node_modules/babel-core/lib/transformation/file/options/option-manager.js:147:12)
    at /home/ubuntu/workspace/node_modules/babel-core/lib/transformation/file/options/option-manager.js:181:30
    at Array.map (native)
    at Function.normalisePlugins (/home/ubuntu/workspace/node_modules/babel-core/lib/transformation/file/options/option-manager.js:153:20)
    at OptionManager.mergeOptions (/home/ubuntu/workspace/node_modules/babel-core/lib/transformation/file/options/option-manager.js:245:36)
    at /home/ubuntu/workspace/node_modules/babel-core/lib/transformation/file/options/option-manager.js:289:14
    at /home/ubuntu/workspace/node_modules/babel-core/lib/transformation/file/options/option-manager.js:342:20
    at Array.map (native)
    at OptionManager.resolvePresets (/home/ubuntu/workspace/node_modules/babel-core/lib/transformation/file/options/option-manager.js:305:20)
 @ multi main

Name

Are we planning on keeping the babel-minify name? Might be better to have a distinct name for it so it can be marketed better. Being separate from the Babel brand, regardless of if it's in the org might be better too since Babel has historically had the stigma of trying to be everything at once.

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.