组件开发脚手架搭建(storybook+rollup+react)

364 阅读3分钟

1. 搭建storybook环境

# 安装rollup
sudo npm install --global rollup
# 初始化react项目
npx create-react-app ./ --template typescript
# 初始化storybook
npx -p @storybook/cli sb init --type react
# 支持ts、sass等
npm install -D @storybook/preset-create-react-app @storybook/react
npm install -D @storybook/preset-scss css-loader sass sass-loader style-loader

启动

npm run storybook

2. lerna进行多包管理

# 安装lerna
npm install lerna -g
# 初始化lerna
lerna init
# 增加组件
lerna create utils  
lerna create sierpinski  

修改启动目录

.storybook/main.js

module.exports = {
  "stories": [
    // "../src/**/*.stories.mdx",
  	// 修改目录
    '../packages/**/*.stories.@(js|jsx|ts|tsx)'
  ],
  "addons": [
    "@storybook/preset-scss",
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions"
  ],
  "framework": "@storybook/react",
  "core": {
    "builder": "@storybook/builder-webpack5"
  }
}

增加stories文件

packages/sierpinski/lib/index.stories.tsx

import React from 'react'
import { ComponentStory, ComponentMeta } from '@storybook/react'

const Component = () => {
    return  <div>button</div>
}

export default {
  title: 'Component',
  component: Component,
} as ComponentMeta<typeof Component>

//storybook 定义的一种args写法,可以在界面生成配置界面
const Template: ComponentStory<typeof Component> = (args: any) => <Component {...args} />

//示例一
export const defaultButton = Template.bind({})
defaultButton.args = {
  bgcolor: '#f0f0f0',
  color: '#000000',
  btnname: '按钮',
}
 
//示例二
export const BlackButton = Template.bind({})
BlackButton.args = {
  bgcolor: '#333333',
  color: '#ffffff',
  btnname: '按钮',
}

运行看下效果

3. rollup编译并发布组件

安装rollup、babel、cross-env相关插件

npm install -D rollup rollup-plugin-babel rollup-plugin-commonjs rollup-plugin-node-resolve rollup-plugin-replace @rollup/plugin-image rollup-plugin-terser rollup-plugin-postcss postcss cssnano postcss-nested postcss-simple-vars

npm install -D @babel/cli @babel/core @babel/plugin-external-helpers @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-proposal-object-rest-spread @babel/plugin-transform-react-jsx @babel/plugin-transform-runtime @babel/preset-env @babel/preset-react @babel/preset-typescript

npm install -D cross-env rollup-plugin-typescript2 @rollup/plugin-json rollup-plugin-dts

# 报错需要全局安装
sudo npm i cross-env -g

配置rollup

// rollup.config.js

// Rollup plugins
// babel插件用于处理es6代码的转换,使转换出来的代码可以用于不支持es6的环境使用
import babel from 'rollup-plugin-babel'
// resolve将我们编写的源码与依赖的第三方库进行合并
import resolve from 'rollup-plugin-node-resolve'
// 解决rollup.js无法识别CommonJS模块
import commonjs from 'rollup-plugin-commonjs'
// 全局替换变量比如process.env
import replace from 'rollup-plugin-replace'
// 使rollup可以使用postCss处理样式文件scss、css等
import postcss from 'rollup-plugin-postcss'
import autoprefixer from 'autoprefixer'
// 可以处理组件中import图片的方式,将图片转换成base64格式,但会增加打包体积,适用于小图标
import image from '@rollup/plugin-image'
// 压缩打包代码(这里弃用因为该插件不能识别es的语法,所以采用terser替代)
// import { uglify } from 'rollup-plugin-uglify';
// 压缩打包代码
import { terser } from 'rollup-plugin-terser'
// PostCSS plugins 处理css定义的变量
import simplevars from 'postcss-simple-vars'
// 处理scss嵌套样式写法
import nested from 'postcss-nested'
// 替代cssnext
import postcssPresetEnv from 'postcss-preset-env'
// css代码压缩
import cssnano from 'cssnano'
// 支持typescript
import typescript from 'rollup-plugin-typescript2'
// 支持rollup.js导入json模块
import json from '@rollup/plugin-json'
// 用于打包生成*.d.ts文件
import dts from 'rollup-plugin-dts'
// 引入package
// import pkg from "./package.json";

