Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webpack5 + type: module = require is not defined #14877

Closed
arty-name opened this issue May 10, 2021 · 52 comments
Closed

Webpack5 + type: module = require is not defined #14877

arty-name opened this issue May 10, 2021 · 52 comments

Comments

@arty-name
Copy link
Contributor

arty-name commented May 10, 2021

Describe the bug
A barebones example with type: module and Webpack5 results in "require is not defined" error in browser:

Uncaught ReferenceError: require is not defined
    js generated-stories-entry.js:3
    Webpack 7
        __webpack_require__
        __webpack_exec__
        <anonymous>
        O
        <anonymous>
        webpackJsonpCallback
        <anonymous>

To Reproduce

git clone git@github.com:arty-name/storybook-webpack5-module.git && yarn install && npx start-storybook

Alternatively these simple steps:

  1. Create package.json containing { "type": "module" }
  2. yarn add react react-dom
  3. yarn add --dev @storybook/react @storybook/builder-webpack5 @storybook/manager-webpack5
  4. Create .storybook/main.cjs containing module.exports = { core: { builder: 'webpack5' }, stories: ['../test.stories.js'] }
  5. Create test.stories.js containing:
export default { title: 'Story' }
export function Story() {
  return 'Pass!'
}
  1. npx start-storybook

System

Environment Info:

  System:
    OS: Linux 5.8 Ubuntu 21.04 (Hirsute Hippo)
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
  Binaries:
    Node: 16.3.0 - /usr/bin/node
    Yarn: 1.22.5 - /usr/bin/yarn
    npm: 7.15.1 - /usr/bin/npm
  Browsers:
    Chrome: 91.0.4472.114
    Firefox: 89.0.1
  npmPackages:
    @storybook/builder-webpack5: ^6.3.0 => 6.3.0 
    @storybook/manager-webpack5: ^6.3.0 => 6.3.0 
    @storybook/react: ^6.3.0 => 6.3.0 
@shilman
Copy link
Member

shilman commented May 10, 2021

Do you have a repro repo you can share?

arty-name added a commit to arty-name/storybook-webpack5-module that referenced this issue May 10, 2021
@arty-name
Copy link
Contributor Author

Sure, I can create it: https://github.com/arty-name/storybook-webpack5-module

@arty-name
Copy link
Contributor Author

Confirmed the issue with storybook@6.3.0

@shilman shilman added this to the 6.3 stabilization milestone Jun 23, 2021
@arty-name
Copy link
Contributor Author

Confirmed the issue with storybook@6.3.1

@dimfeld
Copy link

dimfeld commented Jul 18, 2021

I looked into this a bit, and it's a bit weird since the file as checked in to Git actually does use the import syntax. But it gets transpiled to CommonJS format in the cjs build of storybook, which I suppose is being used because we currently have to use .storybook/main.cjs instead of just .storybook/main.js.

Not quite sure what the proper solution is for this. One possibility is to maintain two copies of virtualModuleStory.template.js, one for CJS and one for ESM, and then keeping them from being processed during the build, would work. Then the template code could use packageJson.type to determine which template to use. There might be a better solution though that lets webpack convert the template or something. Or probably best would be if Node would just run the ESM build of storybook.

EDIT: Actually it's more complicated than this since the template files also reference module and are populated with code that uses require.context. In the end, I found it worked to create a .storybook/package.json file with the contents just {}, nothing else. This seems to put webpack in a mode where it's tolerant of both ES6 import/export and CommonJS require.

@arty-name
Copy link
Contributor Author

The .storybook/package.json workaround works indeed, thanks!

@jpzwarte
Copy link
Member

I can confirm that the workaround does not work for me.

@jpzwarte
Copy link
Member

I've updated the example repo from above and updated the packages to 6.4.0-beta.33 and added the empty package.json, but I still get the require is undefined error. cc @shilman

@shilman shilman added linear and removed linear labels Nov 17, 2021
@tmeasday
Copy link
Member

@jpzwarte I think the reason that the .storybook/package.json solution doesn't work any more in 6.4 is because we "moved" the location of the virtual module created by the file referenced in @dimfeld's comment to the root of the project, rather than the .storybook directory.

Let me see if I understand this issue correctly:

  1. If you specify your project as { "type": "module" }, webpack doesn't want to see require() any more
  2. The entry point(s) we create on your behalf as SB (generated from virtualModuleStory.template.js, which was compiled to CJS) makes use of require()
  3. In 6.3, as that file was "put" in ./.storybook, if you put a package.json in there declaring a non "module" package, WP is happy again.

I wonder if there is an alternate way to tell WP that the bundle we are create is (to begin with at least) CJS, not ESM, so it doesn't look in ./package.json:type to figure that out?

We would like to properly sort out this ESM/CJS business in 6.5 so it is possible to actually just use ESM everywhere.

@arty-name
Copy link
Contributor Author

It works! Thank you very much for fixing it! 🙇

@benjambles
Copy link

Thanks @shilman!

@tmeasday
Copy link
Member

Thanks to @jpzwarte for the fix here!

@benbender
Copy link
Contributor

As this pr is reverted in #17361, this should be reopenend, @shilman?

@shilman shilman reopened this Jan 29, 2022
@shilman
Copy link
Member

shilman commented Jan 29, 2022

Good call @benbender -- hopefully we can get a fix that doesn't break CRA this week

