How to fix a Babel/runtime/helper issue in Webpack 5? - reactjs

I want to upgrade to webpack 5. I've followed the official guide, upgraded all critical libraries (react17, babel, loaders, etc.). When launching the app, it crashes with 23 errors. 21 of them come from #babel/runtime/helpers.
A typical error looks like this:
ERROR in ../../node_modules/#babel/runtime/helpers/esm/createSuper.js 1:0-46
Module not found: Error: Can't resolve './getPrototypeOf' in '/Users/myName/Desktop/myapp/node_modules/#babel/runtime/helpers/esm'
The two other errors are:
Module not found: Error: Can't resolve 'url-loader'
ERROR in FaviconsWebpackPlugin - This FaviconsWebpackPlugin version is not compatible with your current HtmlWebpackPlugin version.
Please upgrade to HtmlWebpackPlugin >= 5 OR downgrade to FaviconsWebpackPlugin 2.x
Note: My html-webpack-plugin version is above 5 and favicons-webpack-plugin is the latest version as well...
Anyway, here is my webpack file:
const FaviconsWebpackPlugin = require("favicons-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
const webpack = require("webpack");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const getKonf = require("./konf");
const getWebpackServerOptions = require("./server");
function buildWebpackConfiguration() {
const konfiguration = getKonf("development"); // returns a large json with proxies, token, etc.
const rootPath = path.resolve(__dirname, "../../../");
return {
devtool: "eval-source-map",
mode: "development",
node: {
global: false,
__filename: false,
__dirname: false,
},
resolve: {
extensions: [".json", ".jsx", ".js", ".tsx", ".ts"],
alias: {
"#componens": "./components",
"react-dom": "#hot-loader/react-dom",
},
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules\/(?!(redux-logger|strict-uri-encode|query-string)\/).*/,
use: [
{
loader: "babel-loader",
options: {
configFile: path.resolve(rootPath, "./babel.config.js"),
},
},
"react-hot-loader/webpack",
],
},
{
test: /\.html$/,
use: ["html-loader"],
},
{
test: /\.less$/,
exclude: /\.m\.less$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
{
test: /\.(eot|gif|jpg|png|svg|ttf|woff)$/,
exclude: [
path.resolve(rootPath, "./assets/svg"),
path.resolve(rootPath, "./icon/glyphs"),
path.resolve(rootPath, "./search/assets"),
],
use: "url-loader?limit=1024",
},
{
test: /\.m\.less$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[local]___[hash:base64:5]",
},
},
},
"less-loader",
],
},
{
test: /\.svg$/,
use: {
loader:
"svg-inline-loader?{'removeTags': true, 'removingTags': ['title', 'desc']",
},
},
{
test: /\.tsx?$/,
use: [{ loader: "ts-loader", options: { transpileOnly: true } }],
exclude: /node_modules/,
},
{
include: /assets\/sw/,
test: /\.js$/,
loader: "file-loader",
},
],
},
plugins: [
new HtmlWebpackPlugin({
title: "My app",
template: path.resolve(__dirname, "./template/index.ejs"),
minify: true,
hash: true,
scripts: [],
styles: [],
}),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("development"),
"process.env.MOCK_REQUESTS": JSON.stringify(
process.env.MOCK_REQUESTS || "0"
),
KONF: JSON.stringify(konfiguration),
}),
new FaviconsWebpackPlugin({
logo: path.resolve(rootPath, "./assets/logo.svg"),
inject: true,
title: "My App",
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /de|en|fr|zh/),
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
chunkFilename: "[id].[contenthash].css",
}),
new BundleAnalyzerPlugin(),
],
optimization: {
minimize: true,
minimizer: [new OptimizeCSSAssetsPlugin({}), new TerserPlugin()],
moduleIds: "deterministic",
splitChunks: {
chunks: "all",
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
name: "node_vendors",
chunks: "all",
},
},
},
},
devServer: getWebpackServerOptions(konfiguration),
};
}
module.exports = buildWebpackConfiguration;
Here is my Babel config file:
module.exports = {
ignore: ["node_modules"],
babelrcRoots: [".", "./packages/*", "./app/*"],
presets: [
"#babel/preset-typescript",
[
"#babel/preset-env",
{
targets: {
browsers: ["defaults"],
},
},
],
"#babel/preset-react",
],
env: {
test: {
plugins: [
[
"babel-plugin-react-css-modules",
{
generateScopedName: "[local]",
filetypes: {
".less": {
syntax: "postcss-less",
},
},
},
],
],
},
development: {
plugins: [
[
"babel-plugin-react-css-modules",
{
webpackHotModuleReloading: true,
generateScopedName: "[local]___[hash:base64:5]",
handleMissingStyleName: "warn",
filetypes: {
".less": {
syntax: "postcss-less",
},
},
},
],
],
},
production: {
plugins: [
[
"babel-plugin-react-css-modules",
{
webpackHotModuleReloading: true,
generateScopedName: "[hash:base64]",
filetypes: {
".less": {
syntax: "postcss-less",
},
},
},
],
],
},
},
plugins: [
"#babel/plugin-transform-object-assign",
"#babel/plugin-transform-regenerator",
"#babel/plugin-transform-runtime",
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-transform-modules-commonjs",
["#babel/plugin-proposal-class-properties", { loose: true }],
[
"module-resolver",
{
cwd: "babelrc",
root: "./",
alias: {
"#components": "./components",
"#assets": "./assets",
},
},
],
],
};
How to fix this?

