storybook icon indicating copy to clipboard operation
storybook copied to clipboard

[Bug]: SyntaxError: Cannot use import statement outside a module

Open eden-lane opened this issue 1 year ago • 12 comments

Describe the bug

I'm using Storybook in pnpm monorepo and getting a bunch of these errors in console. Tried to upgrade to latest version but it didn't solve the problem.

@storybook/cli v7.3.2

WARN   Failed to load preset: "/Users/eden_lane/Projects/.../node_modules/.pnpm/@[email protected][email protected][email protected][email protected][email protected]/node_modules/@storybook/react-vite/preset"
ERR! /Users/eden_lane/Projects/.../shared/node_modules/lazy-universal-dotenv/lib/index.mjs:1
ERR! import fs from 'fs';
ERR! ^^^^^^
ERR! 
ERR! SyntaxError: Cannot use import statement outside a module
ERR!     at internalCompileFunction (node:internal/vm:73:18)
ERR!     at wrapSafe (node:internal/modules/cjs/loader:1176:20)
ERR!     at Module._compile (node:internal/modules/cjs/loader:1218:27)
ERR!     at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
ERR!     at Object.newLoader [as .mjs] (/Users/eden_lane/Projects/.../node_modules/.pnpm/[email protected][email protected]/node_modules/esbuild-register/dist/node.js:2262:9)
ERR!     at Module.load (node:internal/modules/cjs/loader:1117:32)
ERR!     at Module._load (node:internal/modules/cjs/loader:958:12)
ERR!     at Module.require (node:internal/modules/cjs/loader:1141:19)
ERR!     at require (node:internal/modules/cjs/helpers:110:18)
ERR!     at Object.<anonymous> (/Users/eden_lane/Projects/.../shared/node_modules/@storybook/core-common/dist/index.js:15:4029)

To Reproduce

No response

System

System:
    OS: macOS 13.2.1
    CPU: (8) arm64 Apple M2
  Binaries:
    Node: 18.15.0 - /usr/local/bin/node
    npm: 9.5.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 116.0.5845.110
    Safari: 16.3
  npmPackages:
    @storybook/addon-essentials: ^7.3.2 => 7.3.2 
    @storybook/addon-interactions: ^7.3.2 => 7.3.2 
    @storybook/addon-links: ^7.3.2 => 7.3.2 
    @storybook/addon-mdx-gfm: ^7.3.2 => 7.3.2 
    @storybook/addon-onboarding: ^1.0.8 => 1.0.8 
    @storybook/blocks: ^7.3.2 => 7.3.2 
    @storybook/react: ^7.3.2 => 7.3.2 
    @storybook/react-vite: ^7.3.2 => 7.3.2 
    @storybook/react-webpack5: ^7.3.2 => 7.3.2 
    @storybook/testing-library: ^0.2.0 => 0.2.0 
  npmGlobalPackages:
    @storybook/cli: 4.0.0-alpha.0

Additional context

No response

eden-lane avatar Aug 28 '23 12:08 eden-lane

Hi, @eden-lane. Could you please share a reproduction repo? If not, can you create one (see how to create a repro). The team prioritizes bug reports that have reproduction. Thanks!

raphaelvdossantos avatar Aug 28 '23 13:08 raphaelvdossantos

Thanks for the quick answer! Unfortunately I don't think it is possible. It's a monorepo with a lot of deps. I'm pretty sure that on a new project it's gonna work out of the box.

eden-lane avatar Aug 28 '23 13:08 eden-lane

I also experience this error:

@storybook/cli v7.4.0

info => Cleaning outputDir: /storybook-static
./node_modules/@nuxt/kit/dist/index.mjs:1
import { promises, existsSync, readFileSync, lstatSync } from 'node:fs';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:360:18)
    at wrapSafe (node:internal/modules/cjs/loader:1126:15)
    at Module._compile (node:internal/modules/cjs/loader:1162:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1252:10)
    at Object.newLoader [as .mjs] (./node_modules/esbuild-register/dist/node.js:2262:9)
    at Module.load (node:internal/modules/cjs/loader:1076:32)
    at Function.Module._load (node:internal/modules/cjs/loader:911:12)
    at Module.require (node:internal/modules/cjs/loader:1100:19)
    at require (node:internal/modules/cjs/helpers:119:18)
    at Object.<anonymous> (./.storybook/main.ts:1:49)

