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

behaviour with nested node_modules, parent babel.config.js, useBuiltIns: 'usage' vs useBuiltIns: 'entry' #11266

Closed
1 task done
gaurav5430 opened this issue Jun 23, 2020 · 4 comments

Comments

@gaurav5430
Copy link

Describe the bug
I have a lerna monorepo, where there can be nested node_modules folders inside packages.
I also have storybook setup in the same repo, though it is outside of lerna packages and hence not managed by lerna.

I have a custom webpack pipeline which is different from the default storybook webpack config (because I need to have a setup for using css-modules, postcss-loader etc).

But I am also using storybook Docs, for which i need to have some babel-loader setup which can cater to react-docgen. Since storybook webpack config already has this by default, I am just merging my config with storybook webpack config, to pickup whatever i require from storybook config. This might not be the best way to customize webpack config, but stay with me.

This is how my ./storybook/webpack.config.js looks like:

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

const customModule = {
  module: {
    rules: [
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              modules: {
                localIdentName: '[name]__[local]__[hash:base64:5]',
              },
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [
                require('cssnano')({
                  preset: 'default',
                }),
                require('postcss-import')(),
                ...
                require('autoprefixer')({
                  overrideBrowserslist: [
                    '>5%',
                    'cover 99.5%',
                    'Firefox ESR',
                    'not ie < 9', // React doesn't support IE8 anyway
                  ],
                  flexbox: 'no-2009',
                }),
                require('postcss-mixins')(),
                require('postcss-nested')(),
                require('postcss-hexrgba')(),
                require('postcss-flexbugs-fixes')(),
              ],
            },
          },
        ],
      },
      {
        test: /\.css$/,
        include: /node_modules/,
        loader: 'style-loader!css-loader',
      },
      {
        test: /\.(woff|woff2|eot|ttf|svg|png|jpg)$/,
        use: [{
          loader: 'url-loader',
          options: {
            limit: 100000,
          },
        }],
      },
    ],
  },
};

// eslint-disable-next-line import/no-commonjs
module.exports = async ({ config }) => {
  // need to keep some existing storybook module.rules
  // to enable source code and documentation in DocsPage
  console.log(JSON.stringify(config.module.rules));
  const existingConfigRules = config.module.rules
    .filter((rule) => {
      if (rule.use && rule.use[0] && rule.use[0].loader) {
        if (rule.use[0].loader === 'babel-loader') return true;
      } else if (rule.loader && rule.loader.includes('source-loader')) return true;
      return false;
    });

  // return config;
  return ({
    ...config,
    module: {
      ...config.module,
      rules: [
        ...customModule.module.rules,
        ...existingConfigRules,
      ],
    },
  });
};

So, I have my own webpack pipeline for styles, and I am picking up the babel-loader and source-loader from default storybook webpack config.

This setup works fine, stories are rendered correctly and docs work as well.

Recently, when I tried to write stories for a component inside a package which has its own node_modules, I got an error related to

exports is not defined

Screenshot 2020-06-23 at 11 22 48 AM

