如何使用 Next.js、Ant Design、Less 和 TypeScript 配置 Storybook.js Webpack

Posted

技术标签:

【中文标题】如何使用 Next.js、Ant Design、Less 和 TypeScript 配置 Storybook.js Webpack【英文标题】:How can I configure Storybook.js Webpack with Next.js, Ant Design, Less, and TypeScript 【发布时间】:2021-02-21 14:14:42 【问题描述】:

我正在尝试将 Storybook 配置为与 Next.js、Ant Design、Less 和 TypeScript 一起使用。我已经按照我可能找到的所有教程进行操作,但没有任何效果。我将发布我的配置和我遇到的错误......

我的.storybook/main.js 看起来像:

const path = require('path');

module.exports = 
  stories: ['../**/*.stories.mdx', '../**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/preset-ant-design',
  ],
  presets: [path.resolve(__dirname, './next-preset.js')],
;

我的.storybook/next-preset.js 看起来像:

const path = require('path');

module.exports = 
  webpackFinal: async (baseConfig, options) => 
    // Modify or replace config. Mutating the original reference object can cause unexpected bugs.
    const  module =   = baseConfig;

    const newConfig = 
      ...baseConfig,
      module: 
        ...module,
        rules: [...(module.rules || [])],
      ,
    ;

    // TypeScript with Next.js
    newConfig.module.rules.push(
      test: /\.(ts|tsx)$/,
      include: [
        path.resolve(__dirname, '../components'),
        path.resolve(__dirname, '../stories'),
      ],
      use: [
        
          loader: 'babel-loader',
          options: 
            presets: ['next/babel'],
            plugins: ['react-docgen'],
          ,
        ,
      ],
    );
    newConfig.resolve.extensions.push('.ts', '.tsx');

    // // SCSS
    // newConfig.module.rules.push(
    //   test: /\.(s*)css$/,
    //   loaders: ['style-loader', 'css-loader', 'sass-loader'],
    //   include: path.resolve(__dirname, '../styles/global.scss'),
    // );

    // Less
    newConfig.module.rules.push(
      test: /\.less$/,
      use: [
        'style-loader',
        'css-loader',
        
          loader: 'less-loader',
          options: 
            javascriptEnabled: true,
          ,
        ,
      ],
      include: path.resolve(__dirname, '../assets/styles'),
    );

    //
    // CSS Modules
    // Many thanks to https://github.com/storybookjs/storybook/issues/6055#issuecomment-521046352
    //

    // First we prevent webpack from using Storybook CSS rules to process CSS modules
    newConfig.module.rules.find(
      (rule) => rule.test.toString() === '/\\.css$/'
    ).exclude = /\.module\.css$/;

    // Then we tell webpack what to do with CSS modules
    newConfig.module.rules.push(
      test: /\.module\.css$/,
      include: [
        path.resolve(__dirname, '../common/components'),
        path.resolve(__dirname, '../common/layout'),
      ],
      use: [
        'style-loader',
        
          loader: 'css-loader',
          options: 
            importLoaders: 1,
            modules: true,
          ,
        ,
      ],
    );

    return newConfig;
  ,
;

我的.storybook/preview.js 看起来像:

require('../assets/styles/antd.less');

export const parameters = 
  actions:  argTypesRegex: '^on[A-Z].*' ,
;

我的antd.less 文件如下所示:

@import '~antd/dist/antd.less';

@primary-color: red;

最后,我的next.config.js 看起来像:

const withLess = require('@zeit/next-less');
const withCSS = require('@zeit/next-css');

module.exports = withCSS(
  cssModules: true,
  cssLoaderOptions: 
    importLoaders: 1,
    localIdentName: '[local]___[hash:base64:5]',
  ,
  ...withLess(
    lessLoaderOptions: 
      javascriptEnabled: true,
    ,
  ),
);

我在尝试运行 Storybook 时遇到的错误是:

ERROR in ./assets/styles/antd.less (./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js??ref--11-2!./node_modules/style-loader/dist/cjs.js!./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js??ref--16-2!./assets/styles/antd.less)
Module build failed (from ./node_modules/less-loader/dist/cjs.js):


import api from "!../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js";
              ^
Unrecognised input
      in /assets/styles/antd.less (line 1, column 16)
 @ ./assets/styles/antd.less 2:12-284 9:17-24 13:7-14 45:20-27 47:4-60:5 49:6-59:7 50:38-45 56:26-33 58:21-28 68:15-22
 @ ./.storybook/preview.js
 @ ./.storybook/preview.js-generated-config-entry.js
 @ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/frameworks/common/config.js-generated-other-entry.js ./node_modules/@storybook/addon-docs/dist/frameworks/react/config.js-generated-other-entry.js ./node_modules/@storybook/addon-links/dist/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/preset/addArgs.js-generated-other-entry.js ./node_modules/@storybook/addon-backgrounds/dist/preset/defaultParameters.js-generated-other-entry.js ./.storybook/preview.js-generated-config-entry.js ./.storybook/generated-stories-entry.js (webpack)-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined

