storybook

  • 成品展示
  • 开发准备
  • 开发组件
  • 写MDX文档
  • 发布文档
  • 发布组件

成品展示

可视化UI文档页面:

可视化UI文档地址:

https://guozia007.gitee.io/storybook-ui/?path=/docs/mdx-button--default-story

组件库地址:

https://www.npmjs.com/package/storybook-ui-public

项目地址:

https://gitee.com/guozia007/storybook-ui

开发准备

在gitee或者github创建仓库,然后clone到本地。

这次使用了storybook,很多开发环境下的依赖都不需要装了。

根目录创建.gitignore,屏蔽这些,不上传,基本操作了

node_modules
lib
dist

初始化生成pkg文件:

npm init -y

安装react:

npm i react react-dom -D

安装webpack5:

// 这次就不需要安装webpack-dev-server了,因为storybook已经准备好了开发环境的服务
npm i webpack webpack-cli -D

babel那一套,看哪个没有就装哪个,有些是已经通过storybook装好了:

npm i babel-loader @babel/core @babel/preset-env @babel/preset-react -D

根目录下创建.babelrc.js,配置babel:

module.exports = {presets: ['@babel/preset-env','@babel/preset-react']
}

根目录下创建jsconfig.json

{"compilerOptions": {"outDir": "./lib/","module": "ESNext","target": "ES5","moduleResolution": "node","esModuleInterop": true,"jsx": "react","allowJs": true,"allowSyntheticDefaultImports":true},"exclude": ["node_modules", "lib"]
}

stories目录下的文件全部清空,然后创建Button.stories.mdx

用于后面写可视化UI文档。

在根目录下创建src目录,我们的组件要写这里面。

安装less相关:

npm i less less-loader -D

安装postcss相关,用于做样式兼容配置:

npm i postcss postcss-loader postcss-preset-env -D

安装glob,用于获取入口路径:

npm i glob -D

安装css相关plugin:

npm i mini-css-extract-plugin -Dnpm i css-minimizer-webpack-plugin -D

安装storybook管理webpack的工具,默认在使用的版本为4,我们安装5,

用以支持webpack5:

npm i @storybook/builder-webpack5 -Dnpm i @storybook/manager-webpack5 -D

在根目录下创建webpack.config.js,配置生产模式下的webpack:

// webpack.config.jsconst path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const glob = require('glob');const getStyleLoader = (importLoaders, loaderName) => {return [MiniCssExtractPlugin.loader,{loader: 'css-loader',options: {importLoaders}},{loader: 'postcss-loader',options: {postcssOptions: {plugins: ['postcss-preset-env']}}},loaderName].filter(Boolean);
}const entries = {};
const fileNames = glob.sync('./src/**/*.js?(x)');
// console.log('fileNames: ', fileNames);
fileNames.forEach(file => {const filePath = file.replace(/^\.\/src\/(.+)\.jsx?$/, '$1');entries[filePath] = file;
})module.exports = {mode: 'production',entry: entries,output: {path: path.resolve(__dirname, 'lib'),filename: '[name].js',clean: true,library: {name: 'storybook-ui',type: 'umd'}},module: {rules: [{test: /\.css$/,use: getStyleLoader(1)},{test: /\.less$/,use: getStyleLoader(2, 'less-loader')},{test: /\.jsx?$/,exclude: /node_modules/,loader: 'babel-loader'}]},plugins: [new MiniCssExtractPlugin({filename: '[name].css'})],optimization: {splitChunks: {chunks: 'all',name: 'chunk'},minimizer: [new CssMinimizerPlugin()]},resolve: {extensions: ['.js', '.jsx', '.json']},externals: {react: {root: 'React',commonjs2: 'react',commonjs: 'react',amd: 'react',},'react-dom': {root: 'ReactDOM',commonjs2: 'react-dom',commonjs: 'react-dom',amd: 'react-dom',}}
}

