Skip to content

Relax the Webpack plugin's requirement that the package.json's main be exactly ".webpack/main", to support packages with "type": "module" #3230

@waweber

Description

@waweber

Pre-flight checklist

  • I have read the contribution documentation for this project.
  • I agree to follow the code of conduct that this project uses.
  • I have searched the issue tracker for a feature request that matches the one I want to file, without success.

Problem description

The plugin will throw an error if the package.json's "main" field is not exactly ".webpack/main". (Actually, it only checks if it ends with it)

This is because the Webpack plugin outputs the main Electron bundle to .webpack/main/index.js. This causes some problems if you have a package.json of "type": "module":

  1. Electron is started with the package to run provided by path.
  2. Electron imports the given package path using require().
  3. Because require() is given a path instead of a name, Node consults the package.json's "main" property for a script to import.
    • When require() is given a path, it will only consult the "main" field even if "exports" is defined. See the Node docs
  4. Node finds the "main" property is set to ".webpack/main". Because this is a directory, Node will load .webpack/main/index.js.
  5. Because the "type" is "module", all .js files are assumed to be ES modules, and Node throws an error about attempting to require() it (even though the plugin outputs a CJS bundle).

Proposed solution

In a "type": "module" package, all .js files are treated as ES modules, and any CommonJS modules must have a .cjs extension. (The "exports" field lets you explicitly specify these, but this does not get used due to passing a path to require()).

The simplest solution is to ensure the output bundle has a .cjs extension by editing the Webpack config, and explicitly specify "main": ".webpack/main/index.cjs". This fixes the problem, but the plugin throws an error because the entry point isn't the expected value. The plugin would need to be updated to accept /\.webpack\/main(\/index\..js)?$/ as the entry point.

Perhaps a more proper solution would be to allow the user to configure the bundle output/entry point instead of requiring it to be .webpack/main. #2770 suggested this, but didn't have a specific use case.

Alternatives considered

  • It's possible to set up a hook to copy a different package.json or replace the "main" in the output files, but this doesn't seem like a great workaround.
  • It's possible to split the package up into multiple packages, with one just for building the Electron package, but this adds development/configuration overhead, especially if you want to share a common Webpack config for multiple targets/environments.

Additional information

I'm aware Electron doesn't support ES modules, but it doesn't have to. Webpack already turns everything into cjs, we just need to make sure Node knows that.

Metadata

Metadata

Assignees

No one assigned

    Labels

    esmplugin/webpackIssues or pull requests related to first-party webpack plugins/templates

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions