起因
在使用storybook@6.1.21時(shí)厦画,可能只想關(guān)注其中一個(gè)或多個(gè)UI組件假哎,但storybook將所有組件都給打包了妓湘;
導(dǎo)致的問題
- 展示的組件太多玷禽;
- 啟動(dòng)時(shí)間變慢赫段;
- 如果其它包有問題,會(huì)導(dǎo)致啟動(dòng)失斅垩堋瑞佩;
需求
在啟動(dòng)時(shí),只啟動(dòng)指定UI組件坯台,其它組件即不打包炬丸,也不渲染;
配置文件
1. 文件目錄
20210705164628242.png
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';
/** 變化點(diǎn):將真實(shí)路徑正則用 占位字符串 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');
/** 變化點(diǎn):從命令行參數(shù)中獲取組件名 **/
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 **/
/** 變化點(diǎn):使用 webpack.DefinePlugin 插件在打包的時(shí)候?qū)?占位字符串 替換掉 **/
config.plugins.push(new webpack.DefinePlugin({
REPLACE_COMPONENT_DIR_REG_STR: `/\\/(${componentName})\\/.*\\.(stories|story)\\.(tsx|jsx|js)$/`
}))稠炬;
/** end **/
return config;
};
方案2:自定義loader
原理
自定義一個(gè)webpack的loader,在打包c(diǎn)onfig.js文件時(shí)替換 require.context 的正則表達(dá)式
config.js
import { configure } from '@storybook/react';
/** 變化點(diǎn):在正則表達(dá)式中使用 占位字符串 %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
/** 變化點(diǎn) **/
const path = require('path');
/** end **/
module.exports = ({ config }) => {
/** other config **/
/** 變化點(diǎn):為 .storybook/config.js 文件定制一個(gè)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 => {
// 從命令行參數(shù)中獲取組件名
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)
}
啟動(dòng)
npm start componentName1, componentName2