The error
I get the following error when (what appears to be) vendor scripts that try downloading:
index.js:1 loadable-components: failed to asynchronously load component
{fileName: undefined, chunkName: undefined, error: 'Loading chunk 1117 failed.\n(missing: http://localhost:3002/1117.a60143c46b916ef6a52d.vendor.js)'}
I don't know if this helps but when I don't obfuscate the file names, 1117 is the node_modules styled-components script.
The resource exists in the public directory in the correct output path and according to the network tab it gets downloaded successfully.
Script 1117.a60143c46b916ef6a52d.vendor.js 200 script astronomix.js:1 13.5 kB 11 ms
Troubleshooting
- I have a UI library with
loadable-components
exports to create the chunks. - The client consuming apps throw this error which started happening yesterday.
- I reverted the code back a few weeks for both apps and it still broke.
- I created a quick CRA and it breaks there too.
- I replaced
loadable-components
withReact.lazy
and I still encountered issues. - I thought there was an error with one of the components, I isolated it by creating only one component without Styled Components. This breaks unless I remove code splitting. Components render correctly then.
Webpack config
const path = require('path');
const postcss = require('postcss');
const cssnano = require('cssnano');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { LicenseWebpackPlugin } = require('license-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const webpack = require('webpack');
const PUBLIC_PATH = process.env.PUBLIC_PATH || '/';
module.exports = {
mode: 'production',
devtool: false,
entry: {
library: './src/components/index.js',
},
output: {
publicPath: PUBLIC_PATH,
filename: '[name].js',
sourceMapFilename: '[id].[contenthash].lib.map',
chunkFilename: '[id].[contenthash].lib.js',
path: path.resolve(__dirname, 'dist/'),
library: 'MyLibrary',
libraryTarget: 'umd',
globalObject: 'this',
assetModuleFilename: 'images/[name].[contenthash][ext][query]',
},
externals: {
react: {
root: 'React',
commonjs: 'react',
commonjs2: 'react',
amd: 'react',
},
'react-dom': {
root: 'ReactDOM',
commonjs: 'react-dom',
commonjs2: 'react-dom',
amd: 'ReactDOM',
},
},
resolve: {
extensions: ['.js'],
alias: {
react: path.resolve('./node_modules/react'),
'react-dom': path.resolve('./node_modules/react-dom'),
},
},
optimization: {
usedExports: true,
minimize: true,
emitOnErrors: true,
removeAvailableModules: true,
concatenateModules: true,
moduleIds: 'deterministic',
splitChunks: {
chunks: 'async',
minSize: 20000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
reuseExistingChunk: false,
filename: (pathData) => {
return `${pathData.chunk.id}.[contenthash].vendor.js`;
},
},
default: {
reuseExistingChunk: false,
},
},
},
minimizer: [
new MiniCssExtractPlugin({
filename: (pathData) => {
return `${pathData.chunk.name}.[contenthash].min.css`;
},
chunkFilename: (pathData) => {
return `${pathData.chunk.id}.[contenthash].min.css`;
},
}),
new TerserPlugin({
terserOptions: {
format: {
// Tell terser to remove all comments except for the banner added via LicenseWebpackPlugin.
// This can be customized further to allow other types of comments to show up in the final js file as well.
// See the terser documentation for format.comments options for more details.
comments: (astNode, comment) => {
return comment.value.startsWith('! licenses are at ');
},
},
// This option was added to fix the following error in 10n6:
// Uncaught TypeError: Super expression must either be null or a function
keep_fnames: true,
},
extractComments: false, // prevents TerserPlugin from extracting a [chunkName].js.LICENSE.txt file
}),
],
},
plugins: [
// This makes it possible for us to safely use env vars on our code
new webpack.DefinePlugin({
// https://webpack.js.org/guides/public-path/#root
'process.env.PUBLIC_PATH': JSON.stringify(PUBLIC_PATH),
}),
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
patterns: [
{
from: 'src/vendors/**/*.css',
to: './css/[name].[contenthash].min[ext]',
transform: (content, path) => {
return postcss([cssnano])
.process(content, {
from: path,
})
.then((result) => {
return result.css;
});
},
},
],
}),
new LicenseWebpackPlugin({
addBanner: true,
renderBanner: (filename, modules) => {
return `/*! licenses are at ${filename}*/`;
},
handleMissingLicenseText: (packageName, licenseType) => {
console.log(`No license found for ${packageName}`);
return 'UNKNOWN';
},
licenseTextOverrides: {
'styled-components':
'https://github.com/styled-components/styled-components/blob/main/LICENSE',
'use-onclickoutside': 'No license found',
'use-latest': 'No license found',
'are-passive-events-supported': 'No license found',
'react-select':
'MIT | https://github.com/JedWatson/react-select/blob/master/LICENSE',
},
}),
],
module: {
rules: [
{ oneOf: [{ type: 'javascript/auto' }] },
{
test: /\.(js|jsx)$/,
exclude: [/\/node_modules\//, /\/demos\//],
loader: 'babel-loader',
},
{
test: /\.(png|jpg|jpeg|webp|gif|svg|ico)$/,
type: 'asset/resource',
},
{
test: /\.(s*)css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
},
};
Dependencies
...
"devDependencies": {
"@babel/core": "7.18.10",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-transform-react-jsx": "7.18.10",
"@babel/preset-env": "7.18.10",
"@babel/preset-react": "7.18.6",
"@loadable/component": "5.15.2",
"@react-theming/storybook-addon": "1.1.7",
"@storybook/addon-actions": "6.5.10",
"@storybook/addon-console": "1.2.3",
"@storybook/addon-docs": "6.5.10",
"@storybook/addon-essentials": "6.5.10",
"@storybook/addon-links": "6.5.10",
"@storybook/addon-storyshots": "6.5.10",
"@storybook/builder-webpack5": "6.5.10",
"@storybook/manager-webpack5": "6.5.10",
"@storybook/node-logger": "6.5.10",
"@storybook/preset-create-react-app": "4.1.2",
"@storybook/react": "6.5.10",
"@wojtekmaj/enzyme-adapter-react-17": "0.6.7",
"babel-jest": "28.1.3",
"babel-loader": "8.2.5",
"babel-plugin-styled-components": "2.0.7",
"babel-plugin-transform-react-jsx": "6.24.1",
"bootstrap": "5.2.0",
"classnames": "2.3.1",
"clean-webpack-plugin": "4.0.0",
"copy-webpack-plugin": "11.0.0",
"core-js": "3.24.1",
"css-loader": "6.7.1",
"css-minimizer-webpack-plugin": "4.0.0",
"cssnano": "5.1.12",
"date-fns": "2.29.1",
"enzyme": "3.11.0",
"enzyme-to-json": "3.6.2",
"eslint": "8.21.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jsx-a11y": "6.6.1",
"eslint-plugin-react": "7.30.1",
"eslint-plugin-storybook": "0.6.3",
"jest": "28.1.3",
"jest-environment-enzyme": "7.1.2",
"jest-environment-jsdom": "28.1.3",
"jest-enzyme": "7.1.2",
"jest-styled-components": "7.0.8",
"license-webpack-plugin": "4.0.2",
"mini-css-extract-plugin": "2.6.1",
"node-sass": "7.0.1",
"numeral": "2.0.6",
"prettier": "2.7.1",
"prop-types": "15.8.1",
"ramda": "0.28.0",
"react-bootstrap": "2.4.0",
"react-helmet": "6.1.0",
"react-icons": "4.4.0",
"react-is": "18.2.0",
"react-places-autocomplete": "7.3.0",
"react-scripts": "5.0.1",
"react-select": "5.4.0",
"react-test-renderer": "17.0.2",
"regenerator-runtime": "0.13.9",
"sass": "1.54.2",
"sass-loader": "13.0.2",
"styled-components": "5.3.5",
"terser-webpack-plugin": "5.3.3",
"use-onclickoutside": "0.4.1",
"webpack": "5.74.0",
"webpack-cli": "4.10.0"
},
"peerDependencies": {
"react": "17.0.2",
"react-dom": "17.0.2"
}
...
Code splitting
import loadable from '@loadable/component';
global.SC_DISABLE_SPEEDY = true;
export const Theme = loadable(() => import('./Theme'), {
resolveComponent: (component) => component.default,
});
...
Other
Related question but did not assist in solving the problem loadable-components: failed to asynchronously load component. Let me know if you need anything else.
Edits
Stacktrace
Uncaught ChunkLoadError: Loading chunk 2526 failed.
(missing: http://localhost:3002/2526.4c1d9fbd8f9d0aa16a08.vendor.js)
at __webpack_require__.f.j (library.js:1:1)
at library.js:1:1
at Array.reduce (<anonymous>)
at __webpack_require__.e (library.js:1:1)
at h.resolveComponent [as requireAsync] (library.js:1:1)
at cachedLoad (library.js:1:1)
at InnerLoadable.resolveAsync (library.js:1:1)
at InnerLoadable.loadAsync (library.js:1:1)
at InnerLoadable.componentDidMount (library.js:1:1)
at commitLifeCycles (react-dom.development.js:20663:1)
at commitLayoutEffects (react-dom.development.js:23426:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)
at invokeGuardedCallback (react-dom.development.js:4056:1)
at commitRootImpl (react-dom.development.js:23151:1)
at unstable_runWithPriority (scheduler.development.js:468:1)
at runWithPriority$1 (react-dom.development.js:11276:1)
at commitRoot (react-dom.development.js:22990:1)
at performSyncWorkOnRoot (react-dom.development.js:22329:1)
at scheduleUpdateOnFiber (react-dom.development.js:21881:1)
at updateContainer (react-dom.development.js:25482:1)
at react-dom.development.js:26021:1
at unbatchedUpdates (react-dom.development.js:22431:1)
at legacyRenderSubtreeIntoContainer (react-dom.development.js:26020:1)
at Object.render (react-dom.development.js:26103:1)
at Module.<anonymous> (index.js:5:1)
at ./src/index.js (index.js:7:1)
at __webpack_require__ (bootstrap:851:1)
at fn (bootstrap:150:1)
at 1 (index.js:7:1)
at __webpack_require__ (bootstrap:851:1)
at checkDeferredModules (bootstrap:45:1)
at Array.webpackJsonpCallback [as push] (bootstrap:32:1)
at main.chunk.js:1:71