This was from the nested node_modules folder.
With some research, I was able to figure out that this might be happening because webpack is transpiling the nested node_modules folder (although I am not sure why transpiling the node_modules shouldn't work, i know it is not recommended, but not sure if it should break after transpiling
https://stackoverflow.com/questions/54156617/why-would-we-exclude-node-modules-when-using-babel-loader)

The research was mostly related to the fact that removing the nested node_modules folder, but having the dependencies in the top level node_modules folder works, which lead me to believe that somehow these 2 node_modules folders are being treated differently. I was not able to exclude it by overriding it in my custom webpack config and changing the order of merge, because i was not overriding or updating the default storybook babel-laoder config directly, So, i tried to look into the storybook webpack config to see if I can do something there.

There are multiple ways to make it work:

  • as suspected, the nested node_modules is not excluded by storybook webpack config by default, so If i copy the storybook webpack config for babel-laoder and change it to exclude the nested node_modules it works.

  • This is something i understand

{
  test: /\.(ts|js)x?$/,
  use: [
    {
      loader: 'babel-loader',
      options: {
        cacheDirectory: 'appdir/node_modules/.cache/storybook',
        presets: [
          [
            'appdir/node_modules/@babel/preset-env/lib/index.js',
            {
              shippedProposals: true,
              useBuiltIns: 'usage',
              corejs: '3',
            },
          ],
          'appdir/node_modules/@babel/preset-react/lib/index.js',
          'appdir/node_modules/@babel/preset-flow/lib/index.js',
        ],
        plugins: [
          'appdir/node_modules/@babel/plugin-proposal-object-rest-spread/lib/index.js',
          'appdir/node_modules/@babel/plugin-proposal-class-properties/lib/index.js',
          'appdir/node_modules/@babel/plugin-syntax-dynamic-import/lib/index.js',
          [
            'appdir/node_modules/babel-plugin-emotion/dist/babel-plugin-emotion.cjs.js',
            {
              sourceMap: true,
              autoLabel: true,
            },
          ],
          'appdir/node_modules/babel-plugin-macros/dist/index.js',
          'appdir/node_modules/@babel/plugin-transform-react-constant-elements/lib/index.js',
          'appdir/node_modules/babel-plugin-add-react-displayname/index.js',
          [
            'appdir/node_modules/babel-plugin-react-docgen/lib/index.js',
            {
              DOC_GEN_COLLECTION_NAME: 'STORYBOOK_REACT_CLASSES',
            },
          ],
        ],
      },
    },
  ],
  include: [
    'appdir',
  ],
  exclude: [
    'appdir/node_modules',
    'appdir/packages/components/node_modules',
  ],
},

I have added the 'appdir/packages/components/node_modules', in exclude, and this works.

[ ] This is something I don't understand, ie, why is transpiling node_modules a problem ?

module.exports = {
  presets: [[
    '@babel/preset-env',
  ], '@babel/preset-react'],
  plugins: [
    ['react-css-modules', {
      autoResolveMultipleImports: true,
      generateScopedName: '[name]__[local]__[hash:base64:5]',
      handleMissingStyleName: 'warn',
      webpackHotModuleReloading: true,
    }],
    '@babel/plugin-syntax-dynamic-import',
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-proposal-object-rest-spread',
    '@babel/plugin-proposal-optional-chaining',
    '@babel/plugin-proposal-nullish-coalescing-operator',
    '@babel/plugin-transform-modules-commonjs'
  ],
};

I have just added @babel/plugin-transform-modules-commonjs in plugins
I don't believe that i should need to use this.

  • if I just create an empty babel.config.js inside the storybook folder, it works, without changing anything else. OR even if i copy the exact same babel.config.js as the parent folder to storybook folder, it works. I suspect this is due to some faulty setup for reading babel.config.js in storybook ?
    [ ] This is something I don't understand. How does this solve the issue without changing anything else?

  • If I change useBuiltIns: 'usage' to useBuiltIns: 'entry' in storybook babel-loader preset-env, it works without any other changes. This leads me to believe that storybook is using some babel polyfills which are somehow interfering with the transpiled node_modules
    [ ] This is something I don't understand. How does this solve the issue without changing anything else?

Expected behavior
I expected that:

  • transpiling of node_modules shouldn't be a problem and shouldn't lead to this error. But that is more related to webpack.
  • the behaviour should not change by just changing useBuiltIns: usage to useBuiltIns: entry. This might be more related to webpack than storybook.
  • if adding a new babel.config.js at storybook level works, i would have expected that if I remove the parent babel.config.js it should also work, but that doesn't work.

Screenshots
added in problem description

Code snippets
added in problem description

System:
Environment Info:

System:
OS: macOS Mojave 10.14.6
CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Binaries:
Node: 12.11.1 - /usr/local/bin/node
Yarn: 1.19.1 - /usr/local/bin/yarn
npm: 6.11.3 - /usr/local/bin/npm
Browsers:
Chrome: 83.0.4103.106
Firefox: 75.0
Safari: 13.1.1

More Info
This is the default storybook config rules I am getting by console.log(JSON.stringify(config.module.rules))

[
  {
    "test": {},
    "use": [
      {
        "loader": "babel-loader",
        "options": {
          "cacheDirectory": "appdir/node_modules/.cache/storybook",
          "presets": [
            [
              "appdir/node_modules/@babel/preset-env/lib/index.js",
              {
                "shippedProposals": true,
                "useBuiltIns": "usage",
                "corejs": "3"
              }
            ],
            "appdir/node_modules/@babel/preset-react/lib/index.js",
            "appdir/node_modules/@babel/preset-flow/lib/index.js"
          ],
          "plugins": [
            "appdir/node_modules/@babel/plugin-proposal-object-rest-spread/lib/index.js",
            "appdir/node_modules/@babel/plugin-proposal-class-properties/lib/index.js",
            "appdir/node_modules/@babel/plugin-syntax-dynamic-import/lib/index.js",
            [
              "appdir/node_modules/babel-plugin-emotion/dist/babel-plugin-emotion.cjs.js",
              {
                "sourceMap": true,
                "autoLabel": true
              }
            ],
            "appdir/node_modules/babel-plugin-macros/dist/index.js",
            "appdir/node_modules/@babel/plugin-transform-react-constant-elements/lib/index.js",
            "appdir/node_modules/babel-plugin-add-react-displayname/index.js",
            [
              "appdir/node_modules/babel-plugin-react-docgen/lib/index.js",
              {
                "DOC_GEN_COLLECTION_NAME": "STORYBOOK_REACT_CLASSES"
              }
            ]
          ]
        }
      }
    ],
    "include": [
      "appdir"
    ],
    "exclude": [
      "appdir/node_modules"
    ]
  },
  {
    "test": {},
    "use": [
      {
        "loader": "appdir/node_modules/raw-loader/dist/cjs.js"
      }
    ]
  },
  {
    "test": {},
    "include": {},
    "use": [
      {
        "loader": "babel-loader",
        "options": {
          "presets": [
            [
              "appdir/node_modules/@babel/preset-env/lib/index.js",
              {
                "modules": "commonjs"
              }
            ]
          ]
        }
      }
    ]
  },
  {
    "test": {},
    "use": [
      {
        "loader": "babel-loader",
        "options": {
          "cacheDirectory": "appdir/node_modules/.cache/storybook",
          "presets": [
            [
              "appdir/node_modules/@babel/preset-env/lib/index.js",
              {
                "shippedProposals": true,
                "useBuiltIns": "usage",
                "corejs": "3"
              }
            ],
            "appdir/node_modules/@babel/preset-react/lib/index.js",
            "appdir/node_modules/@babel/preset-flow/lib/index.js"
          ],
          "plugins": [
            "appdir/node_modules/@babel/plugin-proposal-object-rest-spread/lib/index.js",
            "appdir/node_modules/@babel/plugin-proposal-class-properties/lib/index.js",
            "appdir/node_modules/@babel/plugin-syntax-dynamic-import/lib/index.js",
            [
              "appdir/node_modules/babel-plugin-emotion/dist/babel-plugin-emotion.cjs.js",
              {
                "sourceMap": true,
                "autoLabel": true
              }
            ],
            "appdir/node_modules/babel-plugin-macros/dist/index.js",
            "appdir/node_modules/@babel/plugin-transform-react-constant-elements/lib/index.js",
            "appdir/node_modules/babel-plugin-add-react-displayname/index.js",
            [
              "appdir/node_modules/babel-plugin-react-docgen/lib/index.js",
              {
                "DOC_GEN_COLLECTION_NAME": "STORYBOOK_REACT_CLASSES"
              }
            ]
          ]
        }
      },
      {
        "loader": "@mdx-js/loader",
        "options": {
          "compilers": [
            null
          ],
          "remarkPlugins": [
            null,
            null
          ]
        }
      }
    ]
  },
  {
    "test": {},
    "exclude": {},
    "use": [
      {
        "loader": "babel-loader",
        "options": {
          "cacheDirectory": "appdir/node_modules/.cache/storybook",
          "presets": [
            [
              "appdir/node_modules/@babel/preset-env/lib/index.js",
              {
                "shippedProposals": true,
                "useBuiltIns": "usage",
                "corejs": "3"
              }
            ],
            "appdir/node_modules/@babel/preset-react/lib/index.js",
            "appdir/node_modules/@babel/preset-flow/lib/index.js"
          ],
          "plugins": [
            "appdir/node_modules/@babel/plugin-proposal-object-rest-spread/lib/index.js",
            "appdir/node_modules/@babel/plugin-proposal-class-properties/lib/index.js",
            "appdir/node_modules/@babel/plugin-syntax-dynamic-import/lib/index.js",
            [
              "appdir/node_modules/babel-plugin-emotion/dist/babel-plugin-emotion.cjs.js",
              {
                "sourceMap": true,
                "autoLabel": true
              }
            ],
            "appdir/node_modules/babel-plugin-macros/dist/index.js",
            "appdir/node_modules/@babel/plugin-transform-react-constant-elements/lib/index.js",
            "appdir/node_modules/babel-plugin-add-react-displayname/index.js",
            [
              "appdir/node_modules/babel-plugin-react-docgen/lib/index.js",
              {
                "DOC_GEN_COLLECTION_NAME": "STORYBOOK_REACT_CLASSES"
              }
            ]
          ]
        }
      },
      {
        "loader": "@mdx-js/loader",
        "options": {
          "remarkPlugins": [
            null,
            null
          ]
        }
      }
    ]
  },
  {
    "test": {},
    "loader": "appdir/node_modules/@storybook/source-loader/dist/server/index.js",
    "options": {
      "inspectLocalDependencies": true
    },
    "enforce": "pre"
  },
  {
    "test": {},
    "sideEffects": true,
    "use": [
      "appdir/node_modules/style-loader/dist/cjs.js",
      {
        "loader": "appdir/node_modules/css-loader/dist/cjs.js",
        "options": {
          "importLoaders": 1
        }
      },
      {
        "loader": "appdir/node_modules/postcss-loader/src/index.js",
        "options": {
          "ident": "postcss",
          "postcss": {}
        }
      }
    ]
  },
  {
    "test": {},
    "loader": "appdir/node_modules/file-loader/dist/cjs.js",
    "query": {
      "name": "static/media/[name].[hash:8].[ext]"
    }
  },
  {
    "test": {},
    "loader": "appdir/node_modules/@storybook/core/node_modules/url-loader/dist/cjs.js",
    "query": {
      "limit": 10000,
      "name": "static/media/[name].[hash:8].[ext]"
    }
  }
]

@stale
Copy link

stale bot commented Jul 25, 2020

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!

@stale stale bot added the inactive label Jul 25, 2020
@gaurav5430
Copy link
Author

looking at the pace that things are evolving, I am hoping that this would automatically be resolved in some later versions of storybook

@stale stale bot removed the inactive label Jul 25, 2020
@stale
Copy link

stale bot commented Aug 16, 2020

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!

@stale stale bot added the inactive label Aug 16, 2020
@stale
Copy link

stale bot commented Sep 20, 2020

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

@stale stale bot closed this as completed Sep 20, 2020
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

2 participants