Dead code elimination with Uglify and Bucklescript

interop

#1

I saw an interesting question on Discord today about accessing process.env.NODE_ENV for dead code elimination with Uglify.

Background

A little background for those who are not familiar with this.

var setting = process.env.NODE_ENV === "production" ? "production" : "development"

Combines with webpack DefinePlugin or browserify envify plugin, the snippet above will be turned into

var setting = "production" === "production" ? "production" : "development"

and uglify will applies its magics to turn it into

var setting = "production"

Bucklescript

How to do that in Bucklescript then?

First, binding:

[@bs.val] external env : string = "process.env.NODE_ENV";

Usage:

let settings =
  if (env == "production") {
    "production";
  } else {
    "development";
  };

Some notes:

  • Do not extract env == "production" into a variable, uglify can’t deal with that
  • Do not use ternary
let settings = env == "production" ? "production" : "development";

The above ternary is desugared into a pattern matching expression like this

let settings =
  match env = "production" with
  | true  -> "production"
  | false  -> "development"

Bucklescript turns it into

var match = +(process.env.NODE_ENV === "production");
var settings = match !== 0 ? "production" : "development";

Uglify can’t work with that either.


#2

Use any hack for now. We’ll look into removing the distinction between ocaml and js bool soon


#3

Even if with js bool support, I don’t think this article needs to be changed. Because we need to print to JS the exact bit


#4

Sorry I misread your thread. I was commenting on the + part which is killed by the removal of difference between bool and boolean.

Though I’d also suggest https://bucklescript.github.io/docs/en/conditional-compilation.html

Example usage: https://github.com/Schmavery/reprocessing/blob/0f443c6d22719b6f3081a340f50435cef20af4ff/src/Reprocessing_Hotreload.ml#L6

Much less magic; doesn’t rely on two plugins fragi-ly communicating with each other.


#5

Can I inject a new constant to conditional compilation?


#6

Yeah, see https://bucklescript.github.io/docs/en/conditional-compilation.html#built-in-custom-variables

Note: OCaml syntax only for now. Reason should probably have a similar feature to match it.


#7

Thank you. This is awesome. I feel like use webpack + uglify is so fragile. Can’t wait to have this in Reason suntax



#8

Update for bs-platform@^4.0.0

Define it like this:

[@bs.val] external env : string = "process.env.NODE_ENV";

Then you use is like this:

env == "production"