cdaringe
cdaringe

Reputation: 1538

Why is my webpack babel setup emitting ESM requires when I have configured my preset to commonjs?

Today I observed babel/babel-loader exhibiting some undesirable behavior. I am bundling some assets for usage on nodejs. Post-compile, a bundle is generated with references to @babel/runtime/**/esm/**. Of course, node cannot import such files, and on node bundle.js I get:

Must use import to load ES Module: /my/project/node_modules/@babel/runtime/helpers/esm/defineProperty.js
require() of ES modules is not supported.

Right. Makes sense. But babel-loader injected those imports. In fact, the parent folder in @babel/runtime has all of the non-ESM things, which I actually probably do want imported! My babel config looks as such:

{
  presets: [
    [
      "@babel/preset-env",
      {
        modules: 'commonjs',
        targets: {
          node: "current",
          esmodules: false,
        },
      },
    ],
    "@babel/preset-typescript",
  ]
}

As you can see, I'm attempting to tell babel via targets.esmodules: false and modules: 'commonjs' to use commonjs. I hoped these entries would tell babel to not expect ESM compatibility! None the less, generated bundles still look like:

...
var _toConsumableArray2 = _interopRequireDefault(__webpack_require__(/*! @babel/runtime/helpers/esm/toConsumableArray */ "@babel/runtime/helpers/esm/toConsumableArray"));

My full webpack config is pretty terse as well:

{
    entry: serverFilename,
    mode: 'development',
    output: {
      path: path.dirname(serverBuildFilename),
      filename: path.basename(serverBuildFilename)
    },
    target: "node",
    externals: [webpackNodeExternals()],
    optimization: {
      moduleIds: 'named',
      minimize: false
    },
    resolve: {
      extensions: ['.ts', '.tsx', '.wasm', '.mjs', '.js', '.json'],
    },
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: babelConfig.presets // see babel config above
            }
          }
        },
      ],
    },
  }

I can't tell if I'm missing configuration, if babel isn't respecting my configuration, or <your ideas here>!

All tips appreciated. Thanks!

Upvotes: 4

Views: 2471

Answers (1)

user15779293
user15779293

Reputation: 21

It took me a while to figure out the solution and this post helps https://github.com/webpack/webpack/issues/11696

Copied my solution from the issue here:

I ended up using webpack-node-externals in webpack config to sort of bypass this issue

const nodeExternals = require('webpack-node-externals');

// add these to the webpack config.
    externals: [
          nodeExternals({
            whitelist: [/^@babel\/runtime/],
          }),
     ],

This solution creates duplicated babel/runtime file injections and can also be mitigated by https://webpack.js.org/loaders/babel-loader/#babel-is-injecting-helpers-into-each-file-and-bloating-my-code

Upvotes: 2

Related Questions