@benbender
Copy link
Contributor

That would be wonderful news as I simply pinned "@storybook/builder-webpack5": "6.5.0-alpha.25", for now as I needed a working setup ;)

@tmeasday
Copy link
Member

tmeasday commented Feb 2, 2022

For those following along, the fix in the CRA preset is here: storybookjs/presets#229

@shilman
Copy link
Member

shilman commented Feb 10, 2022

Released as @storybook/preset-create-react-app@4.0.1 if somebody can please test it out @benbender @tmeasday

@benbender
Copy link
Contributor

@shilman I don't use cra but sveltekit, sorry

@mynormh
Copy link

mynormh commented Mar 31, 2022

Hi! I ran into this issue and none of the workarounds worked for me so I tried npx sb upgrade --prerelease but I'm still seeing the same error whenever I try to add a webpack plugin in main.js

ReferenceError: require is not defined
    at Object.regenerator-runtime/runtime (main.iframe.bundle.js:2217:1)
    at __webpack_require__ (runtime~main.iframe.bundle.js:854:30)

@shilman shilman removed this from the 6.4 improvements milestone May 20, 2022
@arty-name
Copy link
Contributor Author

This doesn’t seem to be an issue in 6.5.4 anymore 👍 Thank you for fixing it!

@dgattey
Copy link

dgattey commented Dec 21, 2022

Still seeing this as an issue in 6.5.15 with storyStoreV7 true 😕 with build-storybook

@nickbullock
Copy link
Contributor

nickbullock commented Feb 9, 2023

@arty-name @shilman hey, could you please reopen it since it's still actual with storyStoreV7 flag?

@arty-name
Copy link
Contributor Author

Hey folks, in my experience, the developers pay more attention to new issues rather than to ones reopened with additions. Since I haven’t used the storyStoreV7 myself and have no more details about what you’re seeing, I recommend creating a new issue with the minimal reproduction case. Of course, feel free to link it to this one. I am not a developer of storybook myself, I’m just a user of it, like you.

@tmeasday
Copy link
Member

Also, could you try with SB7 please? This stuff has changed a lot and we are close to release.

@arty-name
Copy link
Contributor Author

@tmeasday Thank you for checking! My projects seem to run fine with the SB7 prerelease, and I even could remove the workarounds. Well done!

ganezasan added a commit to ganezasan/hello-jest-cra-template that referenced this issue Feb 15, 2023
error message
```
ModuleParseError: Module parse failed: 'import' and 'export' may appear only with 'sourceType: module'
```

issues
- storybookjs/storybook#15335
- storybookjs/storybook#14877
ganezasan added a commit to ganezasan/hello-jest-cra-template that referenced this issue Feb 15, 2023
* use webpack5 and type: module

* uninstall tsconfig-paths-webpack-plugin

* fix webpackFinal:

* fix ModuleParseError

error message
```
ModuleParseError: Module parse failed: 'import' and 'export' may appear only with 'sourceType: module'
```

issues
- storybookjs/storybook#15335
- storybookjs/storybook#14877

* revert preview.ts
hyochan added a commit to dooboolab-community/dooboo-ui that referenced this issue Apr 22, 2023
@makcbrain
Copy link

I have solved problem by adding virtual package.json file in .storybook/main.cjs:

const VirtualModulesPlugin = require('webpack-virtual-modules');

const pathPackageJson = path.join(__dirname, '../package.json');

const virtualModules = new VirtualModulesPlugin({
  [pathPackageJson]: JSON.stringify({
    "name": "someName",
  }),
});

and add this plugin to the webpackFinal property:

module.exports = {
  webpackFinal: config => {

    config.plugins.push(
      virtualModules,
    );

    return config;
  }
}

It's the workaround for solving problem with type: "module" in our package.json
Storybook adds virtual module "storybook-config-entry.js" in the root of our project,
then Webpack loads it as module and reads our package.json and think that
storybook-config-entry.js is a es module and doesn't make some transformation over code like
require. In result, stories fall with error "unknown require function".
Here we add a virtual package.json file which doesn't contain prop "type".

@valentinpalkovic
Copy link
Contributor

@tmeasday Couldn't we change the content of the virtual files to use dynamic imports instead, which are supported in ESM and CommonJS environments?

@tmeasday
Copy link
Member

tmeasday commented Nov 22, 2023

@valentinpalkovic, naively yes. I don't see any reason that:

const getProjectAnnotations = () =>
composeConfigs([{{#each previewAnnotations}}require('{{this}}'),{{/each}}]);

Couldn't be changed to

const getProjectAnnotations = async () =>
  composeConfigs(await Promise.all([{{#each previewAnnotations}}import('{{this}}'),{{/each}}]));

(This is very close to the generated code in Vite, btw:

const getPreviewAnnotationsFunction = `
const getProjectAnnotations = async () => {
const configs = await Promise.all([${previewAnnotationURLs
.map((previewAnnotation) => `import('${previewAnnotation}')`)
.join(',\n')}])
return composeConfigs(configs);
}`;
)

This issue is closed though. What is the circumstance that cause it to happen again?

Very happy to look at it again together if you like.

@valentinpalkovic
Copy link
Contributor

@tmeasday I created a PR last year in July to partially fix this issue, but it was never merged: #18620. I will do some quick testing in the afternoon to determine whether this is still a thing.

@tmeasday
Copy link
Member

Seems like a step forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests