I'm using React + Typescript with Webpack and I'm trying to load some of my react components when they are actually needed.
The issue is that when the chunk is requested via lazy loading I'm getting the following error:
Uncaught Error: Loading chunk 1 failed. (error: http://localhost:58988/1.chunk.js) at HTMLScriptElement.onScriptComplete (bootstrap:114)
This chunk is generated successfully and without any errors, it's just that the path is wrong - http://localhost:58988/1.chunk.js
and it should be http://localhost:58988/dist/1.chunk.js
I've also tried using the newest React.lazy
to lazy load react components but I'm getting the same issue. So, is there a way to tell the compiler how to resolve these file paths?
Here's some of the code:
MyComponent.tsx
import * as React from "react";
import * as ES5Promise from "promise";
export class MyComponent extends React.Component<{}, {}> {
constructor(props) {
super(props);
}
private readonly onLoadModuleClickHandler = (): void => {
import("./Button").then((module) => {
console.log(module);
});
}
render() {
return (
<div>
<input type="button" value="Load another module" onClick={this.onLoadModuleClickHandler}/>
</div>
);
}
}
tsconfig.json
{
"compilerOptions": {
"moduleResolution": "node",
"noImplicitAny": false,
"noEmitOnError": true,
"module": "esnext",
"removeComments": false,
"sourceMap": false,
"target": "es5",
"jsx": "react",
"noEmit": true,
"importHelpers": true,
"lib": ["dom", "es5", "es2015.promise"]
},
"exclude": [
"node_modules",
"wwwroot"
]
}
webpack.config.js
module.exports = {
entry: {
"app": "./src/App.tsx"
},
output: {
path: path.resolve(__dirname, 'wwwroot/dist'),
filename: "[name].bundle.js",
chunkFilename: "[name].chunk.js"
},
module: {
rules: [
{
test: /\.(ts|tsx)?$/,
use: "awesome-typescript-loader",
exclude: /node_modules/
},
{
test: /\.(css|less)?$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader?modules&localIdentName=[local]--[hash:base64:5]"
}, {
loader: "less-loader"
}]
},
]
},
resolve: {
extensions: [".js", ".jsx", ".ts", ".tsx", ".css", ".less"]
}
};
That happens because output.publicPath
by default is /
.
Just update output.publicPath
to point where you want it to be => /dist/
.
When redeploying, on rebuilding the app bundles make sure NOT to clean the output folder with previous chunk files, because users that already have the app loaded will try to fetch previous chunk files that will not exist anymore.
Best thing to do is to have an app version tracking (using AJAX and read from db or dynamic config file) and when the app detects a newer version, message the user about it and ask them to reload the page.
Let's not over fixate on this. It only happened 5 times. I believe that somebody has excalidraw opened for a while, we push a new version in the meantime and when they get back, they try to load some lazy chunk and it is no longer there.
The way we solve this at Facebook is that we keep the previous chunks on our CDN for a week and we force refresh the app for people if the bundle is more than a week old. This way we don't need to care about very old versions.
The above response is from vjeux.
My plan is to listen for errors in window.onerror, and then prompt the user to refresh the browser.
window.addEventListener('error', e => {
// prompt user to confirm refresh
if (/Loading chunk [\d]+ failed/.test(e.message)) {
window.location.reload();
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With