react-styleguidist icon indicating copy to clipboard operation
react-styleguidist copied to clipboard

Examples not displayed when using react-scripts@5

Open malcolm-kee opened this issue 3 years ago • 15 comments

Current behavior

Examples in .md files is not displayed when using react-styleguidist with react-scripts@5.

To reproduce

https://github.com/malcolm-kee/react-styleguidist-cra5-md-bug

Expected behavior

The examples should be displayed.

malcolm-kee avatar Dec 18 '21 04:12 malcolm-kee

hello i have the same issue, someone can help on this please ?

package.json :

{
  "name": "cms",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.1",
    "@testing-library/react": "^12.1.2",
    "@testing-library/user-event": "^13.5.0",
    "@types/jest": "^27.0.3",
    "@types/node": "^16.11.17",
    "@types/react": "^17.0.38",
    "@types/react-dom": "^17.0.11",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "5.0.0",
    "typescript": "^4.5.4",
    "web-vitals": "^2.1.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "styleguide": "styleguidist server",
    "styleguide:build": "styleguidist build"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "react-docgen-typescript": "^2.2.2",
    "react-styleguidist": "^11.1.7",
    "webpack": "^5.65.0"
  }
}

styleguide.config.js :

module.exports = {
    components: 'src/components/**/*.{jsx,tsx}',
    propsParser: require('react-docgen-typescript').withCustomConfig(
        './tsconfig.json'
    ).parse
};

aanikid avatar Dec 25 '21 11:12 aanikid

Running into the same issue with CRA 5 (which comes with webpack 5). All components are blank: Screenshot 000023@2x

sshquack avatar Jan 05 '22 02:01 sshquack

Problem

I debugged this a bit and the problem here seems to be, the way that Webpack 5 is handling assets. It has a new Asset Module mechanism, which determines how webpack will bundle/treat an import. For Markdown files this seems to be asset/resource by default, i.e. it will "copy" the file to a hashed location and make the require return the URL to it.

This is problematic, since react-styleguidist actually specifies a custom inline loader (see getExamples.ts#31 and examples-loader.ts). This loader will return JavaScript, which is now handled by Webpack wrongly as an asset. The solution would be to inform webpack to treat that result as JavaScript via the asset type javascript/auto (see Workaround below).

Also it seems there is a second problem, that in the JavaScript code, that the examples-loader generate absolute paths are used (see examples-loader.ts#19-20). Those seem to no longer resolve properly and will cause those two modules (requireInRuntime and evalInContext) to not resolve properly. It seems relative paths would work fine (see workaround below).

Workaround

Tested with [email protected]

To workaround this, you can put the following into your styleguide.config.js:

const webpack = require('webpack');

const webpackConfig = {
  module: {
    rules: [
      {
        test: /\.examples\.md$/, // see comment below!
        type: 'javascript/auto', // Tell webpack to interpret the result from examples-loader as JavaScript
      },
    ],
  },
  plugins: [
    // Rewrites the absolute paths to those two files into relative paths
    new webpack.NormalModuleReplacementPlugin(
      /react-styleguidist\/lib\/loaders\/utils\/client\/requireInRuntime$/,
      'react-styleguidist/lib/loaders/utils/client/requireInRuntime'
    ),
    new webpack.NormalModuleReplacementPlugin(
      /react-styleguidist\/lib\/loaders\/utils\/client\/evalInContext$/,
      'react-styleguidist/lib/loaders/utils/client/evalInContext'
    ),
  ],
};

module.exports = {
  webpackConfig,
  // The rest of your styleguidist config
};

Couple of notes to this workaround:

  • If you already specify a webpackConfig in your styleguide.config.js (e.g. because you are using craco and want to inject its webpack config) make sure to properly merge the rules and plugins into that config.
  • All my styleguide examples end on .examples.md (using the getExampleFilename configuration). You must make sure to write a test that will match your example markdown files (and also not accidentally other markdown files if you have them in your code). If you can't achieve this with the test option, in the worst case you'd need to use the include and exclude option to include and exclude individual files.

timroes avatar Jan 15 '22 22:01 timroes

Hello Any plans to fix this issue? Still happens on v11.2.0 for me

IKamyshew avatar Feb 15 '22 13:02 IKamyshew

Same for me

hugo-valcourt avatar Feb 15 '22 13:02 hugo-valcourt

Maybe anyone find a solution? because I'm having same problem :/

ourpower avatar Feb 18 '22 14:02 ourpower

@timroes thanks for the workaround, helped me a lot to sort it out easily.

avishka40 avatar Mar 09 '22 04:03 avishka40

Thanks @timroes for this ❤️

It took me some time to make this work with Typescript and Tailwind CSS but it was totally worth it!

In case someone is interested here is a gist for that.

nebomilic avatar Mar 10 '22 18:03 nebomilic

I'm struggling with this issue myself - we don't use typescript, so in that case can anyone show me how to use the gist for .js as opposed to .ts?

alexdunham avatar Jun 01 '22 00:06 alexdunham

For those struggling to hook up existing webpack config with the workaround, adding the below to the styleguide.config.js worked for me. It';s not an ideal solution but works for me while waiting for this to get resolved on the styleguidist end.

   dangerouslyUpdateWebpackConfig(config) { 
     config.module.rules.push({
        test: /.\.md$/,
        type: "javascript/auto"
      });
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/requireInRuntime$/,
          "react-styleguidist/lib/loaders/utils/client/requireInRuntime"
        )
      );
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/evalInContext$/,
          "react-styleguidist/lib/loaders/utils/client/evalInContext"
        )
      );
      return config;
    },
   ...the rest of your config