配置.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: {name: 'webpack5',options: {lazyCompilation: true,fsCache: true}},},webpackFinal: async (config, { configType }) => {// 配置支持less// 配置支持postcss兼容config.module.rules.push({test: /\.less$/,include: path.resolve(__dirname, '../src'),use: ['style-loader','css-loader',{loader: 'postcss-loader',options: {postcssOptions: {plugins: ['postcss-preset-env']}}},'less-loader']});return config;}
}

配置package.json

{"name": "storybook-ui-public","version": "0.0.2","description": "使用storybook发布组件","main": "lib/index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1","storybook": "start-storybook -p 6006","build-storybook": "build-storybook","build": "webpack --config webpack.config.js","pub": "npm run build && npm publish --access=public"},"repository": {"type": "git","url": "https://gitee.com/guozia007/storybook-ui.git"},"homepage": "https://guozia007.gitee.io/storybook-ui/?path=/docs/mdx-button--default-story","keywords": ["storybook","ui","framework","component","react component","frontend"],"author": "guozi007a","license": "MIT","devDependencies": {"@babel/core": "^7.21.0","@babel/preset-env": "^7.20.2","@babel/preset-react": "^7.18.6","@storybook/addon-actions": "^6.5.16","@storybook/addon-docs": "^6.5.16","@storybook/addon-essentials": "^6.5.16","@storybook/addon-interactions": "^6.5.16","@storybook/addon-links": "^6.5.16","@storybook/builder-webpack4": "^6.5.16","@storybook/builder-webpack5": "^6.5.16","@storybook/manager-webpack4": "^6.5.16","@storybook/manager-webpack5": "^6.5.16","@storybook/react": "^6.5.16","@storybook/testing-library": "0.0.13","babel-loader": "^8.3.0","css-loader": "^6.7.3","css-minimizer-webpack-plugin": "^4.2.2","glob": "^8.1.0","less": "^4.1.3","less-loader": "^11.1.0","mini-css-extract-plugin": "^2.7.2","postcss": "^8.4.21","postcss-loader": "^7.0.2","postcss-preset-env": "^8.0.1","react": "^18.2.0","react-dom": "^18.2.0","webpack": "^5.75.0","webpack-cli": "^5.0.1"},"publishConfig": {"registry": "https://registry.npmjs.org/"},"browserslist": [">= 0.25%","last 1 version","not dead"],"files": ["lib"],"peerDependencies": {"react": ">= 16.9.0","react-dom": ">= 16.9.0"},"dependencies": {}
}

开发组件

// src/index.jsexport { default as Button } from './Button';
// src/Button/index.jsximport React from 'react';
import PropTypes from 'prop-types';
import './index.less';const Button = ({ loading, primary, backgroundColor, size, label, ...props }) => {const mode = loading? 'storybook-button--loading': primary? 'storybook-button--primary': 'storybook-button--default';return (<buttontype="button"className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}style={backgroundColor && { backgroundColor }}{...props}>{loading ? <span className='storybook-loading-icon'></span> : null}{label}</button>);
};export default Button;Button.propTypes = {/*** Is this the principal call to action on the page?*/primary: PropTypes.bool,/*** Is something in loading?*/loading: PropTypes.bool,/*** What background color to use*/backgroundColor: PropTypes.string,/*** How large should the button be?*/size: PropTypes.oneOf(['small', 'medium', 'large']),/*** Button contents*/label: PropTypes.string.isRequired,/*** Optional click handler*/onClick: PropTypes.func,
};Button.defaultProps = {backgroundColor: null,primary: false,size: 'medium',label: 'default button',onClick: undefined,loading: false
};
/* src/Button/index.less */.storybook-button {font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;font-weight: 700;border: 1px solid transparent;border-radius: 4px;cursor: pointer;display: inline-block;line-height: 1;user-select: none;font-size: 14px;
}.storybook-button--primary {color: white;background-color: #1ea7fd;&:hover {filter: opacity(.9);}
}.storybook-button--default {color: #333;background-color: transparent;box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;&:hover {border: 1px solid #1ea7fd;color: #1ea7fd;box-shadow: none;}
}.storybook-button--loading {background-color: #1ea7fd;cursor: default;color: #fff;box-shadow: 0 2px 0 rgb(5 145 255 / 10%);opacity: 0.65;color: #fff;
}@keyframes circle {0% {}100% {transform: rotate(360deg);}
}
.storybook-loading-icon {display: inline-block;width: 10px;height: 10px;border-top: 1px solid #fff;border-right: 1px solid #fff;border-radius: 50%;margin-right: 6px;animation: circle .7s linear infinite;vertical-align: middle;
}.storybook-button--small {font-size: 12px;padding: 10px 16px;
}.storybook-button--medium {font-size: 14px;padding: 11px 20px;
}.storybook-button--large {font-size: 16px;padding: 12px 24px;
}

