reactjs - lerna monorepo 中的 webpack 5 在包外加载文件
问题描述
我有一个相当标准的 lerna monorepo 设置,使用 yarn 工作区和 TypeScript。
有各种服务的 pacakge 文件夹以及 React 前端。我一直在将 Webpack 配置迁移到 Webpack 5,以便我可以利用模块联合。React 应用程序很复杂,使用带有 scss、TypeScript 等的 CSS 模块,因此配置相对复杂,但我感觉好像我在编译。尽管有 2 个问题我似乎无法理解,但其中最大的问题是 webpack 似乎试图从 monorepo 中的其他包加载文件(这些导致 TypeScript/eslint 错误)。
Webpack.config.js
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const ESLintPlugin = require("eslint-webpack-plugin");
const isDevelopment = process.env.NODE_ENV === "development";
const imageInlineSizeLimit = 2000;
// Default js and ts rules
const tsRules = {
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: path.resolve(__dirname, "src"),
exclude: [/node_modules/],
loader: "babel-loader",
options: {
customize: require.resolve("babel-preset-react-app/webpack-overrides"),
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [],
},
};
// Process any JS outside of the app with Babel.
// Unlike the application files, we only compile the standard ES features.
const externalJsRules = {
test: /\.(js|mjs)$/,
exclude: [/node_modules/],
loader: "babel-loader",
options: {
babelrc: false,
configFile: false,
compact: false,
presets: [
[
require.resolve("babel-preset-react-app/dependencies"),
{ helpers: true },
],
],
cacheDirectory: true,
cacheCompression: false,
},
};
let plugins = [
new ForkTsCheckerWebpackPlugin({
async: false,
}),
new ESLintPlugin({
extensions: ["js", "jsx", "ts", "tsx"],
}),
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
chunkFilename: "[id].[contenthash].css",
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "public", "index.html"),
}),
new webpack.IgnorePlugin({
// @todo: this prevents webpack paying attention to all tests and stories, which probably ought only be done on build
resourceRegExp: /(coverage\/|\.spec.tsx?|\.mdx?$)/,
}),
];
if (isDevelopment) {
// For use with dev server
tsRules.options.plugins.push("react-refresh/babel");
externalJsRules.options.sourceMaps = true;
externalJsRules.options.inputSourceMap = true;
plugins = [...plugins, new webpack.HotModuleReplacementPlugin()];
}
module.exports = {
entry: path.resolve(__dirname, "src", "index.tsx"),
output: {
path: path.resolve(__dirname, "build"),
publicPath: "/",
clean: true,
},
module: {
rules: [
externalJsRules,
tsRules,
{
test: [/\.avif$/],
loader: "url-loader",
options: {
limit: imageInlineSizeLimit,
mimetype: "image/avif",
name: "static/media/[name].[hash:8].[ext]",
},
},
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: "url-loader",
options: {
limit: imageInlineSizeLimit,
name: "static/media/[name].[hash:8].[ext]",
},
},
{
test: /\.svg$/,
use: ["@svgr/webpack", "url-loader"],
},
{
test: /\.s?css$/,
oneOf: [
{
test: /\.module\.s?css$/,
use: [
isDevelopment
? // insert css into DOM via js
"style-loader"
: // insert link tags
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true,
sourceMap: isDevelopment,
importLoaders: 2,
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-flexbugs-fixes",
[
"postcss-preset-env",
{
autoprefixer: {
flexbox: "no-2009",
},
stage: 3,
},
],
"postcss-normalize",
],
},
},
},
{
loader: "sass-loader",
options: {
sourceMap: isDevelopment,
},
},
],
},
{
use: [
isDevelopment
? // insert css into DOM via js
"style-loader"
: // insert link tags
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
sourceMap: isDevelopment,
importLoaders: 2,
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-flexbugs-fixes",
[
"postcss-preset-env",
{
autoprefixer: {
flexbox: "no-2009",
},
stage: 3,
},
],
"postcss-normalize",
],
},
},
},
{
loader: "sass-loader",
options: {
sourceMap: isDevelopment,
},
},
],
},
],
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js", ".scss"],
symlinks: false,
// don't provide polyfills for non UUI-core
fallback: {
// crypto: false,
// fs: false,
// stream: false,
// path: false,
},
},
optimization: {
runtimeChunk: true,
},
plugins: [...plugins],
devtool: "eval-cheap-module-source-map",
devServer: {
static: path.join(__dirname, "build"),
historyApiFallback: true,
port: 3000,
open: true,
hot: true,
},
};
Webpack 从前端包文件夹运行。此外,我还扫描了代码中对 React 代码中其他包的任何引用,但没有,所以我不明白为什么要加载以及如何阻止它们加载。
示例错误:
ERROR in ../../node_modules/@githubpackage/src/aFile.ts:2:25
TS2801: This condition will always return true since this 'Promise<boolean>' is always defined.
非常感谢您的帮助(我意识到这个问题也应该得到解决;p)。
[编辑] 我已经编辑了错误以表明有问题的包是我通过 github 包安装的唯一包(在其他几个 monorepo 包中)。
此外,我编辑了入口文件,使其仅导入 React 和 ReactDOM 并呈现<p>
标签,而 webpack 仍然尝试加载此包......所以除非 webpack 配置有问题,否则这是一些奇怪的行为。
解决方案
推荐阅读
- prisma2 - 具有不同数据库的 Prisma 2
- python - 无法添加到空白列表
- regex - 在验证电子邮件和电话之前不要提交表单 - Vue.js 3
- sql - 将参数传递给位于另一台服务器上的存储过程
- google-apps-script - Google 表格中的 WTI 价格
- javascript - Discord.js,编辑带有反应的特定嵌入字段,如果未反应则恢复正常
- python-3.x - 不能将字符串转换为浮点数然后再转换为整数?
- python - TypeError TypeError:connect() 参数 3 必须是 str,而不是 list
- java - 为什么用户输入的数字没有出现在 java 单元格中?
- reactjs - 你能在反应三纤维画布内显示一个弹出模式吗?