How to stop babel from transpiling 'this' to 'undefined' (and inserting "use strict")

For Babel >= 7.x

ES6 code has two processing modes:

  • "script" - When you load a file via a <script>, or any other standard ES5 way of loading a file
  • "module" - When a file is processed as an ES6 module

In Babel 7.x, files are parsed as "module" by default. The thing that is causing you trouble is that in an ES6 module, this is undefined, whereas in the "script" case, this varies depending on the environment, like window in a browser script or exports in CommonJS code. Similarly, "module" files are automatically strict, so Babel will insert "use strict";.

In Babel 7, you'll need to tell Babel what type your file is if you want to avoid this behavior. The simplest option would be to use the "sourceType" option to set sourceType: "unambiguous" in your Babel options, which essentially tells Babel to guess the type (scripts vs module), based on the presence of import and export statements. The primary downside there being that it's technically fine to have an ES6 module that doesn't use import or export, and those would be incorrectly treated as scripts. On the other hand, that's really not that common.

Alternatively, you can use Babel 7's "overrides" option to set specific files as scripts, e.g.

overrides: [{
  test: "./vendor/something.umd.js",
  sourceType: "script",
}],

Either approach allows Babel to know that some files are script types, and thus shouldn't have this converted to undefined.

For Babel < 7.x

ES6 code has two processing modes:

  • "script" - When you load a file via a <script>, or any other standard ES5 way of loading a file
  • "module" - When a file is processed as an ES6 module

When using Babel 6 and babel-preset-es2015 (or Babel 5), Babel by default assumes that files it processes are ES6 modules. The thing that is causing you trouble is that in an ES6 module, this is undefined and files are all strict, whereas in the "script" case, this varies depending on the environment, like window in a browser script or exports in CommonJS code.

If you are using Babel, the easiest option is to write your code without the UMD wrapper, and then bundle your file using something like Browserify to automatically add the UMD wrapper for you. Babel also provides a babel-plugin-transform-es2015-modules-umd. Both are geared toward simplicity, so if you want a customized UMD approach, they may not be for you.

Alternatively, you would need to explicitly list all of the Babel plugins in babel-preset-es2015, making sure to exclude the module-processing babel-plugin-transform-es2015-modules-commonjs plugin. Note, this will also stop the automatic addition of use strict since that is part of the ES6 spec too, you may want to add back babel-plugin-transform-strict-mode to keep your code strict automatically.

As of [email protected] presets are able to take options, so you can also do

{
  "presets": [
    [ "es2015", { "modules": false } ]
  ]
}

in your Babel config (.babelrc) to use babel-preset-es2015 with module processing disabled.


The "es2015" preset wraps the Babel output in a commonJs wrapper by default. Use the "babel-preset-es2015-script" (you must npm install --save babel-preset-es2015-script first) to output for "script" (no modules). This was wreaking havoc on other libraries I was wrapping up using Babel.

The preset: https://www.npmjs.com/package/babel-preset-es2015-script