Storybook: Custom addon not working on Windows.

Created on 1 Mar 2020  路  4Comments  路  Source: storybookjs/storybook

Describe the bug
I have a custom addon loaded from my main.js file. This works fine on Mac but fails on Windows with "Cannot use import statement outside a module". Looking at @storybook\core\dist\server\presets.js, it's probably node related rather than storybook but I wanted to check here first.

$ npm start

> [email protected] start C:\Users\IEUser\carbon
> start-storybook -p 9001 -s .assets -c .storybook

info @storybook/react v5.3.4
info
info => Loading static files from: C:\Users\IEUser\carbon\.assets .
info => Loading presets
WARN   Failed to load preset: "C:\\Users\\IEUser\\carbon\\.storybook\\theme-selector\\register" on level 1
ERR! C:\Users\IEUser\carbon\.storybook\theme-selector\register.js:1
ERR! import React, { memo, useState } from 'react';
ERR! ^^^^^^
ERR!
ERR! SyntaxError: Cannot use import statement outside a module
ERR!     at wrapSafe (internal/modules/cjs/loader.js:1072:16)
ERR!     at Module._compile (internal/modules/cjs/loader.js:1122:27)
ERR!     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)
ERR!     at Module.load (internal/modules/cjs/loader.js:1002:32)
ERR!     at Function.Module._load (internal/modules/cjs/loader.js:901:14)
ERR!     at Module.require (internal/modules/cjs/loader.js:1044:19)
ERR!     at require (internal/modules/cjs/helpers.js:77:18)
ERR!     at interopRequireDefault (C:\Users\IEUser\carbon\node_modules\@storybook\core\dist\server\presets.js:164:18)
ERR!     at loadPreset (C:\Users\IEUser\carbon\node_modules\@storybook\core\dist\server\presets.js:174:22)
ERR!     at C:\Users\IEUser\carbon\node_modules\@storybook\core\dist\server\presets.js:230:20
ERR!     at Array.reduce (<anonymous>)
ERR!     at loadPresets (C:\Users\IEUser\carbon\node_modules\@storybook\core\dist\server\presets.js:229:18)
ERR!     at loadPreset (C:\Users\IEUser\carbon\node_modules\@storybook\core\dist\server\presets.js:194:18)
ERR!     at C:\Users\IEUser\carbon\node_modules\@storybook\core\dist\server\presets.js:230:20
ERR!     at Array.reduce (<anonymous>)
ERR!     at loadPresets (C:\Users\IEUser\carbon\node_modules\@storybook\core\dist\server\presets.js:229:18)
ERR!  C:\Users\IEUser\carbon\.storybook\theme-selector\register.js:1
const path = require('path');

module.exports = {
  stories: ['../src/**/*.stories.(js|mdx)', './welcome-page/welcome.stories.js'],
  addons: [
    '@storybook/addon-actions/register',
    '@storybook/addon-knobs/register',
    '@storybook/addon-notes/register',
    '@storybook/addon-viewport/register',
    '@storybook/addon-a11y/register',
    '@storybook/addon-docs',
    '@storybook/addon-google-analytics/register',
    path.resolve(__dirname, 'theme-selector/register'),
  ],
  webpackFinal: async (config, { configType }) => {
    debugger;
    config.module.rules.push(
      {
        test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader']
      }
    );
    config.resolve = {
      alias: {
        helpers: path.resolve(__dirname, '__helpers__/')
      },
      extensions: ['.js']
    };
    return config;
  },
};

To Reproduce
Steps to reproduce the behavior:

  1. On Windows 10 system with node
  2. git clone [email protected]:Sage/carbon.git
  3. git checkout v13.6.0
  4. npm start

Expected behavior
The plugin should load successfully.

System:

Environment Info:

  System:
    OS: Windows 10 10.0.17763
    CPU: (2) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
  Binaries:
    Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
    npm: 6.13.6 - ~\carbon\node_modules\.bin\npm.CMD
  Browsers:
    Edge: 44.17763.831.0

Additional context
https://github.com/storybookjs/storybook/blob/7c55dd1dae076019e954041f99e5b4164cd84132/lib/core/src/server/presets.js#L123
It works fine on Mac

