question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

CRA5 Bug: `require` a submodule of a package (i.e. `my-package/sub-module`) returns a string instead of the module

See original GitHub issue

Describe the bug

Doing require('something/something-else') returns a string — what looks like the path to the bundle file with the lib — instead of returning the actual module that can be used in code. Specifically, the issue was observed with require('nanoid/non-secure').

Using import * as nano from 'nanoid/non-secure' works correctly but require('nanoid/non-secure') doesn’t. Big part of the issue is that if it’s a dependency of your project that’s using it with require, you have no control on your app to change the syntax to import instead of require to workaround this issue.

Using vanilla Webpack 5 works correctly (outside of react-scripts). Downgrading to react-scripts@^4 also makes it all work correctly. My guess is that it’s something in the react-scripts@5 Webpack configuration.

Did you try recovering your dependencies?

No issues with the module tree. Issue is reproducible on a freshly created react-app. It even happens across different yarn setups with versions 1.22.17 and 3.1.0.

$ yarn --version
1.22.17

$ yarn --version
3.1.0

Which terms did you search for in User Guide?

“submodules”, “require”, “require submodule”

Environment

$ yarn create react-app --info
yarn create v1.22.17
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Installed "create-react-app@5.0.0" with binaries:
      - create-react-app

Environment Info:

  current version of create-react-app: 5.0.0
  running from /Users/rart/.config/yarn/global/node_modules/create-react-app

  System:
    OS: macOS 12.1
    CPU: (12) x64 Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz
  Binaries:
    Node: 16.13.0 - /var/folders/5g/4p2kn0ks3x7fj848t3cvt4rw0000gn/T/yarn--1641400000423-0.5498156139928032/node
    Yarn: 1.22.17 - /var/folders/5g/4p2kn0ks3x7fj848t3cvt4rw0000gn/T/yarn--1641400000423-0.5498156139928032/yarn
    npm: 8.1.4 - ~/.nvm/versions/node/v16.13.0/bin/npm
  Browsers:
    Chrome: 97.0.4692.71
    Edge: Not Found
    Firefox: 89.0.2
    Safari: 15.2
  npmPackages:
    react: 17.0.2
    react-dom: 17.0.2
    react-scripts: 5.0.0
  npmGlobalPackages:
    create-react-app: Not Found

✨  Done in 2.29s.

Steps to reproduce

  1. yarn add nanoid
  2. const nano = require('nanoid/non-secure')
  3. Inspect the value of const nano; it should be a module with two functions (nanoid and customAlphabet), but instead is a path that looks like /static/media/index.617173a3029a82877c86.cjs
    • If you — or most importantly a dependency of your project — uses nanoid (e.g. const { nanoid } = require('nanoid/non-secure')), nanoid will be undefined and cause a runtime exception when it’s accessed.

Expected behavior

require('something/something-else') should return the module, an object with whatever is exported, not a string path to a file.

For example require('nanoid/non-secure'), should return { nanoid: ƒ nanoid(), customAlphabet: ƒ customAlphabet() }

Actual behavior

The require('something/something-else') statement returns a string with what looks like the path to the bundle file that contains the lib instead of returning the actual module that can be invoked in code.

Using import * as nano from 'nanoid/non-secure' works correctly but require('nanoid/non-secure') doesn’t. Big part of the issue is that if it’s a dependency of your project that’s using it with require, you have no control on your app to change the syntax to import instead of require to workaround this issue.

Using vanilla Webpack 5 works correctly (no react-scripts involved). Downgrading to react-scripts@^4 also makes it all work correctly. My guess is that it’s something in the react-scripts@5 Webpack configuration.

Reproducible demo

I’m attaching 3 things:

  1. An app created using yarn create react-app that shows the issue: react-scripts-5-issue.zip
  2. A codesandbox download that shows the issue: react-scripts-5-issue-submodules-codesandbox.zip. The code example ran in codesandbox actually works correctly, but if you download it straight from codesandbox, install it (i.e. yarn/npm install), and run the react scripts the bug is reproduced. I don’t think code sandbox actually runs react scripts and that’s why it works. In the same way that trying the same thing on a vanilla Webpack setup works. Or downgrading the app to react-script@^4 works too.
  3. A plain vanilla Webpack setup that shows that it’s not a Webpack issue per se: react-scripts-5-issue-vanilla-webpack.zip

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:12
  • Comments:9

github_iconTop GitHub Comments

4reactions
gdethiercommented, May 2, 2022

In the very short term, a workaround is to use craco in order to add the exclusion. Your craco.config.js file would then look like this:

module.exports = {
    webpack: {
        configure: (config) => {
            // ...
            const fileLoaderRule = getFileLoaderRule(config.module.rules);
            if(!fileLoaderRule) {
                throw new Error("File loader not found");
            }
            fileLoaderRule.exclude.push(/\.cjs$/);
            // ...
	    return config;
        }
    }
};

function getFileLoaderRule(rules) {
    for(const rule of rules) {
        if("oneOf" in rule) {
            const found = getFileLoaderRule(rule.oneOf);
            if(found) {
                return found;
            }
        } else if(rule.test === undefined && rule.type === 'asset/resource') {
            return rule;
        }
    }
}
2reactions
zzmingocommented, Jan 18, 2022

I also have this issue, any workaround for this?

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to git submodule update ONLY on submodules that need ...
Create a script that uses git status to get the submodules to update and then calls git submodule update with the list of...
Read more >
git-submodule Documentation - Git
If --recursive is given, submodules are traversed recursively (i.e. the given shell command is evaluated in nested submodules as well). A non-zero return...
Read more >
Traps for the Unwary in Python's Import System
The submodules are added to the package namespace trap​​ If the submodule is loaded by any module at any point after the import...
Read more >
Importing Modules — Python 3.11.1 documentation
Like for __import__() , the return value when a submodule of a package was requested ... but the name is a UTF-8 encoded...
Read more >
flax.error package - Read the Docs
In general you shouldn't call .setup() yourself, if you need to get access to a field or submodule defined inside setup you can...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found