releted to https://github.com/babel/babel/issues/8462, runtime issues can be solved by upgrading the #babel/runtime pkg version above 7.12.0

Related

Webpack 5, Server-Side rendering, and FOUC

I'm upgrading an existing web site from Webpack 3 to Webpack 5.
The site uses server side rendering for the first load, the client side routing for any in-site navigation. All this worked fine with Webpack 3, but after migrating to Webpack 5 it looks like some of the styles are being applied via javascript and that's creating a FOUC during the first load (after that, in-site navigation works fine and looks correct). As a test, I turned off javascript in my browser; the old site loads fine and looks correct, but the upgraded site does not. It feels like I need style-loader in the server config somewhere, but when that's added, I get a "Cannot GET /" when trying to load the site. Any help is appreciated.
Server-side config
require('dotenv').config({ silent: true });
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const includePaths = [path.resolve(__dirname, 'stylesheets')];
module.exports = {
bail: true,
entry: {
main: './src/entry-server',
},
output: {
path: path.join(__dirname, 'build', 'prerender'),
filename: '[name].js',
publicPath: '/bundle/',
libraryTarget: 'commonjs2',
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
PRERENDER: true,
ASSETS_CDN_PREFIX: JSON.stringify(process.env.ASSETS_CDN_PREFIX || ''),
},
}),
// only load moment english locale: https://github.com/moment/moment/issues/2517
new webpack.ContextReplacementPlugin(/moment[\\/]locale$/, /^\.\/(en)$/),
new webpack.optimize.ModuleConcatenationPlugin(),
new MiniCssExtractPlugin({
ignoreOrder: true,
}),
],
module: {
rules: [
{
test: /\.jsx?$/,
include: path.join(__dirname, 'src'),
use: 'babel-loader',
},
{
test: /\.s?css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: true,
},
},
'postcss-loader',
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths,
data: `$assetprefix: "${process.env.ASSETS_CDN_PREFIX || ''}";`,
},
},
},
],
},
{
test: /\.svg$/,
use: `svg-inline-loader?removeTags&removingTags[]=${['defs', 'style', 'title'].join(',removingTags[]=')}`,
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.css', '.scss', '.json'],
},
target: 'node',
};
Server entry point
export default function (req, res, environmentConstants, callback) {
// ...setup
match({ routes, location: targetUrl }, (error, redirectLocation, renderProps) => {
// ...setup
fetchSomeData().then(() => renderToString(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>,
))
.then((content) => {
callback(null, {
helmet: Helmet.renderStatic(),
content,
initialState: serialize(store.getState(), { isJSON: true }),
env: serialize(someEnvConstants),
});
})
Client-side config
require('dotenv').config({ silent: true });
const AssetsPlugin = require('assets-webpack-plugin');
const CleanPlugin = require('clean-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
const webpack = require('webpack');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const includePaths = [path.resolve(__dirname, 'stylesheets')];
// Match all routes that we want to lazy load
const lazyRouteRegex = /route\/([^/]+\/?[^/]+)Route.jsx$/;
module.exports = {
bail: true,
entry: {
main: './src/entry-client',
vendor: [
'react',
'react-dom',
'react-router',
'redux',
'react-redux',
'xmldom',
],
},
output: {
path: path.join(__dirname, 'build', 'public', '[fullhash]'),
filename: '[name].js',
chunkFilename: '[id].chunk.js',
publicPath: `${process.env.ASSETS_CDN_PREFIX || ''}/build/public/[fullhash]/`,
},
plugins: [
// only load moment english locale: https://github.com/moment/moment/issues/2517
new webpack.ContextReplacementPlugin(/moment[\\/]locale$/, /^\.\/(en)$/),
new MiniCssExtractPlugin({
ignoreOrder: true,
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production'),
PRERENDER: false,
ASSETS_CDN_PREFIX: JSON.stringify(process.env.ASSETS_CDN_PREFIX || ''),
},
}),
new AssetsPlugin(),
new CleanPlugin([path.join(__dirname, 'build', 'public')]),
new CompressionPlugin(),
// new BundleAnalyzerPlugin(),
],
module: {
rules: [
{
test: /\.jsx?$/,
include: path.join(__dirname, 'src'),
exclude: lazyRouteRegex,
use: [
{
loader: 'babel-loader',
},
],
},
{
test: lazyRouteRegex,
include: path.resolve(__dirname, 'src'),
use: [
{
loader: 'bundle-loader',
options: {
lazy: true,
},
},
{
loader: 'babel-loader',
},
],
},
{
test: /swiper.*\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: false,
importLoaders: 1,
},
},
{
loader: 'postcss-loader',
},
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths,
data: `$assetprefix: "${process.env.ASSETS_CDN_PREFIX || ''}";`,
},
},
},
],
},
{
test: /\.s?css$/,
exclude: /swiper.*\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: true,
},
},
{
loader: 'postcss-loader',
},
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths,
data: `$assetprefix: "${process.env.ASSETS_CDN_PREFIX || ''}";`,
},
},
},
],
},
{
test: /\.svg$/,
use: `svg-inline-loader?removeTags&removingTags[]=${['defs', 'style', 'title'].join(',removingTags[]=')}`,
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.css', '.scss', '.json'],
},
target: 'web',
};

