webpack 5 in a lerna monorepo loads files outside of the package

Viewed 1043

I have a fairly standard lerna monorepo setup, using yarn workspaces and TypeScript.

There are pacakge folders for various services and also the React frontend. I've been migrating the Webpack config to Webpack 5 so that I can take advantage of the module federation. The React app is complex, uses CSS modules with scss, TypeScript, etc so the config is relatively complex, nevertheless I feel as if I am there with compilation. That notwithstanding there are 2 issues that I cannot seem to fathom, the most problematic of them being that webpack seems to be trying to load files from other packages in the monorepo (and these are causing TypeScript/eslint errors).

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 is run from the frontend package folder. Also I have scanned the code for any refrences to other packages in the React code, but there are none, so I can't understand why this is loading and how to prevent them loading.

Example error:

ERROR in ../../node_modules/@githubpackage/src/aFile.ts:2:25
TS2801: This condition will always return true since this 'Promise<boolean>' is always defined.

Help much appreciated (I realise the issue should be fixed too ;p).

[EDIT] I've edited the error to indicate that the problematic package is the only package that I am installing via github packages (in a couple of the other monorepo packages).

ALSO I edited the entry file so that it only imported React and ReactDOM and rendered a <p> tag and webpack still tried loading this package... so unless there is something wrong with the webpack config, this is some odd behaviour.

0 Answers
Related