For a reproduction, upgrading storybook from 7.0.26 to 7.4 in https://github.com/JabRef/JabRefOnline/pull/2208 is displaying this issue for me (just run yarn storybook:build). I know its not a 'minimal reproduction' but hopefully its helpful.

tobiasdiez avatar Sep 03 '23 07:09 tobiasdiez

Still present in 7.4.2., see https://github.com/JabRef/JabRefOnline/pull/2231.


Update: also in 7.4.5, see https://github.com/JabRef/JabRefOnline/pull/2249.

tobiasdiez avatar Sep 15 '23 15:09 tobiasdiez

Getting the same error with @storybook/addon-storysource:

Failed to load preset: {"name":"/.../proj/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected][email protected][email protected]/node_modules/@storybook/addon-storysource/preset.js"} on level 2
/.../proj/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected][email protected][email protected]/node_modules/@storybook/addon-storysource/preset.js:1
import './dist/preset';
^^^^^^

SyntaxError: Cannot use import statement outside a module

unional avatar Oct 06 '23 20:10 unional

Hi there! Thank you for opening this issue, but it has been marked as stale because we need more information to move forward. Could you please provide us with the requested reproduction or additional information that could help us better understand the problem? We'd love to resolve this issue, but we can't do it without your help!

github-actions[bot] avatar Oct 28 '23 01:10 github-actions[bot]

@vanessayuenn A reproduction is for example given by the upgrade PR https://github.com/JabRef/JabRefOnline/pull/2249. Let me know if you need any other information.

tobiasdiez avatar Oct 28 '23 02:10 tobiasdiez

@tobiasdiez I'm trying to investigate this, but I'm running into trouble understanding the repro. As the branch referenced has been deleted, I decided to try the main branch instead.

First, I'm assessing if the storybook works as-is, which is isn't? I ran yarn storybook and it exited because an improper flag is passed:

error: unknown option '--no-manager-cache'

When I remove this from package.json, storybook does start, but is trying to load an custom iframe. It seems you've set up a custom iframe, for which I need to run something else? The storybook opened, but the canvas kept loading...

I tried running npx storybook@latest upgrade and I did get the error:

(main)⚡ % nr storybook                                                                                                                                                                         ~/Projects/Storybook/repros/JabRefOnline
@storybook/cli v7.6.15

