reactjs - Eroare Webpack Code Splitting 'Încărcarea fragmentului a eșuat' cale fișier greșită
Folosesc React + Typescript cu Webpack și încerc să încarc unele dintre componentele mele React doar atunci când sunt efectiv necesare.
Problema este că atunci când fragmentul este solicitat prin încărcare leneșă primesc următoarea eroare:
Eroare nepreluată: Încărcarea fragmentului 1 a eșuat. (eroare: http://localhost:58988/1.chunk.js) la HTMLScriptElement.onScriptComplete (bootstrap:114)
Acest fragment este generat cu succes și fără erori, doar că calea este greșită - http://localhost:58988/1.chunk.js și ar trebui să fie http://localhost:58988/dist/1.chunk.js
Am încercat, de asemenea, să folosesc cel mai nou React.lazy pentru a încărca componentele React pe măsură ce sunt necesare, dar întâmpin aceeași problemă. Deci, există o modalitate de a-i spune compilatorului cum să rezolve aceste căi de fișiere?
Iată câteva dintre cod:
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"]
}
};
Răspuns #1
Asta se întâmplă pentru că output.publicPath este în mod implicit /.
Doar actualizează output.publicPath pentru a indica unde vrei să fie => /dist/.
Răspunsul #2
Când realocați, la reconstruirea pachetelor aplicației asigurați-vă SĂ NU curățați folderul de ieșire cu fișierele chunk anterioare, deoarece utilizatorii care deja au aplicația încărcată vor încerca să preia fișierele chunk anterioare care nu vor mai exista.
Cel mai bine este să ai un sistem de urmărire a versiunii aplicației (folosind AJAX și citind din baza de date sau dintr-un fișier de configurare dinamic) și atunci când aplicația detectează o versiune mai nouă, să afișeze un mesaj utilizatorului și să îi ceară să reîncarce pagina.
Răspuns #3
Să nu exagerăm cu această problemă. S-a întâmplat doar de 5 ori. Cred că cineva a avut excalidraw deschis pentru o perioadă, noi lansăm o versiune nouă între timp și când se întorc, încearcă să încarce un fragment lazy și acesta nu mai este acolo.
Modul în care rezolvăm acest lucru la Facebook este că păstrăm bucățile anterioare pe CDN-ul nostru timp de o săptămână și forțăm reîmprospătarea aplicației pentru utilizatori dacă pachetul are mai mult de o săptămână. În acest fel, nu trebuie să ne facem griji cu privire la versiunile foarte vechi.
Răspunsul de mai sus este de la vjeux.
Planul meu este să ascult erorile în window.onerror și apoi să solicit utilizatorului să reîncarce browserul.
window.addEventListener('error', e => {
// prompt user to confirm refresh
if (/Loading chunk [\d]+ failed/.test(e.message)) {
window.location.reload();
}
});
