7

我试图从 Create React App 3 (CRA)、Typescript、Material UI 和 styled-components 设置 react-styleguidist (RSG)。我被困在这个错误上:

./node_modules/react-styleguidist/lib/client/rsg-components/ReactExample/ReactExample.js
Module not found: Can't resolve 'rsg-components/Wrapper' in '/Users/ofj/code/new-core-web/node_modules/react-styleguidist/lib/client/rsg-components/ReactExample'

我按照文档设置了 MUI 主题和样式组件的包装器:
https ://react-styleguidist.js.org/docs/thirdparties.html#styled-components

/styleguidist/MuiThemeWrapper.tsx

const muiTheme = getMuiTheme({});
const MuiThemeWrapper = ({ children, ...rest }) => (
    <MuiThemeProvider muiTheme={muiTheme}>
        <ThemeProvider theme={theme}>
            {children}
        </ThemeProvider>
    </MuiThemeProvider>
);

export default MuiThemeWrapper;

我的 styleguidist 配置:

/styleguidist.config.js

const path = require('path');
module.exports = {
    components: "src/components/**/layout.{js,jsx,ts,tsx}",
    propsParser: require('react-docgen-typescript').withCustomConfig(
        './tsconfig.json'
      ).parse,
    serverPort: 6161,
    styleguideComponents: {
      Wrapper: path.join(__dirname, 'styleguidist/MuiThemeWrapper.jsx')
    }
};

我的 tsconfig 遵循标准 CRA / MUI 建议
https://material-ui.com/guides/typescript/

tsconfig.json

{
  "compilerOptions": {
    "noImplicitAny": true,
    "noImplicitThis": true,
    "strictNullChecks": true,
    "baseUrl": "src",
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "checkJs": false,
    "pretty": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "exclude": [
    "node_modules"
  ],
  "types": [
    "./node_modules/@types/"
  ]
}

我没有自定义 webpack/babel 配置设置,因为我不知道如何并且不会弄乱 TS 转译。也许这是为了让 RSG 工作而缺少的东西......?还是 rsg-components/ReactExample/ReactExample.js 的错误是一个错误?

4

1 回答 1

1

我让它工作了,希望其他人也能发现这很有用,因为到目前为止,几乎没有而且只有非打字稿示例配置。

我的设置需要注意的事项:

  • react mui 应用在src/,组件在src/components/,使用modules:webpack 配置查看src/绝对导入。
  • 应用程序是使用 react 应用程序创建器创建的。
  • tsconfig.jsonnoEmit自动创建(稍后专门为“ts-loader”覆盖,见下文);下面显示了一个重要的例外/补充。
  • 没有单独的 webpack 和 babel 配置,包含在styleguide.config.js.

tsconfig.json是样板,除了这里的 gempaths:'rsg-components/*'需要手动添加——它隐藏在React Styleguidist 的 Cookbook中。没有它,我们需要在 webpack 配置中使用别名定义,包括替换包装器!有了正确的paths定义,tsconfig.json事情终于开始正确到位。

{
  "compilerOptions": {
    "paths": {
      "rsg-components/*": [
        "node_modules/react-styleguidist/lib/client/rsg-components/*"
      ]
    }
  }
}

styleguide.config.js位于项目的顶级目录中:

const path = require('path')

module.exports = {
    components: [
        'src/components/**/*.{ts,tsx}',
        'src/models/**/*.ts',
    ],
    ignore: [
        'src/**/index.{ts,tsx}',
    ],
    // We need to override how to decide on what an example file is, in order
    // to remove default which tries to document undocumented components. Ugh.
    // So, only document components for which we also have an explicit
    // documentation file named the same as the component file, but ending in
    // ".md" instead.
    getExampleFilename: (cpath) => {
        return cpath.replace(/\.(tsx?)$/, '.md')
    },
    // Show import commands without the component filename extension and only
    // for the module; also remove the first "src/" path component.
    getComponentPathLine: (cpath) => {
        const cname = ['.tsx', '.ts'].reduce((name, ext) => path.basename(name, ext), cpath)
        const cdir = path.dirname(cpath).replace(/^src\//, '')
        return `import { ${cname} } from ${cdir}`
    },
    // How uncivilized: do not list components lacking an example.
    skipComponentsWithoutExample: true,
    // Always expand the props and methods of components.
    usageMode: 'expand',
    // Support rendering prop types of typescript components.
    propsParser: require('react-docgen-typescript').withCustomConfig(
        './tsconfig.json',
        {
            "compilerOptions": { "noEmit": false },
        }
    ).parse,
    // Replace the standard wrapper for example component usage code with our
    // own wrapper which brings in the Material UI theme.
    styleguideComponents: {
        Wrapper: path.join(__dirname, 'styleguidist/MuiThemeWrapper.tsx')
    },
    // Tell webpack what to look for and where and how to load it.
    webpackConfig: {
        resolve: {
            extensions: ['.tsx', '.ts', '.js'],
            // https://webpack.js.org/configuration/resolve/#resolvemodules;
            // we're allowing absolute imports to be satisfied from the src/
            // directory.
            modules: [
                path.resolve(__dirname, 'src/'), 
                'node_modules'
            ],
            alias: {
                // Could also be covered by a modules clause, but we are
                // sticking with an alias instead to cover only exactly
                // absolute "styleguidist/..." imports.
                'styleguidist': path.join(__dirname, 'styleguidist'),
            }
        },
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    exclude: /node_modules/,
                    use: [
                        {
                            loader: 'babel-loader',
                            options: {
                                presets: [
                                    "@babel/preset-env",
                                    "@babel/react",
                                ]
                            },
                        },
                        {
                            loader: 'ts-loader',
                            options: {
                                // Important! Avoids "Error: TypeScript emitted no output for..." errors
                                compilerOptions: {
                                    noEmit: false,
                                },
                            },
                        },
                    ],
                },
                {
                    test: /\.css$/,
                    loader: 'style-loader!css-loader?modules',
                },
                {
                    test: /\.svg$/,
                    loader: 'url-loader',
                },
                {
                    test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
                    use: [
                        {
                            loader: 'url-loader',
                            options: {
                                name: '[name].[ext]',
                                outputPath: 'fonts/',
                            }
                        },
                    ]
                }
            ]
        },
    }
}
  • styleguidist/该子句可以涵盖绝对导入modules:,但在这种情况下,我选择了别名。你可能会有不同的判断:)
  • 我正在设置一个相当严格的制度,只用示例记录组件;如果您不想要,请摆脱它。
  • 困难在于使用正确的加载器配置 webpack;我启用了 typescript、TSX 和 JSX,以及提取字体资源。
  • 重要提示:包装器位于styleguidist/MuiThemeWrapper.tsx.

这就是我的包装styleguidist/MuiThemeWrapper.tsx

(对于 MUI v5,请参阅MUI v5 + React styleguidist + ScopedCSSBaseline + createTheme styleOverrides: body fontSize change not working的答案)

import React from 'react'

import "fontsource-roboto/400.css"
import "fontsource-roboto/500.css"
import "fontsource-roboto/700.css"
import "fontsource-roboto-mono/400.css"

import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles'
import CssBaseline from '@material-ui/core/CssBaseline'

const muiTheme = createMuiTheme({})

const MuiThemeWrapper = ({children}) => (
    <ThemeProvider theme={muiTheme}>
        <CssBaseline />
        {children}
    </ThemeProvider>
)

export default MuiThemeWrapper
  • 在我的 react+Material UI 项目中明确引入我需要的 Roboto 字体。
  • 应用 CSS 基线定义,否则font-familys 将无法正确定义。
于 2020-10-15T11:24:24.120 回答