alexdunham avatar Jun 07 '22 01:06 alexdunham

For those struggling to hook up existing webpack config with the workaround, adding the below to the styleguide.config.js worked for me. It';s not an ideal solution but works for me while waiting for this to get resolved on the styleguidist end.

   dangerouslyUpdateWebpackConfig(config) { 
     config.module.rules.push({
        test: /.\.md$/,
        type: "javascript/auto"
      });
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/requireInRuntime$/,
          "react-styleguidist/lib/loaders/utils/client/requireInRuntime"
        )
      );
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/evalInContext$/,
          "react-styleguidist/lib/loaders/utils/client/evalInContext"
        )
      );
      return config;
    },
   ...the rest of your config

Working solution, thanks!

gioxoay avatar Jun 15 '22 02:06 gioxoay

For those struggling to hook up existing webpack config with the workaround, adding the below to the styleguide.config.js worked for me. It';s not an ideal solution but works for me while waiting for this to get resolved on the styleguidist end.

   dangerouslyUpdateWebpackConfig(config) { 
     config.module.rules.push({
        test: /.\.md$/,
        type: "javascript/auto"
      });
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/requireInRuntime$/,
          "react-styleguidist/lib/loaders/utils/client/requireInRuntime"
        )
      );
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/evalInContext$/,
          "react-styleguidist/lib/loaders/utils/client/evalInContext"
        )
      );
      return config;
    },
   ...the rest of your config

Thank you for this; very helpful!

But, two remarks:

  • Your comment ...the rest of your config is not 100% obvious. For anyone who is puzzled here: (1) I needed to add const webpack = require("webpack") at the head of the file. (2) This new code goes inside the module.exports = { ... }, followed by rest of the existing content.

  • This fixes the problem of examples not displaying after updating from react-scripts 4.0.3 to 5.0.1. But, even though the content is being served correctly, I still got a FAIL Failed to compile error, followed by many lines of "require stack" and other details. Fixing each just required carefully searching the messages for which dependencies were causing each problem, updating them, and also deleting and rebuilding node_modules.

deg avatar Aug 30 '22 11:08 deg

For those struggling to hook up existing webpack config with the workaround, adding the below to the styleguide.config.js worked for me. It';s not an ideal solution but works for me while waiting for this to get resolved on the styleguidist end.

   dangerouslyUpdateWebpackConfig(config) { 
     config.module.rules.push({
        test: /.\.md$/,
        type: "javascript/auto"
      });
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/requireInRuntime$/,
          "react-styleguidist/lib/loaders/utils/client/requireInRuntime"
        )
      );
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/evalInContext$/,
          "react-styleguidist/lib/loaders/utils/client/evalInContext"
        )
      );
      return config;
    },
   ...the rest of your config

Thank you for this; very helpful!

