如何解决 Storybook 中的别名?
Posted
技术标签:
【中文标题】如何解决 Storybook 中的别名?【英文标题】:How to resolve aliases in Storybook? 【发布时间】:2021-06-01 07:42:52 【问题描述】:我有一个带有 Storybook 的 React/Typescript 项目。 Storybook 很好用,但是一旦我开始导入带别名的文件,它就会崩溃。
例子:
import Foo from "@components/foo" => crash
import Foo from "../../components/foo" => ok
该应用可以正常使用别名。该问题仅与 Storybook 有关。
这是我的故事书配置:
module.exports =
stories: ["../**/stories.tsx"],
webpackFinal: (config) =>
return
...config,
module:
...config.module,
rules: [
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: loader: "babel-loader" ,
,
test: /\.css$/, use: ["style-loader", "css-loader"] ,
test: /\.(png|jpg|gif)$/, use: ["file-loader"] ,
test: /\.svg$/,
use: [
loader: "babel-loader",
,
loader: "react-svg-loader",
options:
jsx: true,
,
,
],
,
],
,
;
,
typescript:
check: false,
checkOptions: ,
reactDocgen: "react-docgen-typescript",
reactDocgenTypescriptOptions:
shouldExtractLiteralValuesFromEnum: true,
propFilter: (prop) =>
prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
,
,
;
我的 webpack 配置:
/* eslint-env node */
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
const Dotenv = require("dotenv-webpack");
const htmlWebpackPlugin = require("html-webpack-plugin");
const isProductionMode = (mode) => mode === "production";
module.exports = () =>
const env = require("dotenv").config( path: __dirname + "/.env" );
const nodeEnv = env.parsed.NODE_ENV;
return
mode: "development",
entry: "./src/index.tsx",
output:
path: path.join(__dirname, "./dist"),
filename: "[name].[contenthash].bundle.js",
publicPath: "/",
,
resolve:
extensions: [".ts", ".tsx", ".js", "jsx", ".json"],
alias:
"@api": path.resolve(__dirname, "src/api/"),
"@assets": path.resolve(__dirname, "src/assets/"),
"@components": path.resolve(__dirname, "src/components/"),
"@containers": path.resolve(__dirname, "src/containers/"),
"@data": path.resolve(__dirname, "src/data/"),
"@i18n": path.resolve(__dirname, "src/i18n/"),
"@models": path.resolve(__dirname, "src/models/"),
"@pages": path.resolve(__dirname, "src/pages/"),
"@src": path.resolve(__dirname, "src/"),
"@stores": path.resolve(__dirname, "src/stores/"),
"@utils": path.resolve(__dirname, "src/utils/"),
,
,
module:
rules: [
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: loader: "babel-loader" ,
,
test: /\.css$/, use: ["style-loader", "css-loader"] ,
test: /\.(png|jpg|jpeg|gif)$/, use: ["file-loader"] ,
test: /\.svg$/,
use: [
loader: "babel-loader",
,
loader: "react-svg-loader",
options:
jsx: true,
,
,
],
,
],
,
devServer:
historyApiFallback: true,
port: 3000,
inline: true,
hot: true,
,
plugins: [
new HtmlWebpackPlugin(
template: "./src/index.html",
),
new Dotenv(),
],
optimization:
minimize: isProductionMode(nodeEnv),
minimizer: isProductionMode(nodeEnv) ? [new TerserPlugin()] : [],
splitChunks: chunks: "all" ,
,
;
;
如何解决这个问题?我使用的是 webpack 5.24.2 和 storybook 6.1.20,所以这些是最新版本。
【问题讨论】:
您是否尝试过在故事书配置中重复您的别名?不是 100% 肯定,但我认为传递给webpackFinal
的 config
是故事书的默认配置,并且对您的其他 webpack 配置一无所知。您可以尝试在 webpackFinal
中使用 console.log
ging config
进行确认。编辑进一步审查看起来你可以导入和合并你现有的 webpack 配置:storybook.js.org/docs/react/configure/…
如果我用“resolve”添加别名,它会显示“configuration.module 有一个未知属性 'resolve'”。如果我像在官方文档中那样导入 webpack,它会说“无法读取未定义的模块”
两件事,resolve
位于 webpack 配置的顶层,而不是在 config.module
之下。不是 100% 确定 webpack 导出/导入问题,但请注意您的 webpack 配置导出是一个函数,而不是普通对象,因此您需要调用它并将该调用的输出与故事书默认值合并导入工作。
【参考方案1】:
只需将其添加到您的.storybook/main.js
const path = require('path');
module.exports =
"stories": [
"../components/**/*.stories.mdx",
"../components/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
'@storybook/preset-scss',
],
webpackFinal: async (config, configType ) =>
config.resolve.alias =
...config.resolve.alias,
'@/interfaces': path.resolve(__dirname, "../interfaces"),
;
return config;
这里interface
是我项目根目录下的文件夹
对我有用
【讨论】:
【参考方案2】:如果您使用的是 webpack 5,则需要指定应使用 webpack5,方法是在之前的答案之外还添加以下内容:
core:
builder: "webpack5",
,
最终的 storybook/main.js 将类似于:
// .storybook/main.js
const path = require('path');
const appWebpack = require(path.join(process.cwd(), 'webpack.config.js'));
module.exports =
stories: ['../src/**/*.stories.@(tsx|mdx)'],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
'@storybook/preset-scss'
],
core:
builder: "webpack5",
,
webpackFinal: async (config) =>
config.resolve.modules = [
...(config.resolve.modules || []),
...[path.resolve(process.cwd(), "src")],
];
config.resolve.alias =
...(config.resolve.alias || ),
...appWebpack().resolve.alias,
;
return config;
,
;
这将允许绝对路径和别名(当然,只要这些别名在您的主 webpack.config.js 和 jsconfig.json/tsconfig.json 中正确设置)
已编辑
特别是在别名方面遇到了麻烦,我又在 webpack 坎坷的道路上走了一趟。
我已经更新了上面 .storybook/main.js 的原始“final”,明确地合并了别名和模块节点。
编辑 2
请注意,eslint 会在你创建的全局装饰器中使用别名(并添加到 .storybook/preview.js)。你可以放心地忽略这一点——它们仍然有效。如果/当我也想出如何纠正这个问题时,我会回来添加第三次编辑。
【讨论】:
【参考方案3】:当我遇到同样的问题时,这对我有用:
在开发部门yarn add -D tsconfig-paths-webpack-plugin
中安装一个包。
然后调整您的./storybook/main.js
配置:
... // other imports
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
...
webpackFinal: (config) =>
config.resolve.plugins = config.resolve.plugins || [];
config.resolve.plugins.push(
new TsconfigPathsPlugin(
configFile: path.resolve(__dirname, "../tsconfig.json"),
)
);
return ...
...
【讨论】:
以上是关于如何解决 Storybook 中的别名?的主要内容,如果未能解决你的问题,请参考以下文章
我该如何解决这个关于 Storybook 和 Sass 的问题?
如何解决ORACLE中表一得列名的别名为另一表中的某一字段的值?