In react, Websocket connection failed error in react after installed webpack and deploy to DigitalOcean

Here is my webpack config:
webpack.common.js
const { ContextReplacementPlugin, IgnorePlugin } = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
const path = require('path');
const babelOptions = {
babelrc: true,
extends: path.join(__dirname, '/.babelrc'),
cacheDirectory: true,
};
module.exports = {
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '/',
assetModuleFilename: '[path][contenthash][ext]',
},
stats: {
all: false,
modules: true,
errors: true,
warnings: true,
moduleTrace: true,
errorDetails: true,
performance: true,
reasons: true,
assets: true,
assetsSort: 'size',
usedExports: true,
},
resolve: {
extensions: [
'.webpack.js',
'.web.js',
'.mjs',
'.js',
'.jsx',
'.json',
'.ts',
'.tsx',
],
alias: {
// assets: path.resolve(__dirname, 'src/assets'),
react: path.resolve('./node_modules/react'),
},
},
module: {
rules: [
{
test: /\.mjs$/,
include: /node_modules/,
type: 'javascript/auto',
},
{
test: /\.mp4$/,
use: 'file-loader?name=videos/[name].[ext]',
},
{
test: /\.(jpe?g|png|gif|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
// Inline files smaller than 10 kB (10240 bytes)
maxSize: 10 * 1024,
},
},
use: [
{
loader: 'image-webpack-loader',
options: {
name: '[path][contenthash].[ext]',
},
},
],
},
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: babelOptions,
},
{
loader: 'ts-loader',
options: { transpileOnly: true },
},
],
},
{
test: /\.jsx?$/,
exclude: /node_modules\/(?!(kdbush|supercluster)\/).*/,
use: [
{
loader: 'babel-loader',
options: babelOptions,
},
],
},
{
test: /\.js$/,
use: 'source-map-loader',
enforce: 'pre',
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/index.html'),
// favicon: './public/favicon.ico',
// filename: 'index.html',
// manifest: './public/manifest.json',
}),
new ContextReplacementPlugin(/\/ethers\//, (data) => {
delete data.dependencies[0].critical;
return data;
}),
new NodePolyfillPlugin({
excludeAliases: ['console'],
}),
new ForkTsCheckerWebpackPlugin(),
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, 'public/favicon.ico'),
to: path.resolve(__dirname, 'build/favicon.ico'),
},
{
from: path.resolve(__dirname, 'public/manifest.json'),
to: path.resolve(__dirname, 'build/manifest.json'),
},
],
}),
],
ignoreWarnings: [/Failed to parse source map/],
devServer: {
historyApiFallback: true,
client: {
webSocketURL: 'ws://0.0.0.0:8080/ws',
},
},
};
webpack.prod.js
const CompressionPlugin = require('compression-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const { merge } = require('webpack-merge');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const ClosurePlugin = require('closure-webpack-plugin');
const webpack = require('webpack');
const Dotenv = require('dotenv-webpack');
const common = require('./webpack.common');
require('dotenv').config();
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map',
output: { filename: 'js/[name].[contenthash].js' },
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'resolve-url-loader',
'sass-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: 'styles/[name].[contenthash].css',
chunkFilename: 'styles/[id].[contenthash].css',
}),
new Dotenv({ systemvars: true }),
new CompressionPlugin({
filename: '[path][base].gz[query]',
test: /\.(js|css)$/,
algorithm: 'gzip',
compressionOptions: {
level: 9,
},
}),
new CompressionPlugin({
filename: '[path][base].br[query]',
test: /\.(js|css)$/,
algorithm: 'brotliCompress',
compressionOptions: {
level: 11,
},
}),
],
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
name(module) {
const nodeModulePath = module.context.match(
/[\\/]node_modules[\\/](.*?)([\\/]|$)/
);
if (nodeModulePath) {
const packageName = nodeModulePath[1];
// npm package names are URL-safe, but some servers don't like # symbols
return `npm.${packageName.replace('#', '')}`;
}
},
},
},
},
minimizer: [
new TerserPlugin(),
new CssMinimizerPlugin(),
new ClosurePlugin({ mode: 'STANDARD' }, {}),
],
},
devServer: { allowedHosts: 'all' },
});
The error is
Error Message in chrome devTool
This project is working in my local. Not working after deployment to digitalOcean.
I think the websocket port has the problem.
To fix this, how can I config webpack for production?
Please let me know your thought.
Thanks!

