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.