React 可加载 JSON 映射文件,其中包含从多个位置引用的组件

Posted

技术标签:

【中文标题】React 可加载 JSON 映射文件,其中包含从多个位置引用的组件【英文标题】:React Loadable JSON mapping file with components being referenced from multiple locations 【发布时间】:2018-12-15 09:11:04 【问题描述】:

我正在使用React Loadable 对我的组件进行代码拆分,但问题是某些组件是从多个位置引用的。例如,我有这个组件CarsModule,它在多个区域中被引用,如下所示:

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>
  
);

dist/react-loadable.json 文件中最终发生的事情是 CarsModule 看起来像这样:

"../../../../components/CarsModule": [
  
    "id": 822,
    "name": "./dist/components/CarsModule/index.js",
    "file": "0-78a53ff810acc75b6fde.js",
    "publicPath": "http://localhost:3000/dist/0-78a53ff810acc75b6fde.js"
  
],

当其中一个页面在服务器端渲染期间请求它时,像这样'../components/CarsModule' 导入它时,它会为模块未定义(因为包的键是这个"../../../../components/CarsModule")。我使用webpackChunkName 尝试在react-loadable.json 文件中命名这些键,但没有运气:(

我的 webpack prod 文件中正在进行块散列,如下所示:

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,
  ],
;

但是,没有创建 CarsModule.js 文件。如果react-loadable.json 打算使用导入位置作为键,我该如何解决多个组件从不同位置导入相同模块的问题?

如果我从我的项目中删除这些正在执行不同导入的其他文件,将生成 react-loadable.json 文件引用 CarsModule,如下所示:

"../components/CarsModule": [
  
    "id": 822,
    "name": "./dist/components/CarsModule/index.js",
    "file": "0-78a53ff810acc75b6fde.js",
    "publicPath": "http://localhost:3000/dist/0-78a53ff810acc75b6fde.js"
  
],

但是,这不是一个非常合理的解决方案,因为其他组件仍然需要引用该 CarsModule。任何想法我做错了什么?提前致谢!

这是我的react-loadablewebpack 版本:

"react-loadable": "^5.4.0"
"webpack": "^3.5.6"

这是我的.babelrc 文件:


  "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
    ]
  ]

【问题讨论】:

【参考方案1】:

是否将模块解析器别名添加到您的 .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>
  
);

【讨论】:

以上是关于React 可加载 JSON 映射文件,其中包含从多个位置引用的组件的主要内容,如果未能解决你的问题,请参考以下文章

React - 加载 JSON 并渲染组件

React:如何加载和渲染外部 html 文件?

React 页面无法通过带有相对文件路径的 JSON 加载图像

从 JSON 文件动态加载图像位置 - (找不到模块...) React, Next.js

将不相交的力有向图放入 React 应用程序

在 React 中映射 JSON 数组时如何使用 onClick 定位列表中的单个项目