我在一个老项目中运行Storybook时遇到了一些小问题。当我使用自定义的Webpack配置运行Storybook时,出现了一个错误:
ERROR in ./node_modules/asynchronous-local-storage/dist/lib/als.js
Module not found: Error: Can't resolve 'async_hooks' in 'C:\Users\Martin\Documents\censored\censored\node_modules\asynchronous-local-storage\dist\lib'
这个错误意味着无法识别async_hooks。Async_hooks是Node.js的一部分,这意味着我无法在浏览器中访问它。然而,我认为Webpack可以填充这些模块。我的做法如下:
config.target = "node";
但这意味着捆绑的代码将针对 Node.js 进行优化,而不是浏览器应用程序。这就是为什么错误已经消失,我现在可以运行 Storybook 了,但是由于浏览器控制台中的错误,Storybook 中的故事无法加载:
Uncaught ReferenceError: exports is not defined
我现在在应用程序中所做的基本上是这样的:
let als
if (typeof window === 'undefined') {
als = require('asynchronous-local-storage').als
}
如果环境不是浏览器,那么只有依赖于async_hooks模块的包才需要这个包。然而,不知何故,Webpack仍然想要加载这个核心Node模块,我不明白为什么。这是Webpack配置文件:
const path = require('path')
const PnpWebpackPlugin = require('pnp-webpack-plugin')
const webpack = require('webpack')
module.exports = async ({ config, mode }) => {
config.module.rules = [
...config.module.rules,
...[
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
'file-loader',
],
},
{
test: /\.stor[a-z]+\.jsx?$/,
loaders: [
{
loader: require.resolve('@storybook/source-loader'),
options: { injectDecorator: true },
},
],
enforce: 'pre',
},
{
test: /\.css$/,
exclude: [],
include: [/node_modules/, /src/],
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: false,
},
},
],
},
{
test: /\.s?css$/,
exclude: [],
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: false,
},
},
{
loader: 'sass-loader',
},
],
},
],
]
config.resolve = {
...config.resolve,
...{
extensions: [ '.mjs', '.web.js', '.js', '.json', '.web.jsx', '.jsx' ],
alias: {
'./lodash.min': 'lodash/lodash.js',
fs: path.join(__dirname, '..', '__mocks__', 'file.js'),
},
mainFields: [ 'browser', 'main' ],
},
}
config.plugins.push(PnpWebpackPlugin)
config.plugins.push(new webpack.DefinePlugin({
'process.env.IS_BROWSER': JSON.stringify(true)
}))
return config
}
还有针对 Babel 配置文件的情况:
{
"presets": [
"@babel/preset-react",
[
"@babel/preset-env",
{
"targets": {
"node": 10,
"browsers": ["last 2 versions", "> 1%", "IE 11"]
},
"loose": true,
"modules": "auto",
"debug": true,
"useBuiltIns": "entry"
}
],
"@babel/preset-flow"
],
"retainLines": true,
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-optional-chaining"
]
}
我真的很难找到解决方法,想知道如何使它工作。我查看了很多类似的问题,但没有一个与我的问题完全相同。
由于项目大小和NDA,我无法复制存储库。
谢谢
编辑:
@loganfsmyth 我明白了,回退只适用于Node版本 <8.0.0
。该项目在12.14.0
上运行,因此必须使用async_hooks
。我不理解的是,当我使用yarn dev
运行项目(Next.js项目和自定义Express服务器)时,项目可以正常运行。但是,当我尝试运行Storybook(和Webpack构建)时,它会失败并显示Can't resolve 'async_hooks
错误消息。这个错误消息可以追溯到高阶组件(Apollo GraphQL客户端包装器)。HOC以这种方式要求async_hooks
模块:
let als
if (typeof window === 'undefined') {
als = require('asynchronous-local-storage').als
}
HOC是一个普通的.jsx组件,所以我想知道为什么它需要ALS包,尽管上面的条件不应该满足,也不应该需要ALS模块。难道我在Webpack设置中漏掉了某些东西吗?再次感谢:)
asynchronous-local-storage
模块的文档中写道:“对于旧版 Node.js,可以回退到 cls-hooked。”因此,不管怎样这个模块在浏览器中也无法工作,它只是为了支持旧版 Node.js。浏览器无法填充此async_hooks
模块。这是该模块被标记为实验性的一个重要原因:https://nodejs.org/api/documentation.html#stability-index - loganfsmyth