But, two remarks:

  • Your comment ...the rest of your config is not 100% obvious. For anyone who is puzzled here: (1) I needed to add const webpack = require("webpack") at the head of the file. (2) This new code goes inside the module.exports = { ... }, followed by rest of the existing content.
  • This fixes the problem of examples not displaying after updating from react-scripts 4.0.3 to 5.0.1. But, even though the content is being served correctly, I still got a FAIL Failed to compile error, followed by many lines of "require stack" and other details. Fixing each just required carefully searching the messages for which dependencies were causing each problem, updating them, and also deleting and rebuilding node_modules.

Hey there. By 'the rest of your config' I am referring to any other configuration you use from here. Things like sections, styles etc. You're right, you do need to import webpack, since you are referring to it in the config overrides. You can see more examples of config for react-styleguidist in the gist that @nebomilic posted above :)

alexdunham avatar Aug 30 '22 19:08 alexdunham

Workaround for JavaScript + TailwindCSS + Styleguidist + Create React App 5

I was also stuck on the issue of getting TailwindCSS to work with Styleguidist and CRA for my component library but using JavaScript. I tried using the dangerouslyUpdateWebpackConfig option that @alexdunham provided and while this worked properly for getting Styleguidist working itself, once I published the package as an ES6 module it caused loader issues when I imported the package into other apps (specifically RedwoodJS apps, which is a framework using React). This solution is building on what @timroes and @nebomilic created for their apps and hopefully I can give more info for those who want to use their component library in other applications.

I can't publish the full repo I was working on but here's a gist of my styleguide config that allows a Styleguidist component library to work properly on its own, while also being able to publish it as a package and use it in other apps. It's important to make the following other changes to get Styleguidist working:

  1. In your package.json make sure you add "type": "module" to make sure we get the benefits of ES6 syntax while also allowing us to use TailwindCSS, which does not support ES6 syntax
  2. Change your CommonJS files to end in .cjs. This means your repo should have styleguide.config.cjs, tailwind.config.cjs (can use default config), and postcss.config.cjs at the root of your repo. My postcss.config.cjs had the following code:
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}
  1. Make sure your components are using .jsx extension. I don't know why using a .js extension never worked for me but it would always cause issues when trying to get Styleguidist to run. Maybe this is because of the mixing of CommonJS and ES6 syntax within my monorepo. You can try using .js but Styleguidist would always throw an error at all of components when trying to do this.
  2. Make sure you have the necessary dev dependencies installed in your repo that are listed in the styleguide config (like @babel/preset-env, @babel/preset-react, url-loader, etc)
  3. After publishing your component library as a package, you may need to edit the webpack of the app using your component library to use babel-loader. In my case, for a RedwoodJS app I had to add the following to the webpack.config.js to properly load the components:
    config.module.rules.push({
      test: /\.(js|jsx)$/,
      loader: 'babel-loader',
      options: { presets: ['@babel/preset-env',['@babel/preset-react', {"runtime": "automatic"}]]},
      resolve: {
        fullySpecified: false,
      },
    })

Please note that you may have to modify my styleguide config in order to get them to work for your component library. For example, I use .jsx components so if you're not using .jsx this solution may not work and you should try modifying components: 'src/components/**/[A-Z]*.jsx' and same deal with

resolve: {
        extensions: ['.js','.jsx'],
    }

and

       {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                options: { presets: ['@babel/preset-env',['@babel/preset-react', {"runtime": "automatic"}]]},
            }

Make sure your Tailwind config knows to look for .jsx files instead of just .js files too!

jahabeebs avatar Jan 10 '23 21:01 jahabeebs

For those struggling to hook up existing webpack config with the workaround, adding the below to the styleguide.config.js worked for me. It';s not an ideal solution but works for me while waiting for this to get resolved on the styleguidist end.

   dangerouslyUpdateWebpackConfig(config) { 
     config.module.rules.push({
        test: /.\.md$/,
        type: "javascript/auto"
      });
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/requireInRuntime$/,
          "react-styleguidist/lib/loaders/utils/client/requireInRuntime"
        )
      );
      config.plugins.push(
        new webpack.NormalModuleReplacementPlugin(
          /react-styleguidist\/lib\/loaders\/utils\/client\/evalInContext$/,
          "react-styleguidist/lib/loaders/utils/client/evalInContext"
        )
      );
      return config;
    },
   ...the rest of your config

my man 👏 👏 👏 .... about 3 days in with me and a colleague and this.. this was the solution! how can i buy you a coffee or something at least??

crowell-tailord avatar Aug 11 '23 17:08 crowell-tailord