webpack/webpack-cli

Unexpected token 'export' using webpack.config.babel.js with Webpack CLI v5

yvele opened this issue ยท 17 comments

yvele commented

Describe the bug

The following webpack.config.babel.js works with Webpack CLI v4 but fails with v5:

import config from "./webpack/config"; // <---- exports fails with v5 (works with v4)
import path from "path";

export default {
  entry : "./src/main.js",
  output : {
    path : path.resolve(__dirname, config.dist),
    filename : "main.js"
  }
};

The error:

> webpack-cli-repro-babel@1.0.0 build
> webpack

[webpack-cli] Failed to load '/Users/yves/Projects/OSS/webpack-cli-repro-babel/webpack.config.babel.js' config
[webpack-cli] /Users/yves/Projects/OSS/webpack-cli-repro-babel/webpack/config.js:4
export default {
^^^^^^

SyntaxError: Unexpected token 'export'
    at Object.compileFunction (node:vm:360:18)
    at wrapSafe (node:internal/modules/cjs/loader:1088:15)
    at Module._compile (node:internal/modules/cjs/loader:1123:27)
    at Module._compile (/Users/yves/Projects/OSS/webpack-cli-repro-babel/node_modules/pirates/lib/index.js:136:24)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Object.newLoader [as .js] (/Users/yves/Projects/OSS/webpack-cli-repro-babel/node_modules/pirates/lib/index.js:141:7)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Function.Module._load (node:internal/modules/cjs/loader:878:12)
    at Module.require (node:internal/modules/cjs/loader:1061:19)
    at require (node:internal/modules/cjs/helpers:103:18)

Full repo repo: https://github.com/yvele/webpack-cli-repro-babel

What is the current behavior?

I've created a minimal bug repo repository that works fine with Webpack CLI v4 but fails with v5:
https://github.com/yvele/webpack-cli-repro-babel

To Reproduce

Steps to reproduce the behavior:
https://github.com/yvele/webpack-cli-repro-babel#build

Expected behavior

webpack.config.babel.js should be handled by Babel all the import way down. Same behaviour than Webpack CLI v4.

Screenshots

N/A

Please paste the results of npx webpack-cli info here, and mention other relevant information

Additional context

I'm using Node.js v18.12.1 and the following dependencies:

"devDependencies": {
  "@babel/core": "^7.20.7",
  "@babel/preset-env": "^7.20.2",
  "@babel/register": "^7.18.9",
  "webpack": "^5.75.0",
  "webpack-cli": "^5.0.1"
}

I'll check this.

yvele commented

@snitin315 do you maybe have any idea of a workaround? ๐Ÿค”

Try renaming your config to a .mjs extention

Have you tried naming your config webpack.babel.config.js too?

Same issue. None of the breaking changes seem applicable.

I don't want to start mucking around with .mjs files to fix this - they've given me so many headaches in the past.

Our config name is webpack.config.renderer.dev.babel.js. Is our placement of babel okay, or are there some strict rules about how to name the files for Babel transpilation?

yvele commented

Try renaming your config to a .mjs extention

Webpack cannot find the name

Have you tried naming your config webpack.babel.config.js too?

Hum.. this file name is not supported by Webpack ๐Ÿค” but I still tried and Webpack cannot find it:

Module not found: Error: Can't resolve './src' in '/Users/yves/Projects/OSS/webpack-cli-repro-babel'
resolve './src' in '/Users/yves/Projects/OSS/webpack-cli-repro-babel'
  using description file: /Users/yves/Projects/OSS/webpack-cli-repro-babel/package.json (relative path: .)
    Field 'browser' doesn't contain a valid alias configuration
    using description file: /Users/yves/Projects/OSS/webpack-cli-repro-babel/package.json (relative path: ./src)
      no extension
        Field 'browser' doesn't contain a valid alias configuration
        /Users/yves/Projects/OSS/webpack-cli-repro-babel/src is not a file
      .js
        Field 'browser' doesn't contain a valid alias configuration
        /Users/yves/Projects/OSS/webpack-cli-repro-babel/src.js doesn't exist
      .json
        Field 'browser' doesn't contain a valid alias configuration
        /Users/yves/Projects/OSS/webpack-cli-repro-babel/src.json doesn't exist
      .wasm
        Field 'browser' doesn't contain a valid alias configuration
        /Users/yves/Projects/OSS/webpack-cli-repro-babel/src.wasm doesn't exist
      as directory
        existing directory /Users/yves/Projects/OSS/webpack-cli-repro-babel/src
          using description file: /Users/yves/Projects/OSS/webpack-cli-repro-babel/package.json (relative path: ./src)
            using path: /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index
              using description file: /Users/yves/Projects/OSS/webpack-cli-repro-babel/package.json (relative path: ./src/index)
                no extension
                  Field 'browser' doesn't contain a valid alias configuration
                  /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index doesn't exist
                .js
                  Field 'browser' doesn't contain a valid alias configuration
                  /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index.js doesn't exist
                .json
                  Field 'browser' doesn't contain a valid alias configuration
                  /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index.json doesn't exist
                .wasm
                  Field 'browser' doesn't contain a valid alias configuration
                  /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index.wasm doesn't exist

@evenstensberg are you suggesting me random things? ๐Ÿค” ๐Ÿค“

We recently upgraded interpret to v3 in #3437.

Support .babel.(jsx|tsx) extensions (1e3d0f8)

I believe it's related. I can see this in the CHANGELOG.

yvele commented

We recently upgraded interpret to v3 in #3437.

Support .babel.(jsx|tsx) extensions (1e3d0f8)

I believe it's related. I can see this in the CHANGELOG.

@snitin315 Do we need to make an interpret issue? I don't fully understand why this commit is making Babel not to interpret imported files ๐Ÿค”

Try renaming your config to a .mjs extention

Webpack cannot find the name

Have you tried naming your config webpack.babel.config.js too?

Hum.. this file name is not supported by Webpack ๐Ÿค” but I still tried and Webpack cannot find it:

Module not found: Error: Can't resolve './src' in '/Users/yves/Projects/OSS/webpack-cli-repro-babel'
resolve './src' in '/Users/yves/Projects/OSS/webpack-cli-repro-babel'
  using description file: /Users/yves/Projects/OSS/webpack-cli-repro-babel/package.json (relative path: .)
    Field 'browser' doesn't contain a valid alias configuration
    using description file: /Users/yves/Projects/OSS/webpack-cli-repro-babel/package.json (relative path: ./src)
      no extension
        Field 'browser' doesn't contain a valid alias configuration
        /Users/yves/Projects/OSS/webpack-cli-repro-babel/src is not a file
      .js
        Field 'browser' doesn't contain a valid alias configuration
        /Users/yves/Projects/OSS/webpack-cli-repro-babel/src.js doesn't exist
      .json
        Field 'browser' doesn't contain a valid alias configuration
        /Users/yves/Projects/OSS/webpack-cli-repro-babel/src.json doesn't exist
      .wasm
        Field 'browser' doesn't contain a valid alias configuration
        /Users/yves/Projects/OSS/webpack-cli-repro-babel/src.wasm doesn't exist
      as directory
        existing directory /Users/yves/Projects/OSS/webpack-cli-repro-babel/src
          using description file: /Users/yves/Projects/OSS/webpack-cli-repro-babel/package.json (relative path: ./src)
            using path: /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index
              using description file: /Users/yves/Projects/OSS/webpack-cli-repro-babel/package.json (relative path: ./src/index)
                no extension
                  Field 'browser' doesn't contain a valid alias configuration
                  /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index doesn't exist
                .js
                  Field 'browser' doesn't contain a valid alias configuration
                  /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index.js doesn't exist
                .json
                  Field 'browser' doesn't contain a valid alias configuration
                  /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index.json doesn't exist
                .wasm
                  Field 'browser' doesn't contain a valid alias configuration
                  /Users/yves/Projects/OSS/webpack-cli-repro-babel/src/index.wasm doesn't exist

@evenstensberg are you suggesting me random things? ๐Ÿค” ๐Ÿค“

No, I just wanted to find out if some extentions or prefixes were changed without having to run the repro :D Sorry!

Hey if it's still not solved just change config.js to
module.exports = { dist: "dist", };.

instead of
export default { }
Cause I think Webpack v5 doesn't support exports in config file

Sorry for delay, I think you don't undestand how a register works, if you have webpack.config.babel.js, you need to import config.babel.js, not config.js, because register can't undestand what is ESM and what is non ESM, so don't transpile files, we are using interpret + rechoir under the hood to transpile files.

Why it works before - let's look at changelog of interpret - https://github.com/gulpjs/interpret/releases/tag/v3.0.0

Ensure babel only transforms files that match the full extension

So @babel/register will work only for .babel.js files if your root file has the .babel.js extension.

The question - why it was done by interpret team?

The answer is simple - for performance reasons. Previously, if you had a .babel.js root file extension, all import/require were processed by @babel/register, and if there are many, performance will degrade - remember that babel is not as fast as you want.

So again, the solution is to add the .babel.js extension to all imported files that contain pseudo ESM (or need to be transpiled for any other reason). Sorry, we don't want to restore the previous behavior, and that's only possible if we downgrade our dependecy, and that's not possible because new features are used a lot and this is actually the correct fix because it will potentially increase your speed.

Feel free to feedback, I will peen the issue for other developers

So @babel/register will work only for .babel.js files if your root file has the .babel.js extension.

Is there a typo here? It goes against the rest of your comment and doesn't work.

So this change means we need to make any index.js into index.babel.js? But that can't work without writing out ./common/index.babel everywhere instead. And then every file importing some other file within a directory all need to have it added, and then all the import statements need to be updated.

It's quite a messy mess. I understand the meaningful benefits for some, but for us it's just a lot of work for nothing gained.

It's quite a messy mess. I understand the meaningful benefits for some, but for us it's just a lot of work for nothing gained.

I undestand you, but I don't see any options to disable/configure it (we will provide them if it will be possible), maybe better ask about it interpret developers, because that's just my guess (about perf)

So again, the solution is to add the .babel.js extension to all imported files

Is there a workaround I have complex configuration with many files. Also I'm managing multiple repositories ๐Ÿค”

Were should I open an issue to make something "simple" happen?

I wanted to find a workaround but I never did. I had to rename all of our files. Sorry to be the bearer of bad news.

@yvele Hi, I recently encountered an issue because I'm trying to remove "type": "module" in package.json and it complains that import is not recognizable in my webpack.config.js. Could you help me confirm this is the issue you proposed here?

I'm finding a way to write ESM syntax for webpack.config.js without "type": "module" in package.json.

package.json documentation says the below

When set to "module", the type field allows a package to specify all .js files within are ES modules. If the "type" field is omitted or set to "commonjs", all .js files are treated as CommonJS.

Therefore if "type":"module" is omitted, the webpack build js file will be treated as CommonJS and it does not support export default syntax.

However, as mentioned above, if the webpack build file extension is changed to .mjs, it works. Therefore "type":"module" needs to be provided in package.json