javascript - Webpack 解析别名并在该别名下编译文件
问题描述
我有使用 lerna 的项目(monorepo,多个包)。很少有软件包是独立的应用程序。
我想要实现的是在少数包上使用别名来进行依赖注入。因此,例如,我有别名@package1/backendProvider/useCheckout
,并且在我的独立应用程序的 webpack 中,我将其解析为../../API/REST/useCheckout
. 因此,当我将后端提供程序更改为其他内容时,我只会在 webpack 中更改它。
问题
当其他包(不是独立应用程序)使用此别名时会出现问题。例如:
目录结构如下所示:
Project
packageA
ComponentA
packageB
API
REST
useCheckout
standalone app
组件 A 在包 A 中
useCheckout 在 packageB/API/REST/useCheckout
路径下
ComponentAuseCheckout
与别名一起使用import useCheckout from '@packageA/backendProvider/useCheckout
独立应用程序使用 componentA
我得到的错误是Module not found: Can't resolve '@packageA/backendProvider/useCheckout
但是,当在独立应用程序(具有下面提供的配置的 webpack)中使用相同的别名时,它正在工作。问题仅发生在依赖项上。
潜在的解决方案
我知道一种解决方案是使用 webpack 编译每个包 - 但这似乎并不友好。我认为可行的是告诉 webpack 将这些别名解析为目录路径,然后重新编译它。第一部分(解析别名)已完成。
当前代码
当我使用 NextJS 时,我的 webpack 配置如下所示:
webpack: (config, { buildId, dev, isServer, defaultLoaders }) => {
// Fixes npm packages that depend on `fs` module
config.node = {
fs: "empty"
};
const aliases = {
...
"@package1/backendProvider": "../../API/REST/"
};
Object.keys(aliases).forEach(alias => {
config.module.rules.push({
test: /\.(js|jsx)$/,
include: [path.resolve(__dirname, aliases[alias])],
use: [defaultLoaders.babel]
});
config.resolve.alias[alias] = path.resolve(__dirname, aliases[alias]);
});
return config;
}
解决方案
您不需要使用别名。我有一个类似的设置,只需切换到 yarn (v1) 工作区,这是一个非常聪明的技巧,它将 sym 链接添加到根node_modules中的所有包。
这样,每个包都可以毫无问题地导入其他包。
为了使用 lerna 应用纱线工作空间:
// lerna.json
{
"npmClient": "yarn",
"useWorkspaces": true,
"packages": [
"packages/**"
],
}
// package.json
{
...
"private": true,
"workspaces": [
"packages/*",
]
...
}
这将启用带有 lerna 的纱线工作区。
唯一需要解决的想法是让消费者包转译所需的包(因为 babel 和 webpack 的默认配置是忽略 node_module 转译)。
在 Next.js 项目中,使用next-transpile-modules很简单。
// next.config.js
const withTM = require('next-transpile-modules')(['somemodule', 'and-another']); // pass the modules you would like to see transpiled
module.exports = withTM();
在使用 webpack 的其他包中,您需要指示 webpack 转译您使用的包(假设它们在 npm 范围内@somescope/
)。
因此,例如,为了转换 typescript,您可以添加额外的模块加载器。
// webpack.config.js
{
...
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader',
include: /[\\/]node_modules[\\/]@somescope[\\/]/, // <-- instruct to transpile ts files from this path
options: {
allowTsInNodeModules: true, // <- this a specific option of ts-loader
transpileOnly: isDevelopment,
compilerOptions: {
module: 'commonjs',
noEmit: false,
},
},
}
]
}
...
resolve: {
symlinks: false, // <-- important
}
}
如果你有 css,你还需要为 css 添加一个部分。
希望这可以帮助。
额外的好处是,yarn 工作空间会减少你的node_modules
大小,因为它会安装重复的包(具有相同的 semver 版本)一次!
推荐阅读
- ruby-on-rails - Rails 测试帖子内容
- ios - 如何在设备启动时从 adafruit 获取 MQTT 主题数据
- frontend - 网页是否可以根据您点击进入该页面的按钮来更改其内容?
- javascript - swagger UI:如何在将图像发送到服务器之前将其转换为base64?
- dart - 从 txt 文件读取会导致长度为 1 的空字符串
- angular - 如何使用 ngrx/data saveEntities 添加多个实体进行存储?
- r - 排序数据以匹配 ggplot 字体
- javascript - 如何从 youtube 获取调试视频数据的播放质量?
- rust - 如何为字段编写具有生命周期约束的函数?
- r - packrat::resolve() 一直要求我在 Rtools 已经安装时安装它