首页 > 解决方案 > 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 配置有问题,否则这是一些奇怪的行为。

标签: reactjstypescriptwebpackmonorepolerna

解决方案


推荐阅读