React 17 and webpack 5 not working in IE11

I have looked into everything I could about the migration to react 17 and webpack 5. This for an application that is also running on IE11. And after all the changes (as you will see in the code) , according to evrything I read, it still doesnt work. I get the same error . When I look at the bundle and open it, there is a const there, which belongs to es6. It means that there was not translation, despite all the babel change I made.
If someone has an idea what could be done it would great!
Here is my webpack fike:
const webpack = require('webpack');
const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const autoprefixer = require('autoprefixer');
const Dotenv = require('dotenv-webpack')
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
const nodeEnv = process.env.NODE_ENV || "development"
const simulateProd = process.env.SIMULATE_PROD
const isProdEnv = nodeEnv === 'production'
const isNotDevEnv = nodeEnv !== "development"
const buildPath =
const sourcePath =
const imagesPath =
const iconsPath =
const soundsPath = ;
// Common plugins
const plugins = [
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
process: 'process/browser',
}),
new MiniCssExtractPlugin(),
new webpack.LoaderOptionsPlugin({
options: {
postcss: [
autoprefixer(),
],
context: sourcePath,
},
}),
new CopyWebpackPlugin(
{
patterns: [
{from: iconsPath, to: 'icons'},
{from: imagesPath, to: 'images'}
]
}
),
new Dotenv({
systemvars: true
}),
new HtmlWebpackPlugin({
template: path.join(sourcePath, 'index.html'),
path: buildPath,
filename: 'index.html',
}),
]
// Common rules
const rules = [
{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
plugins: ['react-hot-loader/babel'],
presets: ["#babel/preset-env"] //Preset used for env setup
}
// use: [
// 'babel-loader',
// ],
},
{
test: /\.s[ac]ss$/i,
exclude: /node_modules/,
use: [
{
// creates style nodes from JS strings
loader: "style-loader",
// options: {sourceMap: true}
},
// Translates CSS into CommonJS
{
loader: 'css-loader',
options: {
importLoaders: 1,
url: false,
modules: {localIdentName: "[path]___[name]__[local]___[hash:base64:5]"}
}
},
{
loader:"resolve-url-loader"
},
{
// compiles Sass to CSS
loader: "sass-loader",
options: {
sourceMap: true
}
},
],
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "style-loader", 'css-loader'],
},
{
test: /\.(ico|jpe?g|png|gif|svg|mp3|html)$/,
include: [imagesPath, soundsPath],
type: 'asset/resource',
// use: 'file-loader',
// generator: {
// filename: '[path][name].[ext]'
// },
},
{
test: /\.md$/,
use: 'raw-loader'
}
]
if (isProdEnv) {
// Production plugins
plugins.push(
new TerserPlugin({
// cache: true,
parallel: true,
// sourceMap: true
})
)
}
else {
// Development plugins
}
module.exports = smp.wrap({
mode : isNotDevEnv ? 'production' : 'development',
target: ['web', 'es5'],
experiments: {
asset: true
},
devtool: isNotDevEnv ? false : 'source-map',
context: sourcePath,
entry: {
js: ['react-hot-loader/patch','./index.js'],
},
output: {
path: buildPath,
publicPath: '/',
filename: "bundle.js",
assetModuleFilename: '[path][name].[ext]'
},
module: {
rules,
},
resolve: {
extensions: ['.webpack-loader.js', '.web-loader.js', '.loader.js', '.js', '.jsx', '.md', '.scss', '.css'],
modules: [
path.resolve(__dirname, 'node_modules'),
sourcePath,
],
fallback: {
"buffer": require.resolve('buffers'),
"assert": require.resolve('assert/'),
"fs": false,
"os": false,
"path": false,
"zlib": require.resolve('browserify-zlib'),
"stream": require.resolve('stream-browserify'),
"crypto": false,
} ,
},
plugins,
optimization : {
moduleIds: 'named',
sideEffects: isProdEnv,
},
devServer: {
contentBase: isNotDevEnv ? buildPath : sourcePath,
historyApiFallback: true,
port: 8080,
compress: isNotDevEnv,
inline: !isNotDevEnv,
hot: !isNotDevEnv,
host: "localhost",
disableHostCheck: true,
stats: {
assets: true,
children: false,
chunks: false,
hash: false,
modules: false,
publicPath: false,
timings: true,
version: false,
warnings: true,
colors: {
green: '\u001b[32m',
},
},
},
});
Here is my babel.config.json file:
{
"presets": [
[
"#babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": "3",
"targets": {
"browsers": ["last 5 versions", "ie >= 9"]
}
}
],
"#babel/preset-typescript",
"#babel/preset-react"
],
"plugins": [
"#babel/plugin-proposal-object-rest-spread",
["#babel/plugin-proposal-decorators", { "legacy": true }],
"react-hot-loader/babel",
"#babel/plugin-transform-arrow-functions",
"#babel/plugin-proposal-optional-chaining",
"#babel/plugin-proposal-nullish-coalescing-operator",
"#babel/plugin-proposal-class-properties",
[
"#babel/plugin-transform-modules-commonjs",
{
"allowTopLevelThis": true
}
]
]
}
at the start of my src/index.js
there is that :
require('es6-promise/auto')
require('string.prototype.startswith')
require('string.prototype.endswith')
import 'react-app-polyfill/ie11';
import "react-app-polyfill/stable";
import "core-js/stable";
import "regenerator-runtime/runtime";
in my package.json I added that:
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all",
"IE 11"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version",
"IE 11"
]
},
Thank you !

