用storybook+webpack搭建简单react组件库

746 阅读1分钟

用storybook+webpack搭建react组件库

storybook 可以快速构建一个ui组件库的开发环境,本文将介绍完整的过程和一些踩的坑

  1. 初始化storybook项目

npx storybook init

初始化项目的时候可以选择创建webpack-react的项目

  1. 安装并启动项目

yarn

yarn storybook

如果启动有问题,需要手动安装一下react和react-dom

yarn add react react-dom --save

  1. 添加webpack配置,例如添加支持使用less文件的配置
  • 安装包

yarn add css-loader less less-loader style-loader

  • 修改.storybook下面的main.js
const path = require('path');

module.exports = {
  "stories": [
    "../stories/**/*.stories.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions"
  ],
  "framework": "@storybook/react",
  webpackFinal: async (config, { configType }) => {
    config.module.rules.push({
      test: /.less$/,
      use: [
        {
          loader: "style-loader",
        },
        {
          loader: "css-loader",
          options: {
            importLoaders: 2,
            modules: {
              localIdentName: "[local]--[hash:base64:5]",
              exportLocalsConvention: "camelCase",
            },
          },
        },
        {
          loader: "less-loader",
        },
      ],
      include: path.resolve(__dirname, '../'),
    });
    return config;
  }
}

到这里启动项目可能会报 this.getoptions is not a function,这是因为storybook默认使用的是webpack4,不支持高版本的style-loader或者less-loader

  1. 支持webpack5

yarn add @storybook/builder-webpack5 @storybook/manager-webpack5 --save-dev

再次修改.storybook下的main.js

const path = require('path');

module.exports = {
  "stories": [
    "../stories/**/*.stories.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions"
  ],
  "framework": "@storybook/react",
  core: {
      builder: 'webpack5',
  },
  webpackFinal: async (config, { configType }) => {
    // 同上,需要的webpack配置
  }
}
  1. 在stories下编写自己的组件,脚手架搭的项目下也有一些例子

1665653310584.jpg

  1. 打包
  • 安装webpack的相关包

yarn add webpack webpack-cli clean-webpacl-plugin --save

  • 根目录下添加 webpack.config.js
const path = require('path');
const fs = require('fs');
const paths = require('./paths');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

const useTypeScript = fs.existsSync(paths.appTsConfig);

module.exports = {
    mode: 'production',
    entry: {
        index: './stories/index.js',
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, "lib"),
        publicPath: "/assets/",
        libraryTarget: 'umd'
    },
    module: {
        rules: [
            {
                test: /.(js|jsx|ts|tsx)$/,
                include: [
                    path.resolve(__dirname, "stories")
                ],
                exclude: /node_modules/,
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/preset-env', '@babel/preset-react'],
                    plugins: ['@babel/plugin-transform-runtime']
                },
            },
            {
                test: /.(less)$/,
                use: [
                    'style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            importLoaders: 2,
                            modules: {
                                // auto: /.module.\w+$/i,
                                localIdentName: "[local]--[hash:base64:5]",
                                exportLocalsConvention: "camelCase",
                            },
                        }
                    },
                    'less-loader'
                ],
            }
        ],
    },
    externals: {
        'react': 'React',
        'react-dom': 'ReactDOM',
    },
    resolve: {
        extensions: paths.moduleFileExtensions
            .map(ext => `.${ext}`)
            .filter(ext => useTypeScript || !ext.includes('ts')),
    },
    plugins: [
        new webpack.DefinePlugin(env.stringified),
        new CleanWebpackPlugin(),
    ],
};
  • 修改package.json
    "scripts": {
      "test": "echo "Error: no test specified" && exit 1",
      "storybook": "start-storybook -p 6006",
      "build-storybook": "build-storybook",
      "build": "webpack"
    },