Environment Info:

  System:
    OS: macOS Mojave 10.14.6
    CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
  Binaries:
    Node: 12.16.1 - ~/.nvm/versions/node/v12.16.1/bin/node
    npm: 6.13.6 - ~/carbon/node_modules/.bin/npm
  Browsers:
    Chrome: 80.0.3987.122
    Firefox: 69.0.1
    Safari: 13.0.1
bug compatibility with other tools configuration

Most helpful comment

@jamime

TL;DR
Change your path.resolve(__dirname, 'theme-selector/register') to path.resolve(__dirname, 'theme-selector'). It will work only on win32 platforms.

Explanation
The problem, is that your addon determined by storybook as preset, that required on server side, but should as managerEntries, that required in runtime in browser. This resolve is going in resolveAddonName function

export const resolveAddonName = name => {
  let path;
  if (isLocalFileImport(name)) {
    path = name;
  } else {
    ({ path } = parsePackageName(name));
  }

  // when user provides full path, we don't need to do anything
  if (path) {
    return {
      name,
      // Accept `register`, `register.js`, `require.resolve('foo/register'), `register_panel`
      type: path.match(/register(_panel)?(.js)?$/) ? 'managerEntries' : 'presets',
    };
  }

  try {
    return {
      name: resolveFile(join(name, 'preset')),
      type: 'presets',
    };
    // eslint-disable-next-line no-empty
  } catch (err) {}

  try {
    return {
      name: resolveFile(join(name, 'register')),
      type: 'managerEntries',
    };
    // eslint-disable-next-line no-empty
  } catch (err) {}

  return { name, type: 'presets' };
};

Platform error is here:

const isLocalFileImport = packageName => /^[./]/.test(packageName);

Because Unix path starts with /path/to/package, but Windows path starts with disk's name - C:/path/to/package.

So resolveAddonName thinks, that our local package is not local, and tries to resolve register.js or preset.js in directory theme-selector/register. It can't find, and by default returns our custom addon as preset type, that will require on server side without transpiling. And we catch error SyntaxError: Cannot use import statement outside a module.

All 4 comments

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

@jamime - did you ever resolve this? I'm also getting the "cannot use import statement outside module" error.

@jamime

TL;DR
Change your path.resolve(__dirname, 'theme-selector/register') to path.resolve(__dirname, 'theme-selector'). It will work only on win32 platforms.

Explanation
The problem, is that your addon determined by storybook as preset, that required on server side, but should as managerEntries, that required in runtime in browser. This resolve is going in resolveAddonName function

export const resolveAddonName = name => {
  let path;
  if (isLocalFileImport(name)) {
    path = name;
  } else {
    ({ path } = parsePackageName(name));
  }

  // when user provides full path, we don't need to do anything
  if (path) {
    return {
      name,
      // Accept `register`, `register.js`, `require.resolve('foo/register'), `register_panel`
      type: path.match(/register(_panel)?(.js)?$/) ? 'managerEntries' : 'presets',
    };
  }

  try {
    return {
      name: resolveFile(join(name, 'preset')),
      type: 'presets',
    };
    // eslint-disable-next-line no-empty
  } catch (err) {}

  try {
    return {
      name: resolveFile(join(name, 'register')),
      type: 'managerEntries',
    };
    // eslint-disable-next-line no-empty
  } catch (err) {}

  return { name, type: 'presets' };
};

Platform error is here:

const isLocalFileImport = packageName => /^[./]/.test(packageName);

Because Unix path starts with /path/to/package, but Windows path starts with disk's name - C:/path/to/package.

So resolveAddonName thinks, that our local package is not local, and tries to resolve register.js or preset.js in directory theme-selector/register. It can't find, and by default returns our custom addon as preset type, that will require on server side without transpiling. And we catch error SyntaxError: Cannot use import statement outside a module.

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ChucKN0risK picture ChucKN0risK  路  74Comments

dmmarmol picture dmmarmol  路  57Comments

dependencies[bot] picture dependencies[bot]  路  142Comments

ilias-t picture ilias-t  路  73Comments

tycho01 picture tycho01  路  76Comments