写MDX文档

stories/Button.stories.mdx中:

import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs';
import { Button } from '../src';<Meta title="MDX/Button" component={Button} /><style>{`h2 {color: rgba(0, 0, 0, 0.88);font-weight: 500;font-family: Avenir,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji',sans-serif;font-size: 24px;line-height: 32px;}ul, ol {list-style: none;padding: 0;margin: 0;}ul li {margin-left: 20px;padding-left: 4px;list-style-type: circle;}`}
</style># Button 按钮按钮用于开始一个即时操作。## 何时使用标记了一个(或封装一组)操作命令,响应用户点击行为,触发相应的业务逻辑。在 Storybook UI 中我们提供了两种按钮。- 主按钮:用于主行动点,一个操作区域只能有一个主按钮。- 默认按钮:用于没有主次之分的一组行动点。以及两种状态属性与上面配合使用。- 危险:删除/移动/修改权限等危险操作,一般需要二次确认。- 加载中:用于异步操作等待反馈的时候,也可以避免多次提交。## 代码演示export const Template = (args) => <Button {...args} /><Canvas><Story name="default"args={{label: "default button"}}>{Template.bind({})}</Story>
</Canvas><Canvas><Story name="primary"args={{primary: true,label: "primary button"}}>{Template.bind({})}</Story>
</Canvas><Canvas><Story name="loading"args={{loading: true,label: "Loading"}}>{Template.bind({})}</Story>
</Canvas>## API通过设置 Button 的属性来产生不同的按钮样式,按钮的属性说明如下:<ArgsTable of={Button} />

发布文档

执行开发环境打包指令:

npm run build-storybook

会生成一个storybook-static的目录。

代码上传到git,然后发布到githubPages或者giteePage

这里发布后,获取到文档地址,在package.json中添加:

"homepage": "你的线上文档地址"

发布组件

执行打包并发布的指令:

npm run pub

完成。