任何帮助将不胜感激。如果我从 Storybook 配置中省略所有 Less 配置,我可以让 Storybook 工作,但是我对 Ant Design 的自定义都没有通过。

编辑 1: 我的相关依赖项是:

"css-loader": "^5.0.1",
"less-loader": "^5.0.0",
"style-loader": "^2.0.0",
"ts-loader": "^8.0.10",
"typescript": "^4.0.5",
"@storybook/addon-actions": "^6.0.28",
"@storybook/addon-essentials": "^6.0.28",
"@storybook/addon-links": "^6.0.28",
"@storybook/preset-ant-design": "0.0.1",
"@storybook/react": "^6.0.28",
"less": "^3.12.2",
"next": "^9.5.5",
"@zeit/next-css": "^1.0.1",
"@zeit/next-less": "^1.0.1",
""antd": "^4.8.0",

编辑 2: 这是指向GitHub repo 的链接,您应该能够通过运行npm installnpm run storybook 来重现该问题。

【问题讨论】:

你有可复现的仓库吗? @tmhao2005 我没有。不过,我可以试着弄一个。 酷。告诉我你已经完成了 @tmhao2005 here 是一个仓库。您只需要运行npm installnpm run storybook 即可重现该问题。如果它工作正常,您应该能够看到一个红色的主按钮故事,而不是默认的蓝色。 是问题还是项目? 【参考方案1】:

我发现问题出在使用原始的 less webpack 加载器配置。但移除它并不是你让它工作的唯一方法。

您必须执行以下几个步骤:

在添加之前删除原来的 less 加载器:
baseConfig.module.rules = baseConfig.module.rules.filter(
  f => f.test.toString() !== '/\\.less$/'
);
通过包含 antd 更少的文件:

  test: /\.less$/,
  include: [
    /[\\/]node_modules[\\/].*antd/,
    // ...
  ],

简而言之,这是您的最终配置:
const path = require('path');

module.exports = 
  webpackFinal: async (baseConfig, options) => 
    const  module =   = baseConfig;
    
    // Remove original less loader
    baseConfig.module.rules = baseConfig.module.rules.filter(
      f => f.test.toString() !== '/\\.less$/'
    );

    const newConfig = 
      ...baseConfig,
      module: 
        ...module,
        rules: [...(module.rules || [])],
      ,
    ;
    
    // ...

    // Less
    newConfig.module.rules.push(
      test: /\.less$/,
      include: [
        // Include antd to rebuild
        /[\\/]node_modules[\\/].*antd/,
        path.resolve(__dirname, '../assets/styles'),
      ],
      use: [
        'style-loader',
        'css-loader',
        
          loader: 'less-loader',
          options: 
            javascriptEnabled: true,
          ,
        ,
      ],
    );

    //...

    return newConfig;
  ,
;

【讨论】:

非常感谢您的回答。虽然您的答案确实让 Storybook 构建和运行,但它实际上并没有将自定义主题应用于 Storybook 组件。我发现我需要进行更改并删除我已经尝试在 ./storybook/main.js 中使用的 Ant Design 预设。您可以在 GitHub 存储库中查看我的最终解决方案。我会接受这个答案,因为它解决了我的根本问题。但是,如果您也想检查一下,我还有另一个问题。我将发布另一条带有链接的评论。 Here is the other issue 我现在有。 Webpack/CSS 无法将绝对图像路径解析为 public/ 目录中的图像。 我给你另一个建议 感谢@tmhao2005 和@gdvander 的帮助——不过,我在这个设置中又发现了一个问题。将我的项目部署到 Heroku 时,构建通过,但应用程序在运行时崩溃。日志报告:Error: Cannot find module 'webpack' 我已将其范围缩小到 Heroku 自动运行npm prune,这消除了所需的 devDependency。当我将所有与 @storybook 相关的包移动到 dependencies 时,这一切都不会发生。到目前为止,除了通过在 Heroku 中设置 NPM_CONFIG_PRODUCTION=false 来关闭依赖修剪之外,我还没有解决这个问题 我根据我的上一条评论打开了 Storybook 的问题:github.com/storybookjs/storybook/issues/13325

以上是关于如何使用 Next.js、Ant Design、Less 和 TypeScript 配置 Storybook.js Webpack的主要内容,如果未能解决你的问题,请参考以下文章

P10:如何使用Ant Design UI

@ant-design/charts 的 Next.js 问题,错误

Next.js 和 Ant Design Dragger:已部署实例上的文件上传失败

Ant-Design CSS 未正确加载

如何在 ant-design 组件中使用 css-in-js?

如何使用布尔值在 ant design 复选框中呈现默认值?