网页包。使用 `import()` 后加载块失败
Wepback. Loading chunk failed after using `import()`
我正在处理 React
项目,我发现其中一个 budles 文件太大,我需要拆分它。所以,我尝试使用 import()
语法:
import React from 'react';
import thumbnails from './thumbnails.json';
export default class Portfolio extends React.Component {
constructor(props) {
super(props);
import('react-image-gallery').then(module => {
const ImageGallery = module.default;
this.galleries = thumbnails.map((thumbnail, i) => {
let items = [];
for (let i = 0; i < thumbnail.gallery.amount; i++) {
items.push({
original: `${thumbnail.gallery.href}/${i}.png`,
thumbnail: `${thumbnail.gallery.href}/${i}m.png`,
})
}
return (
<div className="gallery">
<ImageGallery key={i} items={items} thumbnailPosition="left" showPlayButton={false}
onImageLoad={this.onGalleryLoad.bind(this, thumbnail.gallery.amount)}/>
<button className="gallery__close" onClick={this.onCloseClick.bind(this)}>×</button>
</div>
)
});
});
}
Portfolio
是一页的主要组成部分。后来打开页面报错Uncaught (in promise) ChunkLoadError: Loading chunk 0 failed.
如我所见,JavaScript 尝试从 portfolio
目录加载文件 0.bundle.js
。而需要的块是位于根目录中的0.chunk.js
。
这是我的 Wepback 配置:
const TerserPlugin = require('terser-webpack-plugin');
module.exports = env => {
const isDev = env.MODE === 'development';
return {
mode: isDev ? 'development' : 'production',
devtool: 'source-map',
entry: {
'./home/script': './home/script.jsx',
'./portfolio/script': './portfolio/script.jsx',
'./prices/script': './prices/script.jsx',
'./contacts/script': './contacts/script.jsx',
'./extra/script': './extra/script.jsx',
'./extra/locations/script': './extra/locations/script.jsx',
'./extra/poses/script': './extra/poses/script.jsx',
'./extra/stylists/script': './extra/stylists/script.jsx',
'./extra/studios/script': './extra/studios/script.jsx',
},
output: {
path: __dirname,
publicPath: __dirname,
filename: '[name].bundle.js',
chunkFilename: '[name].chunk.js',
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['@babel/preset-env', '@babel/react'],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-transform-runtime',
'@babel/plugin-syntax-dynamic-import',
]
}
}
},
],
},
optimization: {
minimize: !isDev,
minimizer: [new TerserPlugin({
test: /.js$/i,
extractComments: false,
terserOptions: {
output: {
comments: false,
},
},
})],
},
resolve: {
extensions: ['.jsx', '.js'],
}
}
};
尝试将输出对象更改为
output: {
......
chunkFilename: '[name].[chunkhash].js',
}
检查一下以供参考https://github.com/webpack/webpack/issues/9207#issuecomment-499448929
我找到了答案。为了避免在子目录中搜索,你应该在 webpack 的输出选项中使用 publicPath: '/'
。它被建议使用块哈希,但正如我所尝试的那样,它并不是真正必要的。整个解决方案在这里:
output: {
path: __dirname,
publicPath: '/',
filename: '[name].bundle.js',
chunkFilename: './assets/chunks/[name].chunk.js',
}
./assets/chunks/
部分不是必需的。它只是为了将所有块保存在一个目录中
我正在处理 React
项目,我发现其中一个 budles 文件太大,我需要拆分它。所以,我尝试使用 import()
语法:
import React from 'react';
import thumbnails from './thumbnails.json';
export default class Portfolio extends React.Component {
constructor(props) {
super(props);
import('react-image-gallery').then(module => {
const ImageGallery = module.default;
this.galleries = thumbnails.map((thumbnail, i) => {
let items = [];
for (let i = 0; i < thumbnail.gallery.amount; i++) {
items.push({
original: `${thumbnail.gallery.href}/${i}.png`,
thumbnail: `${thumbnail.gallery.href}/${i}m.png`,
})
}
return (
<div className="gallery">
<ImageGallery key={i} items={items} thumbnailPosition="left" showPlayButton={false}
onImageLoad={this.onGalleryLoad.bind(this, thumbnail.gallery.amount)}/>
<button className="gallery__close" onClick={this.onCloseClick.bind(this)}>×</button>
</div>
)
});
});
}
Portfolio
是一页的主要组成部分。后来打开页面报错Uncaught (in promise) ChunkLoadError: Loading chunk 0 failed.
如我所见,JavaScript 尝试从 portfolio
目录加载文件 0.bundle.js
。而需要的块是位于根目录中的0.chunk.js
。
这是我的 Wepback 配置:
const TerserPlugin = require('terser-webpack-plugin');
module.exports = env => {
const isDev = env.MODE === 'development';
return {
mode: isDev ? 'development' : 'production',
devtool: 'source-map',
entry: {
'./home/script': './home/script.jsx',
'./portfolio/script': './portfolio/script.jsx',
'./prices/script': './prices/script.jsx',
'./contacts/script': './contacts/script.jsx',
'./extra/script': './extra/script.jsx',
'./extra/locations/script': './extra/locations/script.jsx',
'./extra/poses/script': './extra/poses/script.jsx',
'./extra/stylists/script': './extra/stylists/script.jsx',
'./extra/studios/script': './extra/studios/script.jsx',
},
output: {
path: __dirname,
publicPath: __dirname,
filename: '[name].bundle.js',
chunkFilename: '[name].chunk.js',
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['@babel/preset-env', '@babel/react'],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-transform-runtime',
'@babel/plugin-syntax-dynamic-import',
]
}
}
},
],
},
optimization: {
minimize: !isDev,
minimizer: [new TerserPlugin({
test: /.js$/i,
extractComments: false,
terserOptions: {
output: {
comments: false,
},
},
})],
},
resolve: {
extensions: ['.jsx', '.js'],
}
}
};
尝试将输出对象更改为
output: {
......
chunkFilename: '[name].[chunkhash].js',
}
检查一下以供参考https://github.com/webpack/webpack/issues/9207#issuecomment-499448929
我找到了答案。为了避免在子目录中搜索,你应该在 webpack 的输出选项中使用 publicPath: '/'
。它被建议使用块哈希,但正如我所尝试的那样,它并不是真正必要的。整个解决方案在这里:
output: {
path: __dirname,
publicPath: '/',
filename: '[name].bundle.js',
chunkFilename: './assets/chunks/[name].chunk.js',
}
./assets/chunks/
部分不是必需的。它只是为了将所有块保存在一个目录中