webpack - React Loadable JSON mapping file with components being referenced from multiple locations
问题描述
I'm using React Loadable to code split my components, but the problem is that certain components are referenced from multiple locations. For example, I have this component CarsModule
, which is referenced in multiple areas like this:
const CarsModule = Loadable({
loader: () => import(/* webpackChunkName: "CarsModule" */ '../components/CarsModule'),
loading() {
return <div>Loading...</div>
}
});
const CarsModule = Loadable({
loader: () => import(/* webpackChunkName: "CarsModule" */ '../../../../components/CarsModule'),
loading() {
return <div>Loading...</div>
}
});
const CarsModule = Loadable({
loader: () => import(/* webpackChunkName: "CarsModule" */ '../../components/CarsModule'),
loading() {
return <div>Loading...</div>
}
});
const CarsModule = Loadable({
loader: () => import(/* webpackChunkName: "CarsModule" */ '../../../../components/CarsModule'),
loading() {
return <div>Loading...</div>
}
});
What ends up happening in the dist/react-loadable.json
file is that CarsModule looks like this:
"../../../../components/CarsModule": [
{
"id": 822,
"name": "./dist/components/CarsModule/index.js",
"file": "0-78a53ff810acc75b6fde.js",
"publicPath": "http://localhost:3000/dist/0-78a53ff810acc75b6fde.js"
}
],
When one of the pages goes to request it during server side rendering that imports it like this '../components/CarsModule'
, it gets undefined for the module (since the bundle's key is this "../../../../components/CarsModule"
). I used the webpackChunkName
to try and name those keys in the react-loadable.json
file but no luck :(
I have chunk hashing going on inside my webpack prod file which looks like this:
module.exports = {
devtool: 'source-map',
context: path.resolve(__dirname, '..'),
entry: {
main: [
'babel-polyfill',
'./dist/app/defaultClient.js'
],
},
output: {
path: assetsPath,
filename: '[name]-[chunkhash].js',
chunkFilename: '[name]-[chunkhash].js',
publicPath: STATIC_HOST ? `${STATIC_HOST}/dist/` : `http://localhost:3000/dist/`,
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 2,
localIdentName: '[folder]-[local]',
minimize: true,
},
},
{
loader: 'postcss-loader',
options: {
plugins: () => [require('autoprefixer')()],
},
},
{
loader: 'sass-loader',
options: {
outputStyle: 'expanded',
sourceMap: false,
},
},
],
}),
},
{
test: /\.woff2?(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff',
},
},
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream',
},
},
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: 'file-loader',
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml',
},
},
},
{
test: webpackIsomorphicToolsPlugin.regular_expression('images'),
use: {
loader: 'url-loader',
options: {
limit: 10240,
},
},
},
],
},
resolve: {
modules: ['node_modules', 'src'],
extensions: ['.json', '.js', '.jsx'],
},
plugins: [
new CleanPlugin([assetsPath], { root: projectRootPath }),
// css files from the extract-text-plugin loader
new ExtractTextPlugin({
filename: '[name]-[chunkhash].css',
allChunks: true,
}),
new webpack.DefinePlugin({
'process.env': exportedClientAppConfigProperties,
__CLIENT__: true,
__DEVTOOLS__: false,
}),
// ignore dev config
new webpack.IgnorePlugin(/\.\/dev/, /\/config$/),
// optimizations
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
},
}),
new ReactLoadablePlugin({ filename: `./dist/react-loadable.json` }),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
webpackIsomorphicToolsPlugin,
],
};
However, there is no CarsModule.js file that is created. How can I solve this issue with multiple components importing the same module from different locations if react-loadable.json
is going to use the import location as a key?
If I remove these other files that are doing different imports from my project, the react-loadable.json file will be generated referencing the CarsModule like so:
"../components/CarsModule": [
{
"id": 822,
"name": "./dist/components/CarsModule/index.js",
"file": "0-78a53ff810acc75b6fde.js",
"publicPath": "http://localhost:3000/dist/0-78a53ff810acc75b6fde.js"
}
],
However, this isn't a very plausible solution because other components still need to reference that CarsModule. Any ideas what I'm doing wrong? Thanks in advance!
Here are my versions of react-loadable
& webpack
:
"react-loadable": "^5.4.0"
"webpack": "^3.5.6"
Here is my .babelrc
file:
{
"presets": [
["env", {
"targets": {
"node": "current",
"browsers": ["last 2 versions", "safari >= 7"]
}
}],
"stage-0",
"react"
],
"plugins": [
"dynamic-import-webpack",
"react-loadable/babel",
"syntax-async-functions",
"syntax-dynamic-import",
"transform-decorators-legacy",
["module-resolver", {
"root": ["./src/"],
}],
["transform-runtime", {
"helpers": false,
"polyfill": true
}]
]
}
解决方案
是否将模块解析器别名添加到您的.babelrc
帮助中?
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
[
"module-resolver",
{
"root": [
"."
],
"alias": {
"components": "./components",
}
}
],
"react-loadable/babel"
]
}
这样每个加载器都可以使用相同的路径字符串。
const CarsModule = Loadable({
loader: () => import(/* webpackChunkName: "CarsModule" */ 'components/CarsModule'),
loading() {
return <div>Loading...</div>
}
});
推荐阅读
- php - 样式表被自动删除/注销 - WordPress
- react-native - 安装 react-native-camera 后出现此错误。尝试按照 git 上的一些答案中的建议更改版本和 sdk 工具,但没有解决方案
- google-calendar-api - Google-Calendar API - 获取默认日历的偏移量
- java - 转换一个字节变量并将其转换为字符串
- r - Rmarkdown 中同一行的 Kableextra 表和 ggplot 图(PDF - 不是 Flexdashboard)
- batch-file - 使用循环通过批处理脚本重命名文件名
- python - 使用 tensorflow hub 再训练脚本对任何新类别的图像进行再训练的任何架构的高度不正确的预测
- javascript - nwjs chrome扩展问题
- react-native - React Native 动态组件名称错误
- android - Youtube 嵌入视频无法在小米设备 Cordova WebView 中播放