Webpack 5 module federation missing chunk when dynamically loading remote module

I am trying to split a big monolith React app into micro-frontends using webpack module federation.
I already have the remote module deployed and working great when running the dev server locally, everything works perfectly fine.
But after running yarn build and deploying the consumer app, it fails with the following error:
Uncaught (in promise) ChunkLoadError: Loading chunk 935 failed.
When commenting out the lazy loaded remote module, everything works fine.
Anyone have any idea how to get webpack to build correctly with a remotely loaded module?
This is my consumer component:
import WorkOrderTrackingErrorBoundary from './work_order_tracking_error_boundary'
const WorkOrderTracking = lazy(() => import('dMove/WorkOrderTracking'))
const WorkOrderTrackingPage = (props) => {
const spinner = (
<SpinnerContainer>
<Spinner type="bars" color="#3e145e" width="48px"/>
</SpinnerContainer>
)
return (
<Suspense fallback={spinner}>
<WorkOrderTrackingErrorBoundary>
<WorkOrderTracking/>
</WorkOrderTrackingErrorBoundary>
</Suspense>
);
};
export default WorkOrderTrackingPage;
and this is my webpack.prod.config.js file:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const StringReplacePlugin = require('string-replace-webpack-plugin');
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const paths = require('./paths');
const path = require('path');
module.exports = {
bail: true,
mode: 'production',
devtool: 'source-map',
module: {
rules: [
{
oneOf: [
{
test: /\.(js|jsx)$/,
exclude: paths.appNodeModules,
use: {
loader: 'babel-loader'
}
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader'
}
]
},
{
test: [
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/,
/\.svg$/
],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]'
}
},
{
exclude: [paths.appResources, paths.appNodeModules],
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
}
]
},
{
include: [paths.appResources, paths.appNodeModules],
test: /\.css$/,
use: [
{
loader: 'style-loader' // creates style nodes from JS strings
},
{
loader: 'css-loader' // translates CSS into CommonJS
}
]
},
{
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]'
}
}
]
}
]
},
plugins: [
new ModuleFederationPlugin({
name: "dView", // name of this project
filename: "remoteEntry.js", // entry file to this project, remoteEntry.js is the conventional name
exposes: {
// components exposed out for other projects to consume
},
remotes: {
// projects to consume
dMove: "dMove#https://dmove-dev.3dsignals.io/remoteEntry.js"
},
shared: {
// shared modules between projects
react: {singleton: true},
"react-dom": {singleton: true}
}
}),
new webpack.DefinePlugin({
"GET_API_TOKEN_URL": JSON.stringify("/security/getAPIToken"),
"GET_REFRESH_TOKEN_URL": JSON.stringify("/security/refreshToken"),
"LOGIN_WITH_FOREIGN_IDM": JSON.stringify("/security/foreignLogin"),
"MAPBOX_API_TOKEN": JSON.stringify("pk.eyJ1IjoiM2RzZGV2b3BzIiwiYSI6ImNrazB2ZHJ2bTBsOTMydnJ1cG40dXc2NjYifQ.pGAk7cQ-ekRJY9KSSrW3lg")
}),
new StringReplacePlugin(),
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
}
}),
new NodePolyfillPlugin()
],
output: {
filename: 'static/js/bundle.js',
chunkFilename: 'static/js/[name].[contenthash].chunk.js',
publicPath: '/',
path: paths.appBuild,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')
},
entry: [
'#babel/polyfill',
paths.appIndexJs
],
resolve: {
modules: [
'node_modules',
paths.appNodeModules,
paths.appSrc,
paths.appResources
],
extensions: [
'.web.js',
'.mjs',
'.js',
'.json',
'.web.jsx',
'.jsx',
'tsx',
'ts'
]
}
};
ChunkLoadError: Loading chunk 946 failed. (missing:
I was also facing the missing - Uncaught (in promise) ChunkLoadError: Loading chunk 935 failed when access the chunks of another remote entry js and other chunks in development server but it's working fine local environment.
This chunk file was loading but content type showing as text/html instead of application/javascript when file loads in network tab response header.
You can check the response header - content type as application/javascript..If no then try to check nginx web server config for MIME types.
For me, it worked well in UAT but SIT was showing this error.
Hopes this will help to understand the reason of chunk files missing error.
In your webpack.prod.config.js file, eagerly load all of your shared libaries -
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const StringReplacePlugin = require('string-replace-webpack-plugin');
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const paths = require('./paths');
const path = require('path');
//DO THIS
const packageJson = require("../package.json");
const eagerlyLoadedDependencyObject = Object.keys(
packageJson.dependencies
).reduce((obj, val) => {
obj[val] = {
eager: true,
};
return obj;
}, {});
module.exports = {
bail: true,
mode: 'production',
devtool: 'source-map',
module: {
rules: [
{
oneOf: [
{
test: /\.(js|jsx)$/,
exclude: paths.appNodeModules,
use: {
loader: 'babel-loader'
}
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader'
}
]
},
{
test: [
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/,
/\.svg$/
],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]'
}
},
{
exclude: [paths.appResources, paths.appNodeModules],
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
}
]
},
{
include: [paths.appResources, paths.appNodeModules],
test: /\.css$/,
use: [
{
loader: 'style-loader' // creates style nodes from JS strings
},
{
loader: 'css-loader' // translates CSS into CommonJS
}
]
},
{
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]'
}
}
]
}
]
},
plugins: [
new ModuleFederationPlugin({
name: "dView", // name of this project
filename: "remoteEntry.js", // entry file to this project, remoteEntry.js is the conventional name
exposes: {
// components exposed out for other projects to consume
},
remotes: {
// projects to consume
dMove: "dMove#https://dmove-dev.3dsignals.io/remoteEntry.js"
},
shared: packageJson.dependencies,
}),
new webpack.DefinePlugin({
"GET_API_TOKEN_URL": JSON.stringify("/security/getAPIToken"),
"GET_REFRESH_TOKEN_URL": JSON.stringify("/security/refreshToken"),
"LOGIN_WITH_FOREIGN_IDM": JSON.stringify("/security/foreignLogin"),
"MAPBOX_API_TOKEN": JSON.stringify("pk.eyJ1IjoiM2RzZGV2b3BzIiwiYSI6ImNrazB2ZHJ2bTBsOTMydnJ1cG40dXc2NjYifQ.pGAk7cQ-ekRJY9KSSrW3lg")
}),
new StringReplacePlugin(),
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
}
}),
new NodePolyfillPlugin()
],
output: {
filename: 'static/js/bundle.js',
chunkFilename: 'static/js/[name].[contenthash].chunk.js',
publicPath: '/',
path: paths.appBuild,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')
},
entry: [
'#babel/polyfill',
paths.appIndexJs
],
resolve: {
modules: [
'node_modules',
paths.appNodeModules,
paths.appSrc,
paths.appResources
],
extensions: [
'.web.js',
'.mjs',
'.js',
'.json',
'.web.jsx',
'.jsx',
'tsx',
'ts'
]
}
};
eagerlyLoadedDependencyObject changes your dependencies from -
{
"react": "17.0.2",
"react-dom": "17.0.2",
"react-redux": "7.2.6",
"react-router-dom": "5.3.4"
}
to this -
{
"react":
{
"eager": true
},
"react-dom":
{
"eager": true
},
"react-redux":
{
"eager": true
},
"react-router-dom":
{
"eager": true
}
}

