使用 React.lazy、Suspense 和 react-router-dom 进行代码拆分不起作用

Posted

技术标签:

【中文标题】使用 React.lazy、Suspense 和 react-router-dom 进行代码拆分不起作用【英文标题】:Code splitting with React.lazy, Suspense and react-router-dom doesn't work 【发布时间】:2020-01-13 05:08:47 【问题描述】:

我正在尝试设置一个非常基本的示例,类似于:https://reactjs.org/docs/code-splitting.html#route-based-code-splitting

它应该根据当前路由动态延迟加载路由组件(ModuleOne 或 ModuleTwo)及其依赖项。

但是看起来代码拆分不起作用,并且所有内容都包含在一个包中。

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = 
  entry: './src/index',
  output: 
    filename: '[name].bundle.js',
    chunkFilename: '[name].bundle.js',
    path: path.resolve(__dirname, '../dist'),
  ,
  module: 
    rules: [
      
        test: /\.tsx?$/,
        loader: 'awesome-typescript-loader',
        exclude: /node_modules/,
      
    ],
  ,
  resolve: 
    modules: ['node_modules', path.resolve(__dirname, '../src')],
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
  
;

App.tsx

import * as React from 'react';
import  HashRouter as Router, Link, Route, Switch  from 'react-router-dom';
import * as styles from './App.scss';

const LazyModuleOne = React.lazy(() => import('../modules/ModuleOne/ModuleOne'));
const LazyModuleTwo = React.lazy(() => import('../modules/ModuleTwo/ModuleTwo'));

const App = () => (
    <Router>
        <div className=styles.wrapper>
            <nav>
                <Link to="/">Start</Link>
                <Link to="/module-one">Module One</Link>
                <Link to="/module-two">Module Two</Link>
            </nav>
            <main>
                <React.Suspense fallback=<div>Loading...</div>>
                    <Switch>
                        <Route path="/module-one" component=LazyModuleOne />
                        <Route path="/module-two" component=LazyModuleTwo />
                    </Switch>
                </React.Suspense>
            </main>
        </div>
    </Router>
);

export default App;

ModuleOne.tsx

import * as React from 'react';
import * as _ from 'lodash';
import  RouteComponentProps  from 'react-router';

const apples = _.fill([1,2,3], 'apple');

const ModuleOne: React.FC<RouteComponentProps> = () => (
  <div>
    <div>ModuleOne</div>
    <div>There are apples.length apples</div>
  </div>
)

export default ModuleOne;

ModuleTwo.tsx

import * as React from 'react';
import * as R from 'ramda';
import  RouteComponentProps  from 'react-router';

const cherries = [1,2,3];

const ModuleTwo: React.SFC<RouteComponentProps> = () => (
  <div>
    <div>ModuleTwo</div>
    <div>There are R.length(cherries) cherries</div>
  </div>
)

export default ModuleTwo;

演示:

有人知道为什么基于路由的代码拆分不能按预期工作吗?

【问题讨论】:

你用的是哪个版本? @TapanDave:“webpack”:“4.39.3”,“react”:“16.9.0”,“react-dom”:“16.9.0”,“react-router-dom” : "^5.0.1" 你有运行演示的 jsfiddle 吗? @TapanDave 不,只是在本地,但我可以准备 是的,如果你能做到的话,请 【参考方案1】:

我找到了解决方案。这是TypeScript 相关的。我需要设置:


  "compilerOptions": 
    "module": "esnext",
  ,

而不是commonjs

现在代码拆分按预期工作。

【讨论】:

这可以帮助某人:当我将模块从“commonjs”更改为“esnext”时,我的编译失败了,因为我忘记了“moduleResolution”:“node”。现在可以了!【参考方案2】:

我的反应版本是 16.4.0 并且可以使用!

我和你的唯一区别:

我使用浏览器路由器。 你用过HashRouter。

【讨论】:

以上是关于使用 React.lazy、Suspense 和 react-router-dom 进行代码拆分不起作用的主要内容,如果未能解决你的问题,请参考以下文章

React.lazy和Suspense组合实现组件懒加载

React.lazy和React.Suspense异步加载组件

react lazy和suspense

使用 React Suspense 和 React.lazy 子组件进行 Jest/Enzyme 类组件测试

如何使用React.lazy和Suspense进行组件延迟加载

用React.lazy和Suspense优化React代码打包