【react storybook】从零搭建react脚手架,并使用storybook发布组件库到npm,并生成可视化UI文档相关推荐

  1. 从零搭建React全家桶框架教程

    从零搭建React全家桶框架教程 源码地址:https://github.com/brickspert/react-family 欢迎star 提问反馈:blog 原文地址:https://githu ...

  2. react安装_超全面详细一条龙教程!从零搭建React项目全家桶(上篇)

    React是近几年来前端项目开发非常火的一个框架,其背景是Facebook团队的技术支持,市场占有率也很高.很多初学者纠结一开始是学react还是vue.个人觉得,有时间的话,最好两个都掌握一下.从学 ...

  3. 2023新春版:看这篇大宝典就够了!从零搭建React项目全家桶

    React是近年来前端开发领域非常热门的技术框架,其背景是Facebook团队的技术支持,在全球的前端开发市场上占有率很高.结合React丰富的社区资源,可以让项目开发如虎添翼.虽然React的学习门 ...

  4. 【React自制全家桶】一、Webstrom+React+Ant Design+echarts搭建react项目

    前言 一.React是Facebook推出的一个前端框架,之前被用于著名的社交媒体Instagram中,后来由于取得了不错的反响,于是Facebook决定将其开源.出身名门的React也不负众望,成功 ...

  5. 从零搭建开发脚手架 Spring Boot集成Mybatis-plus之一

    文章目录 简介 特性 框架结构 依赖集成 依赖 配置 编码 开始使用 核心功能 代码生成器 添加依赖 编码 编写配置 自定义模板引擎 自定义代码模板 自定义属性注入 字段其他信息查询注入 实战总结 常 ...

  6. (上)vuepress编写API文档verdaccio搭建并发布组件库

    vuepress编写API文档 介绍 搭建 安装 初始化 配置 组件API文档 发布组件库 坑 没有高亮 介绍 想要搭建一个类似elementUI的组件库及相关的API文档,可以直接引用组件,还有代码 ...

  7. 基于webpack4.X从零搭建React脚手架

    项目初始化 $ npm init 复制代码 安装webpack 本次创建是基于webpack4 $ npm install --save-dev 复制代码 新建webpack配置文件 在根目录创建bu ...

  8. 从零搭建react + webpack项目

    初始化项目 mkdir my-react cd my-react npm init 安装 webpack npm install webpack webpack-cli --save-dev 最简单的 ...

  9. 【React+ts】从零开始搭建react函数式组件+router+redux+less+sass+axios反向代理+antd(保姆式教学)

    前提 你需要准备好node.js版本不低于6.14.8 和 git 文章内容比较长(保姆级别教程),全是干货,请耐心看完 通过create-react-app脚手架搭建项目 1.第一步 注: 项目名称 ...

最新文章

  1. 8条腾讯的产品管理方式
  2. [xUnit]尝试单元测试
  3. python 类的知识点整理_Python基础知识点整理,看下你能答对几个
  4. java分批查询oracle数据库_数据库的分批查询问题
  5. redhat 5.6下网卡冗余实验
  6. 多态部分作业 2.编写2个接口:InterfaceA和InterfaceB;在接口InterfaceA中有个方法void 输出大小写字母表
  7. ASP.NET里创建Microsoft Word文档
  8. 招人!入职阿里仅1年,我和做AI的程序员薪资翻了2倍!
  9. hibernate框架学习笔记11:Criteria查询详解
  10. Python高并发应用场景下四种写入SQLite数据库的速度比较
  11. Android图片,PNG还是JPG?用哪种?
  12. WSL2之kali从C盘迁移到E盘
  13. TMS320C55x的指令系统
  14. [图灵程序设计丛书].流畅的Python.revise11.pdf
  15. 【琐识】日常获取知识随笔
  16. 一年风雨几度寒,一杯浊酒敬虎年
  17. 模糊数学Fuzzy Set第2讲——Fuzzy Logic Fuzzy Reasoning
  18. 干货!如何快速拥有自己的商城APP
  19. 开关电源环路的零极点可以在反馈端补偿吗_开关电源的建模和环路补偿设计(1):小信号建模的基本概念和方法(一)...
  20. 4.5 拉普拉斯定理

热门文章

  1. 22.3 ORDER BY语句的优化
  2. 软硬件全面测评教程,宝妈亲测读书郎AI学习机C30
  3. qq阅读java带签名_手机QQ阅读器Java触屏且签名版
  4. [附源码]Python计算机毕业设计SSM基于java旅游信息分享网站(程序+LW)
  5. Win10系统如何彻底卸载腾讯游戏安全中心
  6. 鸿蒙系统打败安卓,鸿蒙系统会不会打败安卓,苹果
  7. stm32倒计时秒表proteus_单片机课程设计倒计时秒表
  8. 【五校联盟集训】DAY 1
  9. 《CPU通识课》读书笔记
  10. python txt 读取 写入