Computed Properties not working with Babel preset-env

I'm trying to use computed properties in my Material UI style object, but I've getting an unexpected token error.
Below is the code snippet, error, and babel-webpack config.
const useStyles = makeStyles(theme => {
root: {
[desktop]: {
width: "80%",
}
}
});
//webpack.config.babel.js
...
const config = {
entry: ['#babel/polyfill', './src/components/index.js'],
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
devServer: {
host: '0.0.0.0',
historyApiFallback: {
index: 'index.dev.html',
},
},
output: {
path: path.resolve(__dirname, 'build'),
filename: 'main.js',
chunkFilename: '[name].js',
publicPath: '/build/',
},
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true,
extractComments: true,
}),
new OptimizeCSSAssetsPlugin({}),
],
splitChunks: {
cacheGroups: {
default: false,
vendors: {
// name of the chunk
name: 'vendor',
// sync + async chunks
chunks: 'all',
// import file path containing node_modules
test: /node_modules/,
priority: 20,
},
styles: {
name: 'styles',
test: /\.css$/,
chunks: "all",
enforce: true,
},
common: {
name: 'common',
minChunks: 2,
chunks: 'all',
priority: 10,
reuseExistingChunk: true,
enforce: true,
},
},
},
},
module: {
rules: [
{
test: /\.(js|ts)x?$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
'#babel/typescript',
"#babel/preset-env",
'#babel/preset-react',
'#babel/preset-flow',
],
plugins: [
'#babel/plugin-transform-runtime',
'#babel/plugin-proposal-object-rest-spread',
['#babel/plugin-proposal-decorators', {legacy: true}],
['#babel/plugin-proposal-class-properties', {loose: true}],
['#babel/plugin-transform-computed-properties', {loose: true}],
],
},
},
{
test: /\.s?[ac]ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
],
},
],
},
node: {
fs: 'empty',
},
// First array is dev only, second is production
plugins: devMode
? [
] : [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
],
};
// Exports
module.exports = config;
at Object.raise (/node_modules/#babel/parser/lib/index.js:6931:17)
at Object.unexpected (/node_modules/#babel/parser/lib/index.js:8324:16)
at Object.semicolon (/node_modules/#babel/parser/lib/index.js:8306:40)
at Object.parseExpressionStatement (/node_modules/#babel/parser/lib/index.js:11147:10)
at Object.parseExpressionStatement (/node_modules/#babel/parser/lib/index.js:2072:18)
at Object.parseStatementContent (/node_modules/#babel/parser/lib/index.js:10746:19)
at Object.parseStatement (/node_modules/#babel/parser/lib/index.js:10612:17)
at Object.parseStatement (/node_modules/#babel/parser/lib/index.js:2045:26)
at Object.parseBlockOrModuleBlockBody (/node_modules/#babel/parser/lib/index.js:11188:25)
at Object.parseBlockBody (/node_modules/#babel/parser/lib/index.js:11175:10)
at Object.parseBlock (/node_modules/#babel/parser/lib/index.js:11159:10)
at Object.parseStatementContent (/node_modules/#babel/parser/lib/index.js:10688:21)
at Object.parseStatement (/node_modules/#babel/parser/lib/index.js:10612:17)
at Object.parseStatement (/node_modules/#babel/parser/lib/index.js:2045:26)
at Object.parseLabeledStatement (/node_modules/#babel/parser/lib/index.js:11139:22)
at Object.parseStatementContent (/node_modules/#babel/parser/lib/index.js:10744:19)
Well this was a simple mistake. I didn't enclose my object in parentheses (missing return).
const useStyles = makeStyles((theme) => ({
root: {
[desktop]: {
...
}
}
}));

Resources