9

I think I've read every thread on SO and every related page on the internet on this, everything has some variation of a problem

I want:

  • To use webpack to bundle my web app up
  • To use ES Modules within my source js and have them transpiled down for wider browser support
  • To use ES Modules within my webpack configuration

Node 14 allegedly supports ESM, so lets use that

Setup 1

I have "type": "module" in my package.json

then my webpack.config.js looks something like:


import { somethingUseful } from './src/js/useful-things.js';

export default (env, argv) => {
    return {
        // webpack config here
    };
}

running > webpack (webpack-cli) I get:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: D:\git\Useroo\webpack.config.js
require() of ES modules is not supported.
require() of webpack.config.js from C:\nvm\v14.14.0\node_modules\webpack-cli\lib\groups\resolveConfig.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename webpack.config.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from package.json.

OK, so lets do what the error message says

Setup 2a

If I remove "type": "module" from my package.json I get

webpack.config.js
import { somethingUseful } from './src/js/useful-things.js';
^^^^^^

SyntaxError: Cannot use import statement outside a module

right.... So lets try the other suggested alternative:

Setup 2b

module.exports = async (env, argv) => {

    var somethingUseful = await import('./src/js/useful-things.js');

    return {
        // webpack config here
    };
}

I get a segfault.

/c/Program Files/nodejs/webpack: line 14: 14272 Segmentation fault "$basedir/node" "$basedir/node_modules/webpack/bin/webpack.js" "$@"

Andrew Bullock
  • 36,616
  • 34
  • 155
  • 231
  • 3
    You're running `webpack` through `webpack-cli` code which is not ESM as far as I know, I guess that might be why you can't use ESM in `webpack.config.js`. You should be able to make the first two points with webpack. – Sam Chen Nov 21 '20 at 15:45
  • @chenxsan is there an alternative way I can invoke webpack then? – Andrew Bullock Nov 21 '20 at 16:00
  • https://webpack.js.org/guides/ecma-script-modules/ – Omer Cohen Nov 21 '20 at 16:04
  • @OmerCohen what am I looking at here? Which part solves my problem? – Andrew Bullock Nov 21 '20 at 18:07
  • Why not just use CommonJS in your `webpack.config.js` file? Seems like you're trying to use ESM code from your `src` in webpack configuration. If you must use it, maybe check https://stackoverflow.com/questions/31903692/how-can-i-use-es6-in-webpack-config-js for help. – Sam Chen Nov 22 '20 at 00:35
  • not a solution, because even if he used commonjs in his webpack.config.js file, he may require a module that imports an ES module, so the same error will come again. – Sh eldeeb Sep 12 '21 at 13:29

3 Answers3

11

webpack-cli now supports ES Modules. All that is required is

  • adding "type": "module" to your package.json

or

  • name your webpack config with the mjs extension: webpack.config.mjs
Tate Thurston
  • 4,236
  • 1
  • 26
  • 22
3

At the time of writing, webpack-cli just doesn't support ES6 modules, so you basically have to re-implement it yourself.

It's not that hard really, just annoying. You need something like this (simplified for brevity): Just RTFM here https://webpack.js.org/api/node/

import webpack from 'webpack';
import webpackConfig from './webpack.config.js';


var config = await webpackConfig(mode);
var compiler = webpack(config);

compiler.watch()
halfer
  • 19,824
  • 17
  • 99
  • 186
Andrew Bullock
  • 36,616
  • 34
  • 155
  • 231
1

Webpack does not have native support for ESM config files, as the other answer states, but it does support automatically transpiling them. If your config file is named webpack(.whatever).babel.js, and you have babel properly installed, your config file will be quietly downleveled before use.

As far as I know, the only way to configure Babel in this case is to use a top level .babelrc in your project directory. Mine simply contains {"presets": ["@babel/preset-env"]}. It does mean that if I want to use Babel in the build, I have to configure it through e.g. plugin options, but it works for me.

ETA: user @bendwarn says in a deleted comment that as of Webpack CLI 4.5.0 you can name your config file webpack.config.mjs or just call it webpack.config.js if your package is type: "module" and it should work natively. I haven't tried it (and frankly that second one sounds like a terrible idea).

Coderer
  • 25,844
  • 28
  • 99
  • 154