./node_modules/@nuxt/kit/dist/index.mjs:1
import { promises, existsSync, readFileSync, lstatSync } from 'node:fs';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:73:18)
    at wrapSafe (node:internal/modules/cjs/loader:1149:20)
    at Module._compile (node:internal/modules/cjs/loader:1190:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1280:10)
    at Object.newLoader [as .mjs] (./node_modules/esbuild-register/dist/node.js:2262:9)
    at Module.load (node:internal/modules/cjs/loader:1089:32)
    at Module._load (node:internal/modules/cjs/loader:930:12)
    at Module.require (node:internal/modules/cjs/loader:1113:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at Object.<anonymous> (./.storybook/main.ts:1:49)

WARN Broken build, fix the error above.

I think it's esbuild-register related and the fact that '@nuxt/kit' is ESM only. It doesn't have any CJS files in it's dist.

But then that package says there's a require-version (CJS) version available, but it's the ESM file. Screenshot 2024-02-14 at 13 52 44

I've tried manually editing the package.json file of the problematic module, but couldn't make it work.

Thn I tried changing the extention to .js (because that's what it should be, considering the package.json's type field is set to module, and it accepted it, but now I am confronted with the next-in-line problem.

(main)⚡ [1] % nr storybook                                                                                                                                                                     ~/Projects/Storybook/repros/JabRefOnline
@storybook/cli v7.6.15

./node_modules/@nuxt/schema/dist/index.mjs:1
import { defineUntypedSchema } from 'untyped';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:73:18)
    at wrapSafe (node:internal/modules/cjs/loader:1149:20)
    at Module._compile (node:internal/modules/cjs/loader:1190:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1280:10)
    at Object.newLoader [as .mjs] (./node_modules/esbuild-register/dist/node.js:2262:9)
    at Module.load (node:internal/modules/cjs/loader:1089:32)
    at Module._load (node:internal/modules/cjs/loader:930:12)
    at Module.require (node:internal/modules/cjs/loader:1113:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at Object.<anonymous> (./node_modules/@nuxt/kit/dist/index.js:17:34)

WARN Broken build, fix the error above.

ndelangen avatar Feb 14 '24 13:02 ndelangen

@ndelangen Thanks for testing it. I am currently on the road, so only a quick response now.

The latest upgrade PR is https://github.com/JabRef/JabRefOnline/pull/2332, but it fails already at the Build step. My setup is indeed a bit involved as I want to render the stories using the nuxt pipeline. So you have to first run yarn dev and then in parallel start the storybook. Sorry, should have provided more details in the first place.

Cannot say much about the require statement in nuxt/kit's package.json. Maybe @pi0 or @danielroe can shine some light on it.

tobiasdiez avatar Feb 14 '24 13:02 tobiasdiez

I found a fix @tobiasdiez

please change the declarative import of @nuxt/kit to an impaerative import where it's needed:

await import('@nuxt/kit')

I got it working with:

// https://github.com/nuxt/nuxt/issues/14534
// From: https://github.com/danielroe/nuxt-vitest/blob/main/packages/nuxt-vitest/src/config.ts
async function startNuxtAndGetViteConfig(rootDir = process.cwd()) {
  const { buildNuxt, loadNuxt, tryUseNuxt } = await import('@nuxt/kit'); // <<<-----

  let nuxt = tryUseNuxt()
  let nuxtAlreadyRunnnig = true
  if (!nuxt) {
    nuxtAlreadyRunnnig = false
    nuxt = await loadNuxt({

ndelangen avatar Feb 14 '24 13:02 ndelangen

I think this PR caused a regression: https://github.com/storybookjs/storybook/pull/23018/files

I'll talk to the team to see what option we have to remedy this.

ndelangen avatar Feb 14 '24 13:02 ndelangen

User will now get a MainFileESMOnlyImportError error in their terminal.

Here's an contrived example of what users will need to do when they are faced with this error:

// main.ts
- import { something } from "@scope/an-esm-only-package";
import type { StorybookConfig } from "@storybook/react-vite";

const config: StorybookConfig = {
  stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],

  addons: ["@storybook/addon-essentials"],

  framework: {
    name: "@storybook/react-vite",
    options: {},
  },

  docs: {
    autodocs: "tag",
  },

-  viteFinal: (config) => ({
+  viteFinal: async (config) => ({
    ...config,
-    ...something,
+    ...(await import('@scope/an-esm-only-package')).something,
  }),
};

export default config;

Note the:

  • removal of the static import at the top of the file.
  • conversion to async function of the config property in main.ts.
  • use of await and the dynamic import inside of the config property.

See highlighted before and after

Before:

// main.ts
import { something } from "@scope/an-esm-only-package";
import type { StorybookConfig } from "@storybook/react-vite";

const config: StorybookConfig = {
  stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],

  addons: ["@storybook/addon-essentials"],

  framework: {
    name: "@storybook/react-vite",
    options: {},
  },

  docs: {
    autodocs: "tag",
  },

  viteFinal: (config) => ({
    ...config,
    ...something,
  }),
};

export default config;

After:

// main.ts
import type { StorybookConfig } from "@storybook/react-vite";

const config: StorybookConfig = {
  stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],

  addons: ["@storybook/addon-essentials"],

  framework: {
    name: "@storybook/react-vite",
    options: {},
  },

  docs: {
    autodocs: "tag",
  },

  viteFinal: async (config) => ({
    ...config,
    ...(await import('@scope/an-esm-only-package')).something,
  }),
};

export default config;

Why does this happen?

Storybook used to convert all code loaded by node to CJS via https://github.com/egoist/esbuild-register. During 7.x it was discovered that this process took valuable time when storybook started.

In a performance improving PR: https://github.com/storybookjs/storybook/pull/23018 this was changed to exclude node_modules from being converted. However this introduced a breaking change, unbeknownst to the storybook core team. After this change, esbuild-register converts the static import to require, but leaves the referenced module as-is. This is fine, when the module supports both (it's either ESM+CJS, or only CJS). But when it's ESM only, this presents node with a problem: It tried to require() a ESM module. This is not allowed, and so node throws.

ndelangen avatar Feb 16 '24 14:02 ndelangen

@ndelangen It took me a bit longer than expected, but I finally was able to test your solution and can happily report that it worked like a charm! Thanks a lot for the time and effort you put into discovering the root issue and providing a fix. Very much appreciated!

tobiasdiez avatar Mar 07 '24 15:03 tobiasdiez