Read more

Webpacker: Configuring browser compatibility

Avatar
Henning Koch
April 10, 2018Software engineer at makandra GmbH

Webpacker Show archive.org snapshot uses Babel and Webpack to transpile modern JavaScript down to EcmaScript 5. Depending on what browser a project needs to support, the final Webpack output needs to be different. E.g. when we need to support IE11 we can rely on fewer JavaScript features. Hence our output will be more verbose than when we only need support modern browsers.

Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show archive.org snapshot

Rails 5.1+ projects often use Webpacker to preconfigure the Webpack pipeline for us. The default configuration works something like this:

  1. Webpack checks which files need to be compiled
  2. Babel dumbs down JavaScript for old browsers, but leaves ES5 module directives in place (require / export)
  3. Webpack replaces require and export directives with function calls to a Webpack-provided module registry.
  4. Webpack bundles everything into a single large file
  5. UglifyJS compresses the output by removing comments, renaming local variables, etc.

When targeting old browsers you need to make sure all steps in the pipeline are aware of your compatibility target. Configuring Babel alone is not enough, because UglifyJS might re-break your code once Babel is done.

Configuring browser compatibility in Babel

We tell Babel which JavaScript features to dumb down by adding Babel plugins. There are a lot of plugins Show archive.org snapshot , so choosing the right set involves a lot of trips to caniuse.com Show archive.org snapshot .

Luckily there is a package babel-preset-env Show archive.org snapshot that can pick the right plugins for you. You just need to tell it which browsers you support in your .babelrc. For example, if you need to support ancient browsers:

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": [
          "> 1%",
          "Firefox >= 52", // old ESR
          "IE 11"
        ],
        "uglify": true
      },
      "useBuiltIns": true
    }]
  ]
}

UglifyJS also has compatibility settings

Once Babel and Webpack is done, the resulting bundle is run through UglifyJS Show archive.org snapshot to remove comments, shorten variable names, etc. This results in a smaller file size (even if you are compressing with gzip afterwards).

UglifyJS is not aware of your Babel plugins. Even when you configure Babel to support old IE, UglifyJS might rewrite the Babel output so it is no longer compatible with old IE. We had this issue when we used the Babel to dumb down shorthand object properties Show archive.org snapshot , but then UglifyJS would restore shorthand properties, since they are shorter. IE11 does not support shorthand properties.

You can configure UglifyJS's browser support with many configuration options Show archive.org snapshot . The most important option is { ecma }. Setting this to { ecma: 5 } will usually result in broad compatibility with legacy browsers, while { ecma: 8 } will expect a modern JavaScript runtime.

Webpacker 3 breaks IE11

Webpacker 3 has a bug where it hard-codes Show archive.org snapshot UglifyJS options to { ecma: 8 }. So no matter how many Babel plugins you use, the resulting output will break IE11.

You can work around this by adding the following line to your config/webpack/production.js:

environment.plugins.get("UglifyJs").options.uglifyOptions.ecma = 5

The { ecma } option will be configurable in Webpacker 4. Note that even with Webpacker 4 you will need to pay attention to your UglifyJS options, and keep it consistent with the browsers you are targeting in Babel.

Posted by Henning Koch to makandra dev (2018-04-10 18:04)