const env = process.env.NODE_ENV
const PACKAGE_ROOT_PATH = process.cwd()

const config = [{
  // 入口文件我这里在components下统一导出所有自定义的组件
  input: `${PACKAGE_ROOT_PATH}/src/index.tsx`,
  // 输出文件夹,可以是个数组输出不同格式(umd,cjs,esm...)通过env是否是生产环境打包来决定文件命名是否是.min
  output: [
    {
      file: `${PACKAGE_ROOT_PATH}/dist/index.esm.js`,
      format: 'esm',
    },
    {
      file: `${PACKAGE_ROOT_PATH}/dist/index.js`,
      format: 'cjs',
    },
  ],
  // 注入全局变量比如jQuery的$这里只是尝试 并未启用
  // globals: {
  //   react: 'React',// 这跟external 是配套使用的,指明global.React即是外部依赖react
  //   antd: 'antd'
  // },
  // 自定义警告事件,这里由于会报THIS_IS_UNDEFINED警告,这里手动过滤掉
  onwarn: function (warning) {
    if (warning.code === 'THIS_IS_UNDEFINED') {
      return
    }
  },
  // 将模块视为外部模块,不会打包在库中
  external: ['react', 'react-dom'],
  // 插件
  plugins: [
    typescript(),
    image(),
    postcss({
      plugins: [
        simplevars(),
        nested(),
        postcssPresetEnv(),
        autoprefixer(),
        cssnano(),
      ],
      // 处理.css和.scss文件
      extensions: ['.css', '.scss'],
    }),
    // 告诉 Rollup 如何查找外部模块并安装它
    resolve(),
    // babel处理不包含node_modules文件的所有js,ts,tsx
    babel({
      exclude: 'node_modules/**',
      runtimeHelpers: true,
      plugins: ['@babel/plugin-external-helpers'],
      extensions: ['.js', '.ts', 'tsx'],
    }),
    // 将 CommonJS 转换成 ES2015 模块
    // 这里有些引入使用某个库的api但报未导出该api通过namedExports来手动导出
    commonjs({
      namedExports: {
        'node_modules/react-is/index.js': ['isFragment'],
        'node_modules/react/index.js': [
          'Fragment',
          'cloneElement',
          'isValidElement',
          'Children',
          'createContext',
          'Component',
          'useRef',
          'useImperativeHandle',
          'forwardRef',
          'useState',
          'useEffect',
          'useMemo',
        ],
        'node_modules/react-dom/index.js': [
          'render',
          'unmountComponentAtNode',
          'findDOMNode',
        ],
        'node_modules/gojs/release/go.js': [
          'Diagram',
          'GraphLinksModel',
          'Overview',
          'Spot',
        ],
      },
    }),
    json(),
    // 全局替换NODE_ENV,exclude表示不包含某些文件夹下的文件
    replace({
      // exclude: 'node_modules/**',
      'process.env.NODE_ENV': JSON.stringify(env || 'development'),
    }),
    // 生产环境执行terser压缩代码
    env === 'production' && terser(),
  ],
},
{
  // 打包*.d.ts配置,用于支持typescript项目
  input: `${PACKAGE_ROOT_PATH}/src/index.tsx`,
  output: [{
    file: `${PACKAGE_ROOT_PATH}/dist/index.d.ts`,
    format: 'esm',
  }],
  external: [/.scss$/, /.css$/],
  plugins: [dts()],
}];

export default config

修改tsconfig.json

"jsx": "react"

修改.gitignore

packages/*/dist
packages/*/lib


storybook-static

每个子包加上scripts

"build:sit": "cross-env BABEL_ENV=rollup rollup -c ../../rollup.config.js",
"build": "cross-env NODE_ENV=production rollup -c ../../rollup.config.js"

修改根目录script

"build": "lerna run build", 

参考:blog.csdn.net/u013938465/…