起因
在应用storybook @6.1.21时,可能只想关注其中一个或多个UI组件,但storybook将所有组件都给打包了;
导致的问题
- 展现的组件太多;
- 启动工夫变慢;
如果其它包有问题,会导致启动失败;
需要
在启动时,只启动指定UI组件,其它组件即不打包,也不渲染;
配置文件
1. 文件目录
2. config.js
import { configure } from '@storybook/react';const req = require.context('../packages', true, /\.(stories|story)\.(tsx|jsx|js)$/);function loadStories() { req.keys().forEach(filename => req(filename));}configure(loadStories, module);
3. webpack.config.js
module.exports = ({ config }) => { /** other config **/ return config;};
4. 版本信息
storybook: 6.1.21
解决方案:
计划1:webpack.DefinePlugin
原理
利用webpack.DefinePlugin定义全局变量,并替换config.js中的require上下文门路
config.js
import { configure } from '@storybook/react';/** 变动点:将实在门路正则用 占位字符串 REPLACE_COMPONENT_DIR_REG_STR 代替 **/const req = require.context('../packages', true, REPLACE_COMPONENT_DIR_REG_STR);/** end **/function loadStories() { req.keys().forEach(filename => req(filename));}configure(loadStories, module);
webpack.config.js
const webpack = require('webpack');/** 变动点:从命令行参数中获取组件名 **/let componentName;try { const [cmd1, cmd2] = JSON.parse(process.env.npm_config_argv).original.slice(-2); if (cmd1 === 'start' && cmd2 && cmd2.trim()) { componentName = cmd2 .split(',') .map(item => item && item.trim()) .filter(Boolean) .join('|'); }}catch(e) {console.error(e)}/** end **/module.exports = ({ config }) => { /** other config **/ /** 变动点:应用 webpack.DefinePlugin 插件在打包的时候将 占位字符串 替换掉 **/ config.plugins.push(new webpack.DefinePlugin({ REPLACE_COMPONENT_DIR_REG_STR: `/\\/(${componentName})\\/.*\\.(stories|story)\\.(tsx|jsx|js)$/` })); /** end **/ return config;};
计划2:自定义loader
原理
自定义一个webpack的loader,在打包config.js文件时替换 require.context 的正则表达式
config.js
import { configure } from '@storybook/react';/** 变动点:在正则表达式中应用 占位字符串 %REPLACE_COMPONENT_DIR_NAME% **/const req = require.context('../packages', true, /%REPLACE_COMPONENT_DIR_NAME%\.(stories|story)\.(tsx|jsx|js)$/);/** end **/function loadStories() { req.keys().forEach(filename => req(filename));}configure(loadStories, module);
webpack.config.js
/** 变动点 **/const path = require('path');/** end **/module.exports = ({ config }) => { /** other config **/ /** 变动点:为 .storybook/config.js 文件定制一个loader **/ config.module.rules.push({ test: /\.storybook\/config\.js$/, use: path.resolve(__dirname, './cus-set-package-loader.js'), }); /** end **/ return config;};
.storybook/cus-set-package-loader.js
module.exports = res => { // 从命令行参数中获取组件名 let componentName try { const [cmd1, cmd2] = JSON.parse(process.env.npm_config_argv).original.slice(-2) if (cmd1 === 'start' && cmd2 && cmd2.trim()) componentName = cmd2 }catch(e) {console.error(e)} console.log('\n\x1b[33m%s\x1b[0m', `package names: ${componentName || 'all packages'}`) // 解决 多组件 和 组件名中的空格 const componentDirName = componentName ? `\\/(${componentName.split(',') .map(item => item && item.trim()) .filter(Boolean) .join('|')})\\/.*` : '' // 替换配置文件中的 占位符 return res.replace('%REPLACE_COMPONENT_DIR_NAME%', componentDirName)}
启动
npm start componentName1, componentName2