Skip to content

Dynamic require() without .js extension breaks bundling (esbuild) #1160

@7PH

Description

@7PH

Node v20
ShellJS 0.8.5

Related issues

Description of the bug

This library can't be bundled with esbuild

Cause

require('./src/' + command);

The combination of dynamic calls to require() and omiting .js extension in require() breaks bundlers. Bundlers can't know whether dynamic imports will include or not the file extension, so some of them (eg esbuild) assume it is included.

If we open the generated bundle, we can see that all required modules are there (src/cat.js, etc) but referenced with their extensions (eg src/cat.js @ L4684)
image

The dynamic require() is included as-is in the bundle (@ L4762):
image

But this fails at runtime with

Error: Module not found in bundle: ./src/cat

Because ./src/cat does not exist, ./src/cat.js does.

How to fix

To fix this, shell.js @ L25 can be modified to add the .js file extension. For consistency, all other calls to require could also use the .js extension in calls to require.

I do not know what solution you prefer @nfischer . Happy to contribute on this if you give me pointers to how you think it should be done.

Workaround

I've made an esbuild plugin to patch shelljs to unblock me as soon as now:

Metadata

Metadata

Assignees

No one assigned

    Labels

    featurefixBug/defect, or a fix for such a problem

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions