Storybook: Error: exports is not defined

Created on 3 Apr 2018  ·  78Comments  ·  Source: storybookjs/storybook

I'm trying to use storybook for the first time, so I decided to follow the guides.
I can get it working with the examples, but as soon as i pull in my own components i get __exports is not defined__.
It doesn't matter if I use the _"Quick Start Guide"_ or the _"Slow Start Guide (React)"_ I always get the same unhelpful error.

exports is not defined

ReferenceError: exports is not defined
at Object. (http://localhost:6006/static/preview.bundle.js:43176:23)
at __webpack_require__ (http://localhost:6006/static/preview.bundle.js:679:30)
at fn (http://localhost:6006/static/preview.bundle.js:89:20)
at Object. (http://localhost:6006/static/preview.bundle.js:43132:76)
at Object. (http://localhost:6006/static/preview.bundle.js:43142:30)
at __webpack_require__ (http://localhost:6006/static/preview.bundle.js:679:30)
at fn (http://localhost:6006/static/preview.bundle.js:89:20)
at loadStories (http://localhost:6006/static/preview.bundle.js:40160:3)
at ConfigApi._renderMain (http://localhost:6006/static/preview.bundle.js:41134:20)
at render (http://localhost:6006/static/preview.bundle.js:41092:17)
at ConfigApi.configure (http://localhost:6006/static/preview.bundle.js:41117:9)
at Object. (http://localhost:6006/static/preview.bundle.js:40164:68)
at Object.defineProperty.value (http://localhost:6006/static/preview.bundle.js:40165:30)
at __webpack_require__ (http://localhost:6006/static/preview.bundle.js:679:30)
at fn (http://localhost:6006/static/preview.bundle.js:89:20)
at Object.window.STORYBOOK_REACT_CLASSES (http://localhost:6006/static/preview.bundle.js:38867:18)
at __webpack_require__ (http://localhost:6006/static/preview.bundle.js:679:30)
at http://localhost:6006/static/preview.bundle.js:725:39
at http://localhost:6006/static/preview.bundle.js:728:10

That error doesn't really help much, and when I look up the error I end up at some issues from last year all saying that this problem has been patched out...
I know that it's probably my component that is exported in some way that storybook doesn't like. But since all I'm getting is __exports is not defined__ (along with some mess of a stacktrace) its kind of hard to debug.

I'm using typescript and I'm compiling it with just plain old tsc.

//tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "jsx": "react",
    "declaration": true,
    "sourceMap": true,
    "outDir": "./dist",
    "esModuleInterop": true
  },
  "include": [
    "./src/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

And then importing the compiled js into storybooks.

//index.stories.jsx
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import { MatrixEffect } from '../dist/index';

storiesOf('MatrixEffect', module)
  .add('100x100', () => 
    <MatrixEffect height={100} width={100} />
  );

Version

  • @storybook/react 3.4.0
  • @storybook/addon-actions 3.4.0
  • babel-core 6.26.0
  • react 16.3.0

What am I missing?
(if there's a way to just import the ts straight away then that would preferable. But since I haven't found any official docs for it, this is what I've got so far)

babel / webpack compatibility with other tools has workaround high priority typescript

Most helpful comment

this issue can be fixed by adding the correct plugin in the .babelrc file, since the tsconfig file is configured to generate commonjs compatible modules, we need to use the proper plugin

{
    "env": {
        "test": {
            "plugins": ["instanbul"]
        }
    },
    "plugins": ["@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-modules-commonjs"]
}

This is what I have in my .babelrc file and everything is working fine, I have my tsconfig file with exactly the same options and values.

"@babel/core" "^7.1.0"
"@storybook/react" ^4.0.0-alpha.2"
"react" "^16.4.0"

Note: This solution works for another kind of modules https://babeljs.io/docs/en/next/plugins#modules

All 78 comments

I'm getting export 'MatrixEffect' was not found in '../dist/index' in the terminal. But I can import the module in just a plain node runtime (can't use it ofc, but at least i know it can be imported).

this might help since we don't have official docs yet: https://github.com/storybooks/storybook/issues/3270

This is still not working...

I just ran into an issue with the same error message in a storybook after turning on yarn workspaces in a lerna project. I suspect that this is caused by package loading issues. Investigating further.

Sounds like I have the identical issue.

If I understand the problem right, there is an issue with resolving .ts files from the .js? (Though, I don't understand why you are importing your component from dist)

Maybe you should add .ts/.tsx to the resolve.extensions in your extended storybook webpack.config?

@igor-dv No, I use JS. Anyway, changing variable identifier (variable to Variable) works, somehow.

I'm getting this error without using TypeScript, just vanilla JS

I removed the babel loader from webpack.config.js in the .storybook folder and it works fine now. I don't use Typescript though.

I'm running into this, in the browser I get exports is not defined but in the terminal I get `"export 'default' (imported as '[ComponentName]') was not found in '@[namespace]/[package-name]'"

  • Using lerna
  • Storybook 3.4.7
  • Everything is fine for my components with no internal dependencies
  • If I try to import a module with a dependency on another package in project/packages the error shows up
  • I am running my build scripts, so it's trying to pull in a common-js version of the package.

If I change the internal dependency's package.json main config to the non-built source everything works

So there's something wrong with storybook's webpack config and importing cjs into es module code, or something ...

My fix

So I realized I accidentally deleted my package.json "module" field that pointed to the ES module version of my builds, adding that back in makes everything work again. Still seems like storybook should be able to pull the cjs version, but my problem is solved 🤷🏽‍♂️

This is still happening for me in v4.0.0-alpha.20 with babel 7.0.0

Same here @tony. I'm using Flow, though.

@ryanflorence I have the exact same lerna setup and the exports issue for storybook.
I have a package which exposes the built version of the UI-Elements.
Apologies but could you provide more details when you say, "module" field that pointed to the ES module version of my builds, adding that back in makes everything work again.

this issue can be fixed by adding the correct plugin in the .babelrc file, since the tsconfig file is configured to generate commonjs compatible modules, we need to use the proper plugin

{
    "env": {
        "test": {
            "plugins": ["instanbul"]
        }
    },
    "plugins": ["@babel/plugin-syntax-dynamic-import", "@babel/plugin-transform-modules-commonjs"]
}

This is what I have in my .babelrc file and everything is working fine, I have my tsconfig file with exactly the same options and values.

"@babel/core" "^7.1.0"
"@storybook/react" ^4.0.0-alpha.2"
"react" "^16.4.0"

Note: This solution works for another kind of modules https://babeljs.io/docs/en/next/plugins#modules

For me the issue is caused with the recent changes to include babel-loader in 4.0.0.alpha. The default server webpack config could include your commonjs compiles (packages, workspaces): https://github.com/storybooks/storybook/blob/b2b73596f9dd97b4ba8c03340bd36f868e836772/lib/core/src/server/config/webpack.config.dev.js#L78
https://github.com/storybooks/storybook/blob/b2b73596f9dd97b4ba8c03340bd36f868e836772/lib/core/src/server/config/utils.js#L3

For me, a fix is to override the default plugin declare with a custom webpack.dev.js:

https://github.com/psychobolt/react-rollup-boilerplate/blob/d9cb9179cb7c00baab486646c504110bf7e2f50a/.storybook/webpack.config.js#L7

// exclude 'babel-loader' so we can override it later
...defaultConfig.module.rules.filter(rule => !(
    (rule.use && rule.use.length && rule.use.find(({ loader }) => loader === 'babel-loader'))
)),

https://github.com/psychobolt/react-rollup-boilerplate/blob/d9cb9179cb7c00baab486646c504110bf7e2f50a/.storybook/webpack.config.js#L11

{
  test: /\.jsx?$/,
  include: require('path').resolve('./'),
  exclude: /(node_modules|dist)/, // exclude any commonjs files
  loader: 'babel-loader',
},

Omitting include also fixes the issue and has no side effects for me.

I think I understand what's going on.

What @psychobolt is saying is 100% correct.

I think we could do better for monorepo users, make our default webpack config so the above doesn't happen.

I think removing include: includePaths, would do it, but the question is at what performance cost..

Who has a good suggestion on how to best solve this?

We also stumbled upon this issue and it took more more of a half a day fighting configs to figure it out what it might be. 😢

@cilice How did you solve this?

@0nn0 by following https://github.com/storybooks/storybook/issues/3346#issuecomment-425516669 this advice :)

I'm having the same issue with stotybook-4.1.4, Lerna project, React 16.7.0, plain JS. Works with storybook-4.0.12

I had the same error on 4.1.4, I'm back to 4.0.10 and works fine (no typescript) babel-webapck

Using a modified config to exclude compiled output from babel-loader will avoid this issue for Lerna or monorepo projects with the latest storybook package.

@psychobolt Could you provide an example config? Thanks.

Not sure if this will help anyone else but we fixed this issue by running the following:

npm i react-scripts -D

@skeet I wondered why storybook had the message

info => Using base config because react-scripts is not installed.
info => Using default webpack setup based on "create-react-app".
info => Using base config because react-scripts is not installed.

So, after installing react-scripts, it now says

info => Loading create-react-app config.
info => Using default webpack setup based on "create-react-app".
info => Loading create-react-app config.

We have also had the exports is not defined problem a few times and we've previously worked around it by overriding the Babel configuration as suggested by others.

But, I recently started to look into this again and I noticed that the exclude property for the default JS rule was being resolved to an absolute path (below is a console.log() of the generated Webpack config):

{
  test: /\.(mjs|jsx?)$/,
  use: [
    {
      loader: 'babel-loader',
      options: {
        cacheDirectory: '.cache/storybook',
        presets: [
          [
            '@babel/preset-env',
            { shippedProposals: true, useBuiltIns: 'usage' }
          ],
          '@babel/preset-react',
          '@babel/preset-flow'
        ],
        plugins: [
          'babel-plugin-macros',
          '@babel/plugin-proposal-class-properties',
          [
            'babel-plugin-react-docgen',
            { DOC_GEN_COLLECTION_NAME: 'STORYBOOK_REACT_CLASSES' }
          ]
        ]
      }
    }
  ],
  include: ['/Users/matt.hinchliffe/Project/'],
  exclude: ['/Users/matt.hinchliffe/Project/node_modules']
}

I had assumed the exclude property should be a RegExp so I thought it looked odd! I realised that due to the structure of our project we actually have many node_modules folders so I tried updating this line to a RegExp (/node_modules/) - and it fixed it!

This avoids transpiling modules which have already been transpiled - and in particular avoids the useBuiltins option of preset-env from injecting core-js polyfills (removing the useBuiltins option or setting the environment to target runtimes which do not require any polyfills can also help to avoid this issue.)

So there are a few different issues at play which result in this problem:

  1. Dependencies in node_modules folders can be unintentionally transpiled by Babel
  2. The useBuiltins option can inject core-js polyfills into your code in the wrong format for the module type (see https://github.com/babel/babel/issues/7463 and https://github.com/babel/babel/issues/9187)
  3. If packages are being symlinked (such as in a monorepo) then you must tread extra carefully to avoid point 1!

Unfortunately it is not very easy to extend the existing exclude option, but it is possible!

I have created a reduced test case for this problem with information on how to avoid it. I will file an issue with Babel if necessary.

https://github.com/i-like-robots/broken-webpack-bundle-test-case

We are using storybooks + lerna + typescript. What solved for us was mixing @i-like-robots with @psychobolt:

module.exports = (baseConfig, env, config) => {
    config.module.rules = config.module.rules.filter(rule => !(
        (rule.use && rule.use.length && rule.use.find(({ loader }) => loader === 'babel-loader'))
    ));
    config.module.rules.push({
        test: /\.(ts|tsx)$/,
        loader: require.resolve('babel-loader'),
        options: {
            sourceType: 'unambiguous',
            presets: [['react-app', { flow: false, typescript: true }]],
        },

    });
    config.resolve.extensions.push('.ts', '.tsx');
    return config;
};

We have same issue, when r u going to fix it ?

Getting this error on a fresh install. No clue as to what's causing this (possibly in a conflict with the .babelrc between create-react-app's setup and this one?).

I managed to fix the issue by adding the following line to the .babelrc file:

"sourceType": "unambiguous"

More info on this option: https://babeljs.io/docs/en/options#sourcetype
Believe this option is only available with Babel 7 and up.

Just to drive by on this one without fully understanding what people's issues are (apologies!) -- here's a snippet from my webpack config that works around this issue, maybe in a simpler way:

  const babelLoader = storybookBaseConfig.module.rules[0];
  babelLoader.exclude.push(
    path.resolve('./lib/components/node_modules'),
    /* etc */
  );

@tmeasday Can you please elaborate on your suggestion — i.e. where to place that code?

Storybook is awesome, but this error has been intermittent and awful. I cannot seem to find a rhyme or reason as to why this error will start happening. I'll fuss around with components and then boom, everything just starts working without any real changes being made. But I've been stuck now for an hour trying to get this working and I just don't have the foggiest idea why this is broken.

Please look into this issue which seems to be affecting many people and is a showstopper.

I solved the issue by creating a .storybook/weback.config.js file containing the following:

const path = require('path');

// Export a function. Accept the base config as the only param.
module.exports = async ({ config, mode }) => {
    // `mode` has a value of 'DEVELOPMENT' or 'PRODUCTION'
    // You can change the configuration based on that.
    // 'PRODUCTION' is used when building the static version of storybook.

    config.module.rules[0].use[0].options.sourceType = "unambiguous";

    return config;
};

Seems like it does boil down to the sourceType babel issue. I tried adding a .babelrc file (as suggested by @0nn0), but that seemed to replace the entire babel configuration rather than modify it, causing further issues.

@JasonTheAdams the code snippet I wrote above would go in the .storybook/webpack.config.js. I think it is similar to what you've done.

Here's what I think is going on:

The issue is that files in node_modules inside subprojects (e.g. ./lib/components/node_modules) are being compiled by babel. They are files that have already shipped to NPM and don't need to be compiled. In some cases, this causes confusing issues, maybe around how babel parses files.

My approach is just to tell babel-loader not to compile any file inside any node_modules folder. By default it will ignore ./node_modules so it will compile things inside subproject's node_modules. So I add some paths to the exclude list.

Your approach is to configure babel-loader to use babel's sourceType detection to tell how to parse a file. This basically works around babel mis-parsing files. However babel is still running on files that don't need to be compiled, so I don't know if it's what you want?

I am not an expert so take my words with a grain of salt, but that's my understanding having worked through similar issues myself.

After applying @skeet's suggestion (https://github.com/storybooks/storybook/issues/3346#issuecomment-459308703) the issue returned when I started referencing one package as a dependency (not peer or dev) of a few others.

Putting the module field into the dependency's package.json as in @ryanflorence's fix (https://github.com/storybooks/storybook/issues/3346#issuecomment-415982589) did the job.

   main: "dist/index.js",
+  module: "dist/index.js",

@tmeasday Got it. I'm starting to wrap my head around this issue. What's tricky is that, in my situation, I actually _do_ want it to compile the child node_modules as that's where I'm developing the components themselves, treating it as a separate package.

I think @skeet's suggestion, as echoed by @jcousins-ynap, is probably the best solution here. We don't want Storybook to make assumption on how sub-packages are handled (i.e. ignoring their node_modules). If someone didn't want the sub-modules node_modules compiled, they likely wouldn't have installed the package dependencies to begin with.

It seems to all come down to babel + webpack's ability to recognize CommonJS vs ES6 modules, which doesn't seem to be perfect. Adding the "module": field to the sub-package's package.json explicitly informs babel that the package uses ES6 modules, which is the safest way to approach this.

Thank you for your attention to this!

Also want to chime in here. Using Storybook 5, Babel 7.4 (with core-js 3), TypeScript 3.4 and a monorepo. Most of these suggestions did not work 100%, but something I realized did. The very nature of monorepos is that a package is importing the "built" files from another package, not the source files, which is true when in the NPM registry/node module layer, but in development, is quite annoying. To get around this, I defined Webpack aliases that forwarded lib/ to src/, and everything just worked, especially since all code is now ESNext/ESM!

Here's the hack:

glob.sync(path.join(__dirname, '../packages/*/package.json')).forEach(filePath => {
  const { name } = require(filePath);

  config.resolve.alias[`${name}$`] = `${name}/src`;
  config.resolve.alias[`${name}/lib`] = `${name}/src`;
});

And to get Babel + TS working, I opted to mutate the existing babel-loader instead of adding a new one, as my local Babel config isn't 100% compatible with Storybook's, but their own config is.

const babelConfig = config.module.rules[0];

// Replace Flow with TypeScript
babelConfig.test = /\.(j|t)sx?$/;
babelConfig.exclude.push(/node_modules/);
babelConfig.use[0].options.sourceType = 'unambiguous';
babelConfig.use[0].options.presets[2] = require.resolve('@babel/preset-typescript');
babelConfig.use.unshift({ loader: require.resolve('react-docgen-typescript-loader') });

config.resolve.extensions.push('.ts', '.tsx');

Had the same issue, also due to removing module field.
Adding @babel/plugin-transform-modules-commonjs to babel plugin helped, as described in this comment: https://github.com/storybooks/storybook/issues/3346#issuecomment-423719241

@elado work!

totally stymied by this one as well. spent the last ~2 days unsuccessfully trying all the suggestions from this thread as well as some of my own. none were successful 😢

ultimately, i'm left with:

WARNING in ./packages/one/src/index.jsx 2:289-293
"export 'default' (imported as 'Two') was not found in '@my-monorepo/two'
 @ ./packages/one/src/index.stories.jsx
 @ ./packages sync \.stories\.jsx$
 @ ./.storybook/config.js
 @ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/config.js

...when starting storybook and...

index.js:49 ReferenceError: exports is not defined
    at react-is.development.js:18
    at Module../packages/one/node_modules/react-is/cjs/react-is.development.js (react-is.development.js:226)
    at __webpack_require__ (bootstrap:785)
    at fn (bootstrap:150)
    at Object../packages/one/node_modules/react-is/index.js (index.js:6)
    at __webpack_require__ (bootstrap:785)
    at fn (bootstrap:150)
    at Object../packages/one/node_modules/prop-types/index.js (index.js:9)
    at __webpack_require__ (bootstrap:785)
    at fn (bootstrap:150)

...when viewing the storybook ui (http://localhost:9001). my stories don't load.

fwiw, here's my setup:

├── .storybook/
│   ├── addons.js
│   ├── config.js
│   └── webpack.config.js
│
├── packages/
│   ├── one
│   │   ├── src/
│   │   │   ├── index.jsx
│   │   │   ├── index.stories.jsx
│   │   │   └── index.test.jsx
│   │   ├── dist/
│   │   │   ├── index.js
│   │   │   ├── index.stories.js
│   │   │   └── index.test.js
│   │   └── package.json
│   │
│   └── two
│       ├── src/
│       │   ├── index.jsx
│       │   ├── index.stories.jsx
│       │   └── index.test.jsx
│       ├── dist/
│       │   ├── index.js
│       │   ├── index.stories.js
│       │   └── index.test.js
│       └── package.json
│
├── .babelrc
├── .eslintrc.js
├── jest.config.js
├── lerna.json
├── npm-shrinkwrap.json
└── package.json


addons.js

import '@storybook/addon-knobs/register';
import '@storybook/addon-backgrounds/register';
import '@storybook/addon-storysource/register';


config.js

import { configure } from '@storybook/react';

const req = require.context('../packages', true, /.stories.jsx$/);

function loadStories(){
    req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);


webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.stories\.jsx?$/,
                loaders: [require.resolve('@storybook/addon-storysource/loader')],
                enforce: 'pre'
            }
        ]
    }
};


.babelrc

{
    "presets": ["@babel/preset-env", "@babel/preset-react"],
    "plugins": [
        "@babel/plugin-transform-modules-commonjs"
    ]
}


package.json (root)

{
  "name": "my-monorepo",
  "description": "monorepo containing POC react ui component library",
  "version": "1.0.0",
  "author": "me",
  "scripts": {
    "postinstall": "npm run bootstrap",
    "bootstrap": "lerna bootstrap",
    "storybook": "npm run build && start-storybook --port 9001 --config-dir .storybook --ci",
    "test": "npm run lint && npm run test:unit",
    "test:unit": "npm run build && NODE_ENV=development BABEL_ENV=test jest --no-watchman",
    "test:unit:watch": "npm run test:unit -- --watch",
    "test:unit:snapshot": "npm run test:unit -- --updateSnapshot",
    "lint": "eslint . --ext .js,.jsx --ignore-path .gitignore",
    "lint:fix": "npm run lint -- --fix",
    "build": "npm run clean && lerna run build",
    "clean": "lerna run clean",
    "clean:modules": "lerna clean --yes",
    "release": "npm run build && lerna publish",
    "start": "npm run storybook"
  },
  "dependencies": {},
  "devDependencies": {
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/plugin-transform-modules-commonjs": "^7.5.0",
    "@babel/preset-env": "^7.5.5",
    "@babel/preset-react": "^7.0.0",
    "@storybook/addon-backgrounds": "^5.1.9",
    "@storybook/addon-knobs": "^5.1.9",
    "@storybook/addon-storysource": "^5.1.9",
    "@storybook/react": "^5.1.9",
    "babel-jest": "^22.4.1",
    "babel-loader": "^8.0.6",
    "enzyme": "^3.10.0",
    "enzyme-adapter-react-16": "^1.14.0",
    "enzyme-to-json": "^3.3.5",
    "eslint": "^4.18.2",
    "eslint-config-particle": "^2.2.1",
    "eslint-plugin-react": "^7.14.2",
    "jest": "^22.4.2",
    "jest-styled-components": "^6.3.3",
    "lerna": "^3.15.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "styled-components": "^4.3.2"
  }
}


package.json (one)

{
  "name": "@my-monorepo/one",
  "description": "react component one",
  "version": "1.1.0",
  "author": "me",
  "main": "dist/index.js",
  "scripts": {
    "test": "cd ../../ && npm test",
    "build": "babel ./src --out-dir ./dist --ignore test.jsx,stories.jsx --config-file ../../.babelrc",
    "clean": "rm -rf ./dist"
  },
  "peerDependencies": {
    "react": ">=15",
    "styled-components": ">=3"
  },
  "dependencies": {
    "@my-monorepo/two": "^1.1.0",
    "create-react-class": "^15.6.3",
    "prop-types": "^15.7.2"
  }
}


package.json (two)

{
  "name": "@my-monorepo/two",
  "description": "react component two",
  "version": "1.1.0",
  "author": "me",
  "main": "dist/index.js",
  "scripts": {
    "test": "cd ../../ && npm test",
    "build": "babel ./src --out-dir ./dist --ignore test.jsx,stories.jsx --config-file ../../.babelrc",
    "clean": "rm -rf ./dist"
  },
  "peerDependencies": {
    "react": ">=15"
  },
  "dependencies": {
    "create-react-class": "^15.6.3",
    "prop-types": "^15.7.2"
  }
}

everything within the components' ./src directory uses ESM-style imports / exports. the @my-monorepo/one depends on @my-monorepo/two. at install-time, lerna _links_ the dependency (via lerna bootstrap). all packages are built using babel - the top-level npm run build command generates the individual ./dist directories and their contents. npm start first builds the components, then starts storybook.

under v3 all of this worked just fine - though it always felt a bit awkward to have to build the components first. i get _why_ though - package.json includes "main: "dist/index.js" so without that in place storybook would report that @my-monorepo/two could not be found when attempting to build (since @my-monorepon/one depends on it). but otherwise, i was happy with the setup.

one thing i noticed: when i added "module": "src/index.jsx" to the components' package.json files, it got rid of the webpack warning but the client-side ReferenceError: exports is not defined remained. i found someone reporting the same error but no resolution.

i'm going to stick with storybook v3 for now but i'll keep an eye on this thread and happily try any suggestions :pray::+1:

@busticated sounds like you might have a reproduction repo you could share i could take a look at?

@ndelangen thanks for taking a look :pray: my repo is not public atm unfortunately. i tried to share the relevant details above but in the meantime i can try to build up a working example if that'd be helpful. might take a bit though. otherwise, happy to try suggestions, etc.

@busticated I'd be happy to take a look at a monorepo-repro-repo 🙈

It's likely that:

  • some files are parsed through babel twice
  • some files are parsed though loaders that aren't compatible with each other
  • some files are compiled using the wrong babel/ts config
  • some other monorepo shenanigans

Unfortunately ReferenceError: exports is not defined doesn't tell us anything other then, something is not as it's supposed to be.

@ndelangen ok, here's the repro repo 😂

https://github.com/busticated/storybook-monorepo-repo

you should be able to simply:

  1. git clone
  2. npm i && npm start

...and see storybook attempt to load in the browser. open dev tools' console and you'll see the exports error.

couple of notes:

  • run npm run build to test the prepublish build
  • it should work across node / npm versions +/- some lock file noise (fwiw, i used node@8 and npm@5 to align w/ day job)
  • the last two commits add the "module": "src/index.jsx" fields to packages/*/packge.json files. if you revert those, you'll see the original export 'default' (imported as 'Two') was not found webpack warning.

I'll try to take a look asap

I'm using Lerna, internal packages are bundled by Webpack with output libraryTarget: 'commonjs2'. Approach based on @JasonTheAdams comment works for me. I've also tested @0nn0 solution with babelrc { "sourceType": "unambiguous" } and it also works however it requires to have .babelrc in package root.

Some basic setup - maybe it will help someone 😉(Storybook: 5.1.10, Lerna: 3.16.4, Webpack: 4.39.1, Babel: 7.5.5)


file: _lerna_repo/.storybook/webpack.config.js_ - doesn't exist by default

module.exports = async ({ config }) => {
  const [ mjsjsx ] = config.module.rules;
  const [ babelLoader ] = mjsjsx.use;

  babelLoader.options.sourceType = 'unambiguous'

  return config;
};

file: _lerna_repo/stories/index.stories.js_

import defaultExport, { namedExport } from '../packages/examplePackage' // works locally
// import defaultExport, { namedExport } from '@examplePackage' // works installed
...

file: _lerna_repo/packages/examplePackage/package.json_

"name": "@examplePackage",
"version": "0.0.1",
"main": "./dist/index.js"
...

file: _lerna_repo/packages/examplePackage/dist/index.js_ - generated by Webpack

module.exports=function(e){var n={};function...

@ndelangen Any update on the above?

I got the "exports is not defined" error when trying to "import" a CommonJS-style module. Setting Babel sourceType option to "unambiguous" as suggested by others did the trick.

This isn't really an issue with Storybook, moreso a consequence of being stuck in the middle of two module specifications.

Seems to be fixed in version 5.2

Hi guys, is it fixed actually ?

I'm using 5.2.1 and have this issue in newly created Lerna monorepo.

In my case this happening: https://github.com/storybookjs/storybook/issues/3346#issuecomment-475437230

I modified Storybook Webpack config to exclude node_modules in "Lerna" packages from Babel compiling. But the issue is still there I think.

I closed based on @idbartosz 's comment. Do you think it's still broken @Lighttree ?

Sorry for bringing confusion, I've based my answer on Lerna configuration where required packages are hoisted to the root and installed there as dev dependencies. So I did't experience the problem of parsing their node_modules.

It seems that some user have a use case where they have installed packages deeper in the tree like /lib/components/node_modules https://github.com/storybookjs/storybook/issues/3346#issuecomment-475437230 and babel-loader tries to parse them.

By default storybook excludes root node_modules but maybe it's worth to exclude all of them.

https://github.com/storybookjs/storybook/blob/f7367b18ec7d6e077fba5b99da89233b63c4f280/lib/core/src/server/config/utils.js#L5-L6

https://github.com/storybookjs/storybook/blob/f7367b18ec7d6e077fba5b99da89233b63c4f280/lib/core/src/server/common/babel-loader.js#L1-L13

@shilman I am facing this error too , with react-motion in lerna mono-repo repository.
did @idbartosz solution fix the issue ?

@sayjeyhi yeah, it should. This is not actually Storybook issue. This happens just because when you work in monorepo, you have node_modules not only in your project root, but in */packages as well, which is not excluded by default. (I actually not sure that it shouldn't, because its monorepo organization specific. If you create your Storybook as package in Lerna packages folder you won't have this issue)

So for my case I just did this in .storybook/webpack.config.js:

const path = require('path');
const glob = require('glob');

// Export a function. Accept the base config as the only param.
module.exports = async ({ config, mode }) => {
    // `mode` has a value of 'DEVELOPMENT' or 'PRODUCTION'
    // You can change the configuration based on that.
    // 'PRODUCTION' is used when building the static version of storybook.
    // Make whatever fine-grained changes you need
    const babelLoader = config.module.rules[0];

    /**
     * Exclude pacakge's `node_modules` from Storybook babel processing.
     */
    glob.sync('./packages/*/node_modules').forEach(match => {
        babelLoader.exclude.push(path.resolve(match));
    });

    // Return the altered config
    return config;
};

has anyone actually shown their proposed work-around fixes the example repro I created?

https://github.com/storybookjs/storybook/issues/3346#issuecomment-514324312

seems like that would answer the question definitively.

I can see that mostly everyone here with a monorepo project is using lerna, I have a monorepo project that uses yarn workspaces rather than lerna and everything is working fine with the latest version of storybook + typescript, and without strange webpackconfigurations, it should work fine as well with babel.

If you show some interest I can create a monorepo with a working storybook, I can see on the @busticated 's files, is that some scripts runs in the wrong order and some dependencies are in the incorrect package.json, I'm not saying that is causing issues but it could be.

@pixeleate

I can see on the @busticated 's files, some scripts runs in the wrong order and some dependencies are in the incorrect package.json

can you be more specific?

also, keep in mind that i have a _working_ version of my example repo running storybook v3 as noted here https://github.com/storybookjs/storybook/issues/3346#issuecomment-513397002

@pixeleate Would you mind sharing your working repo?

I can see that mostly everyone here with a monorepo project is using lerna, I have a monorepo project that uses yarn workspaces rather than lerna and everything is working fine with the latest version of storybook + typescript, and without strange webpackconfigurations, it should work fine as well with babel.

If you show some interest I can create a monorepo with a working storybook, I can see on the @busticated 's files, is that some scripts runs in the wrong order and some@ dependencies are in the incorrect package.json, I'm not saying that is causing issues but it could be.

babelConfig.exclude.push(/node_modules/); fixes the issue for me when running start-storybook, but I get the same exports is not defined error when running the output from build-storybook.

Edit: Resolved by removing storybook-addon-jsx.

@busticated I opened a PR with a fix:
https://github.com/busticated/storybook-monorepo-repo/pull/1

There were a few incorrect imports that were the main problem I think.

@jacobrask I want to change that in storybook's core. But I'm scared it will wreak havoc if we change that in a minor release.

@shilman I think we should change it, but it should be a major version bump

@ndelangen

I opened a PR with a fix

thanks!

There were a few incorrect imports that were the main problem I think

hm. yeah. serves me right for not setting up eslint 😂🤦‍♂

that all said, it seems once you account for the bad variable names and updated @storybook/addon-backgrounds usage - as i did over on master (1, 2, 3, 4) - the only outstanding change is to use yarn.

am i correct?

edit: here's a cleaned-up branch w/ just the changes required for yarn 👉 https://github.com/busticated/storybook-monorepo-repo/commit/4fb2cac0f05b65a5983f121b92a7c2d7438d8857

yarn workspaces will hoist all dependencies to the root, this will solve tons of issues.

In my PR: https://github.com/storybookjs/storybook/pull/8822 I make a change to storybook to support excluding MULTIPLE node_modules folders by default.

As detailed there, I'm pretty terrified of rolling that change out in a minor release, and so is @shilman. We've decided it's better to hold that until 6.0.

yarn workspaces will hoist all dependencies to the root, this will solve tons of issues.

assuming you use yarn 😉

make a change to storybook to support excluding MULTIPLE node_modules folders by default

is that the root cause? applying the change locally doesn't seem to fix my issue.

i'm getting the following in my browser's console:

TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

...which is a bit different i guess..? yet another error that you see all the time but always has a different solution 🤦‍♂ _/me frowns in babel and webpack's general direction_ 😬

I'm pretty terrified of rolling that change out in a minor release, and so is @shilman. We've decided it's better to hold that until 6.0.

oh yeah i hear you - none of this stuff is ever easy. thank you very much for al the work you do here and elsewhere - storybook (even v3) is an amazingly helpful tool :pray::clap::clap::clap::+1:

TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

This is most likely caused by Webpack wrapping a CommonJS module with its ESM wrapper. Webpack will use an ESM wrapper if it sees any usage of import in the module. It's usually caused by either:

  1. Mixing and matching ESM and CJS in your source code
  2. Babel injecting ESM helpers into a CJS module

To avoid the second case you'll need to set Babel's sourceType to "unambiguous" to force it to check the module type first.

https://github.com/i-like-robots/broken-webpack-bundle-test-case


Update: My original comment is hidden above but this is the base configuration we have been using to resolve these issues across multiple monorepo projects:

const excludePaths = [/node_modules/, /dist/]

module.exports = ({ config }) => {
  // Use real file paths for symlinked dependencies do avoid including them multiple times
  config.resolve.symlinks = true

  // HACK: extend existing JS rule to ensure all dependencies are correctly ignored
  // https://github.com/storybooks/storybook/issues/3346#issuecomment-459439438
  const jsRule = config.module.rules.find((rule) => rule.test.test('.jsx'))
  jsRule.exclude = excludePaths

  // HACK: Instruct Babel to check module type before injecting Core JS polyfills
  // https://github.com/i-like-robots/broken-webpack-bundle-test-case
  const babelConfig = jsRule.use.find(({ loader }) => loader === 'babel-loader')
  babelConfig.options.sourceType = 'unambiguous'

  // HACK: Ensure we only bundle one instance of React
  config.resolve.alias.react = require.resolve('react')

  return config
}

@i-like-robots what's the downside of using sourceType = 'unambiguous'?

Thanks for posting the workaround!

I'm going to use this to improve monorepo support: https://github.com/storybookjs/storybook/pull/8822

(6.0.0 feature)

Maybe unrelated, but I was having this exports is not defined issue because of my custom babel.config.js, reading https://storybook.js.org/docs/configurations/custom-babel-config/ solved my particular problem.

@qrosmeli Thanks for the tip. You saved my day! 🚀

Huzzah!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.0.0-alpha.0 containing PR #8822 that references this issue. Upgrade today to try it out!

You can find this prerelease on the @next NPM tag.

Closing this issue. Please re-open if you think there's still more to do.

[UPDATED] - We have to exclude node_modules from this rule otherwise it will break the build

I have resolved it by adding this rule in storybook main.js file

let rules = [{
  test: /\.(js|mjs|jsx|ts|tsx)$/,
  include: /dist/, //Include dist folder as well to parse using babel loader in order to resolve exports not defined error
  exclude: /node_modules/,
  loader: 'babel-loader',
  options: {
    presets: [
      ["@babel/preset-env", {
        modules: "commonjs"
      }]
    ]
  }
}]

Along with this, you may also need to disable the eslint validations for your dist folder, so for that, you can use below script

  webpackFinal: config => {

    //Find eslint loader rule from webpack config
    let eslintRule = config.module.rules.find(rule => {
      if (rule && rule.use) {
        return rule.use.some(use => use.loader.match('eslint-loader'))
      }
    });

    //Exclude validations of dist folder contents
    eslintRule.exclude = /dist/;

    return {
      ...config,
      module: {
        rules: [
          ...rules,
          eslintRule,
          ...config.module.rules
        ]
      }
    }
  }

Thanks @ashvin777, works like a charm :wink:

Hey @aperkaz, I have updated the rule to exclude node_modules, I found that storybook was launching properly in dev mode however breaking in production mode because of this change. So I had to exclude node_modules in order to fix. You can take the latest from my updated comment above.

I had the exact same issue, and for me the solution was switching from using transform-es2015-modules-commonjs to @babel/plugin-transform-modules-commonjs on babel.config.js.

before

module.exports = {
    presets: [['@babel/preset-env', { modules: false }], '@babel/preset-react'],
    plugins: [
        'transform-es2015-modules-commonjs',
        '@babel/plugin-proposal-class-properties'
    ]
};

after

module.exports = {
    presets: [['@babel/preset-env', { modules: false }], '@babel/preset-react'],
    plugins: [
        '@babel/plugin-transform-modules-commonjs',
        '@babel/plugin-proposal-class-properties'
    ]
};
TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

I spent the day on this issue, I already had the sourceType: 'unambigous'.

For my part, it was not linked to a node_modules folder to ignore since it is a relative file right next to it.

A workaround that works for me is to force the option modules: 'cjs' for the @babel/preset-env.

I also have this problem with @storybook/react@next, the final solution for me was to manually add the babel plugin @babel/plugin-transform-modules-commonjs, while with the debug: true option on the @babel/preset-env I see that it is already used... I don't understand but it works.

EDIT: This is not a solution because it loses the benefits of ESM modules with webpack. I need to force transform to cjs only for the storybook builds.

:tada: My .storybook/.babelrc: :tada:

{
  "extends": "../.babelrc",
  "plugins": [
    "@babel/plugin-transform-modules-commonjs"
  ]
}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tlrobinson picture tlrobinson  ·  3Comments

dnlsandiego picture dnlsandiego  ·  3Comments

miljan-aleksic picture miljan-aleksic  ·  3Comments

levithomason picture levithomason  ·  3Comments

rpersaud picture rpersaud  ·  3Comments