babel-loader: Plugin transform-runtime with webpack doesn't work properly

Trying to make working transform-runtime plugin within webpack babel-loader.

loaders: [{
      test:   /\.js$/,
      loader: 'babel-loader',
      query: {
        presets: ['es2015'],
        plugins: ['transform-runtime']
      }
    }]

Packages babel-runtime and babel-plugin-transform-runtime are both installed.

I have 2 different results in 2 different projects:

  • On a real project it increase the size of file (is that fine?) babel-transform-runtime
  • Then I decided to test it within 2 simple files. No impacts. The same built file with and without the plugin.

Am I doing something wrong or there is a real bug there?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 16
  • Comments: 34 (3 by maintainers)

Most upvoted comments

Same here, i am compiling with transform runtime plugin and still have those helpers in each module file.

I figured out what’s going on. The babel-plugin-transform-runtime plugin is correctly doing its business and the babel-loader is returning the correct source to webpack. But then webpack’s module resolution begins and traces the dependencies within the source code, expanding them out. So in this case when transform-runtime adds require("babel-runtime/helpers/createClass") to the file, webpack says, “hey, let me find that dependency” finds it and expands it out to the final output, including what you were trying to exclude.

So the workaround is to add a regex to the webpack “externals” config with:

externals: [
    /^babel-runtime/
]

Then all is well.

It’d be nice if this could work as expected, but I’m not sure there is any mechanism for telling webpack to ignore resolving specific dependencies.

EDIT: You may also need to add libraryTarget: 'commonjs' to the output object.

@jesprider - Thanks for providing the negative test case, it should make it far easier to track this down. I’ve thrown this on the hotlist and as such, the resolution will take priority.

Give me a day to get a few things in place & i’ll see if I can get to the bottom or this. That said, given the obvious performance implications of that amount of duplication this certainly isn’t working as intended.

I’m seeing the same. transform-runtime doesn’t appear to remove _interopRequireWildcard declarations from the generated source, which appears to be the majority of duplication

I rewrote the sample files a bit. Now I have class Page in page.js. home.js and about.js create instances of the page class. In app.js I import these two pages and call a method.

The result of building with transform-runtime: 5 additional modules in build file, weight is twice more. Does it work how it supposed to work?

I put my sample app here with 2 different builds to compare: sample.zip

Sorry to necropost, but if you see this error ReferenceError: Unknown plugin "@babel/transform-runtime" specified, you might type “yarn why babel-core” or similar to see why an older package (babel-core which is v6) is included instead of (@babel/core which is v7). In my case I had @babel/core in my package.json but I had to “yarn add jest” to bump the jest version and get it to recognize it

Hey all, I believe the size issues here should be resolved in Babel 7. The reason it was so large in Babel 6 is because it also pulled in additional polyfilling logic, but in Babel 7 this requires opt-in behavior alongside @babel/runtime-corejs2 instead of @babel/runtime.

This seems like a pretty big issue. I’m not sure why it hasn’t got more traction if it really doesn’t do what it’s intended to do without a bunch of workarounds. I’m hoping I’m just doing something stupid. I’m using

    "webpack": "^4.5.0",
    "@babel/runtime": "^7.0.0-beta.44"
    "@babel/preset-env": "^7.0.0-beta.44",
    "@babel/core": "^7.0.0-beta.44",
    "@babel/plugin-transform-runtime": "^7.0.0-beta.44",

with a .babelrc of

{
  "presets": [
    ["@babel/env", {
      "targets": {
        "browsers": [
          "last 2 versions",
          "not IE <= 10"
        ]
      },
      "modules": false
    }]
  ],
  "plugins": ["@babel/plugin-transform-runtime"],
}

If I add a simple ES7 file like:

function sleep(duration) {
  return new Promise(function(resolve, reject) {
    setTimeout(()=> { resolve(0) }, duration);
  })
}

export async function delayedMessage(message, delay) {
  let remainingTime = await sleep(delay)
  console.log(message, `(remaining time: ${remainingTime})`)
}

and then use it in index.js:

import {delayedMessage} from './modules/delay.js'

delayedMessage("World", 400).then(()=>{ console.log('done') })
delayedMessage("Hello", 200)

When building with webpack 4, these are my results. With plugin-transform-runtime image

Without plugin-transform-runtime image

So the app size went from 4.29 KiB to 75.8KiB. What is happening? Am I using this wrong?

I could understand if there might be a bit more code added to get the benefit of not affecting the global namespace. I assumed I might only see the benefit of consolidating all the inline helper methods to references to a single runtime module in a much larger app… but adding > 70KiB seems incredibly excessive.

I’m having this issue as well. using libraryTarget: commonjs isn’t an option for us: has anyone come up with a different workaround?

oh wow 😮

So, I was able to fix the issues I was facing by excluding node_modules from webpack modules rules. I thought including a folder would basically result in the same thing, but it seems not!

You can check a working configuration at this repo: https://github.com/Apidcloud/webpack-babel

It uses Webpack and Babel transform-runtime.

This is what I get in exports: module.exports = babel-runtime/helpers/classCallCheck;. No requires, just path. Strange.

@d3viant0ne is this ready in some beta version or is it blocked by something?