zoukankan      html  css  js  c++  java
  • webpack v3 结合 react-router v4 做 dynamic import — 按需加载(懒加载)

    为什么要做dynamic import?

    dynamic import不知道为什么有很多叫法,什么按需加载,懒加载,Code Splitting,代码分页等。
    总之,就是在SPA,把JS代码分成N个页面份数的文件,不在用户刚进来就全部引入,而是等用户跳转路由的时候,再加载对应的JS文件。
    这样做的好处就是加速首屏显示速度,同时也减少了资源的浪费。

    为什么选择 webpack 3?

    • 更高的性能
    • 有scope hosting功能,不再需要rollup来处理代码冗余
    • 可与react-router结合,更优雅的做dynamic import
    • 最重要的一点是,我正经学webpack的时候3已结出了- -

    完整的 react spa 项目地址

    GitHub项目地址

    这个一个完整的项目,这节相关的内容可在router/routerMap.jsx中找到。

    第一步:安装 babel-plugin-syntax-dynamic-import

    babel用的是babel-env,使用方法可以去babel官方学习,实践可看我项目的源代码。

    npm i -D babel-plugin-syntax-dynamic-import 以后, 在.babelrc文件的plungins中加上"syntax-dynamic-import"

    第二步:安装 react-loadable

    npm i -S react-loadable 以后,我们就能愉快得做dynamic import了。

    第三步: 编辑routerMap

    
    import React from 'react';
    import { HashRouter as Router, Route, Switch } from 'react-router-dom';
    import createHistory from 'history/createBrowserHistory';
    const history = createHistory();
    
    import App from 'containers';
    
    // 按路由拆分代码
    import Loadable from 'react-loadable';
    const MyLoadingComponent = ({ isLoading, error }) => {
        // Handle the loading state
        if (isLoading) {
            return <div>Loading...</div>;
        }
        // Handle the error state
        else if (error) {
            return <div>Sorry, there was a problem loading the page.</div>;
        }
        else {
            return null;
        }
    };
    const AsyncHome = Loadable({
        loader: () => import('../containers/Home'),
        loading: MyLoadingComponent
    });
    const AsyncCity = Loadable({
        loader: () => import('../containers/City'),
        loading: MyLoadingComponent
    });
    const AsyncDetail = Loadable({
        loader: () => import('../containers/Detail'),
        loading: MyLoadingComponent
    });
    const AsyncSearch = Loadable({
        loader: () => import('../containers/Search'),
        loading: MyLoadingComponent
    });
    const AsyncUser = Loadable({
        loader: () => import('../containers/User'),
        loading: MyLoadingComponent
    });
    const AsyncNotFound = Loadable({
        loader: () => import('../containers/404'),
        loading: MyLoadingComponent
    });
    
    // 路由配置
    class RouteMap extends React.Component {
        render() {
            return (
                <Router history={history}>
                    <App>
                        <Switch>
                            <Route path="/" exact component={AsyncHome} />
                            <Route path="/city" component={AsyncCity} />
                            <Route path="/search/:category/:keywords?" component={AsyncSearch} />
                            <Route path="/detail/:id" component={AsyncDetail} />
                            <Route path="/user" component={AsyncUser} />
                            <Route path="/empty" component={null} key="empty" />
                            <Route component={AsyncNotFound} />
                        </Switch>
                    </App>
                </Router>
            );
            // 说明
            // empty Route
            // https://github.com/ReactTraining/react-router/issues/1982  解决人:PFight
            // 解决react-router v4改变查询参数并不会刷新或者说重载组件的问题 
        }
    }
    
    export default RouteMap;
    

    大功告成

    我们可以运行webpack,然后就能看到效果(图仅为dev环境,build才会再打包一个vendor.js,为什么要有vendor.js,请见devDependencies和dependencies的区别 >>

    参考文章

    Code Splitting in Create React App

    Q&A

    有同学表示,我的方法做页面分离并没有什么好处,因为每个页面都依赖了三方库的代码,所以其实页面有很多冗余代码,能想到这点很棒,已经开始有架构思维了。不过,注意这个想法在dev环境下,这个同学是对的。

    那到了build环境,或者说到了发布环境,又是怎么样的呢?的确,这篇文章我没有提到,请见我的另一篇文章devDependencies和dependencies的区别。这篇文章主要解释了npm的package.json中devDependencies和dependencies区别是什么。

    看完以后,我们就可以知道,为什么我之前说“注意这个想法在dev环境下,这个同学是对的”了。因为,我们npm run build以后,webpack会把三方包打包到vendor.js文件,页面逻辑代码不会牵涉其中,每个页面都会引用vendor.js这个文件,这样的话,就不会出现重复引入冗余代码的情况了。

    来源:https://segmentfault.com/a/1190000011128817

  • 相关阅读:
    discuz Ucenter第三方双向同步登录
    python: 输出 1~100 之间不能被 7 整除的数,每行输出 10 个数字,要求应用字符串格式化方法美化输出格式。
    用python语言来判断一个数是否是水仙花数?
    java如何调用webservice接口
    ASP.NET 全局变量和页面间传值方法
    从客户端中检测到有潜在危险的 Request.Form 值] 处理办法
    第一次作业要点及重要属性
    Servlet生命周期
    cookie与session的比较
    零基础学习HTML5
  • 原文地址:https://www.cnblogs.com/qixidi/p/10160830.html
Copyright © 2011-2022 走看看