Webpack(bundle-loader?lazy!) + react-router 实现组件的动态加载

#1

有没大神有现成的例子参考参考 怎么写的。。。

文档看得我头都炸了。。。

几个坑我也注意了, 就是imodule.exports 和 es6的import 的坑

报错

invariant.js:44 Uncaught Error: Component(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.

TypeError: cb is not a function

我的路由配置 :

    import App from "../pages/app";
    import HelloWorld from "../pages/hellow";
    import Page1 from "../pages/page1";
    import Page2 from "../pages/page2";

    //const lazyLoadComponent = (pageName, callback) => {
    //  let pageBundle = require("bundle-loader?lazy&name="+ pageName +"!../pages/" + pageName);
    //  return pageBundle( page => callback(null, page));
    //};

    const lazyLoadComponent = lazyModule => {
      return (location, cb) => {
        lazyModule(module => cb(null, module));
      };
    };

    const routeConfig = [
      {
        path: "/",
        component: lazyLoadComponent(App),
        indexRoute: lazyLoadComponent(HelloWorld),
        childRoutes: [
          { 
            path: "page1", 
            getComponents: lazyLoadComponent(Page1)
          },
          { 
            path: "page2", 
            getComponents: lazyLoadComponent(Page2)
          }
        ]
      }
    ];

    export default routeConfig;
#2

我以前是这么用的,仅供参考

/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react';
import {
  Router, Switch, Route, Redirect,
} from 'react-router';
import { createBrowserHistory } from 'history';
import Bundle from 'components/common/Bundle';
import RouteWithSubRoutes from 'components/common/RouteWithSubRoutes.web';
import Login from 'bundle-loader?lazy&name=login!components/account/Login.web';
import CodePassword from 'bundle-loader?lazy&name=code-password!components/account/CodePassword.web';
import Register from 'bundle-loader?lazy&name=register!components/account/Register.web';
import UpdateProfile from 'bundle-loader?lazy&name=update-profile!components/account/UpdateProfile.web';
import OpenAccount from 'bundle-loader?lazy&name=open-account!components/bank/OpenAccount.web';
import ChooseBank from 'bundle-loader?lazy&name=choose-bank!components/bank/ChooseBank.web';
import BindCard from 'bundle-loader?lazy&name=bind-card!components/bank/BindCard.web';
import ProductIndex from 'bundle-loader?lazy&name=product-index!components/product/index.web';
import FundDetail from 'bundle-loader?lazy&name=fund-detail!components/product/fund/FundDetail.web';
import AssetDetail from 'bundle-loader?lazy&name=asset-detail!components/product/asset/AssetDetail.web';
import BuyChange from 'bundle-loader?lazy&name=buy-change!components/product/change/BuyChange.web';
import BuyChangeResult from 'bundle-loader?lazy&name=buy-change-result!components/product/change/BuyResult.web';
import ChangeDetail from 'bundle-loader?lazy&name=change-detail!components/product/change/ChangeDetail.web';
import RedeemChange from 'bundle-loader?lazy&name=redeem-change!components/product/change/RedeemChange.web';
import RedeemChangeResult from 'bundle-loader?lazy&name=redeem-change-result!components/product/change/RedeemResult.web';
import WalletIndex from 'bundle-loader?lazy&name=wallet-index!components/wallet/index.web';
import WalletAsset from 'bundle-loader?lazy&name=wallet-asset!components/wallet/asset/index.web';
import WalletAssetDetail from 'bundle-loader?lazy&name=wallet-asset-detail!components/wallet/asset/AssetDetail.web';
import AssetSettle from 'bundle-loader?lazy&name=asset-settle!components/wallet/asset/AssetSettle.web';
import AssetProfit from 'bundle-loader?lazy&name=asset-profit!components/wallet/asset/AssetProfit.web';
import AssetProduct from 'bundle-loader?lazy&name=asset-product!components/wallet/asset/AssetProduct.web';
import WalletFund from 'bundle-loader?lazy&name=wallet-fund!components/wallet/fund/index.web';
import WalletFundDetail from 'bundle-loader?lazy&name=wallet-fund-detail!components/wallet/fund/FundDetail.web';
import WalletTranDetail from 'bundle-loader?lazy&name=wallet-tran-detail!components/wallet/fund/TranDetail.web';
import ApplyFund from 'bundle-loader?lazy&name=apply-fund!components/wallet/fund/ApplyFund.web';
import FundCastSurely from 'bundle-loader?lazy&name=fund-cast-surely!components/wallet/fund/FundCastSurely.web';
import Redeem from 'bundle-loader?lazy&name=redeem!components/wallet/fund/Redeem.web';
import CastSurelyExplain from 'bundle-loader?lazy&name=cast-surely-explain!components/wallet/fund/CastSurelyExplain.web';
import ApplyRedResult from 'bundle-loader?lazy&name=cast-surely-explain!components/wallet/fund/ApplyRedResult.web';
import WalletPlan from 'bundle-loader?lazy&name=wallet-plan!components/wallet/plan/index.web';
import WalletHistoryPlan from 'bundle-loader?lazy&name=wallet-history-plan!components/wallet/historyplan/index.web';
import WalletSearch from 'bundle-loader?lazy&name=wallet-search!components/wallet/search/index.web';
import TradeIndex from 'bundle-loader?lazy&name=trade-index!components/wallet/trade/index.web';
import ProfitIndex from 'bundle-loader?lazy&name=profit-index!components/wallet/profit/index.web';
import MeIndex from 'bundle-loader?lazy&name=me-index!components/me/index.web';
import AboutIndex from 'bundle-loader?lazy&name=about-index!components/me/about/index.web';
import RiskIndex from 'bundle-loader?lazy&name=risk-index!components/me/risk/index.web';
import PageNotFound from 'bundle-loader?lazy&name=404!./PageNotFound.js';
import Account from 'bundle-loader?lazy&name=account!./Account';
import Bank from 'bundle-loader?lazy&name=bank!./Bank';
import Product from 'bundle-loader?lazy&name=product!./Product';
import Wallet from 'bundle-loader?lazy&name=wallet!./Wallet';
import Me from 'bundle-loader?lazy&name=me!./Me';
import Static from 'bundle-loader?lazy&name=static!./Static';
import FastRedeemAgreement from 'bundle-loader?lazy&name=fast-redeem-agreement!components/static/FastRedeemAgreement';
import FastPayAgreement from 'bundle-loader?lazy&name=fast-pay-agreement!components/static/FastPayAgreement';
import EContractAgreement from 'bundle-loader?lazy&name=e-contract!components/static/EContractAgreement';
import InvestorNotes from 'bundle-loader?lazy&name=investor-notes!components/static/InvestorNotes';
import QABindCard from 'bundle-loader?lazy&name=qa-bind-card!components/static/QABindCard';
import QACommon from 'bundle-loader?lazy&name=qa-common!components/static/QACommon';
import About from 'bundle-loader?lazy&name=about!components/static/About';
/* eslint-enable */

const history = createBrowserHistory();

const lazy = (lazyComponent) => {
  return props => (
    <Bundle load={lazyComponent}>
      { Component => <Component {...props} />}
    </Bundle>
  );
};

/* Use route config, for more centralized vision of whole routes  */
const routes = [
  {
    path: '/account',
    component: lazy(Account),
    routes: [
      {
        path: '/account/register',
        component: lazy(Register),
      }, {
        path: '/account/login/phone',
        component: lazy(Login),
      }, {
        path: '/account/login/code',
        component: lazy(CodePassword),
      }, {
        path: '/account/profile',
        component: lazy(UpdateProfile),
      },
    ],
  }, {
    path: '/bank',
    component: lazy(Bank),
    routes: [
      {
        path: '/bank/open',
        component: lazy(OpenAccount),
      }, {
        path: '/bank/choose',
        component: lazy(ChooseBank),
      }, {
        path: '/bank/bind',
        component: lazy(BindCard),
      },
    ],
  }, {
    path: '/product',
    component: lazy(Product),
    routes: [
      {
        path: '/product/fund/:id',
        component: lazy(FundDetail),
      }, {
        path: '/product/asset/:id',
        component: lazy(AssetDetail),
      }, {
        path: '/product/favorate',
        component: lazy(ProductIndex),
      }, {
        path: '/product/cash',
        component: lazy(ProductIndex),
      }, {
        path: '/product/asset',
        component: lazy(ProductIndex),
      }, {
        path: '/product/fund',
        component: lazy(ProductIndex),
      }, {
        path: '/product/change/buy/result',
        component: lazy(BuyChangeResult),
      }, {
        path: '/product/change/buy',
        component: lazy(BuyChange),
      }, {
        path: '/product/change/detail',
        component: lazy(ChangeDetail),
      }, {
        path: '/product/change/redeem/result',
        component: lazy(RedeemChangeResult),
      }, {
        path: '/product/change/redeem',
        component: lazy(RedeemChange),
      },
    ],
  }, {
    path: '/wallet',
    component: lazy(Wallet),
    routes: [
      {
        path: '/wallet/main',
        component: lazy(WalletIndex),
      }, {
        path: '/wallet/asset',
        component: lazy(WalletAsset),
      }, {
        path: '/wallet/assetdetail/:fundcode',
        component: lazy(WalletAssetDetail),
        routes: [
          {
            path: '/wallet/assetdetail/:fundcode/settle',
            component: lazy(AssetSettle),
          }, {
            path: '/wallet/assetdetail/:fundcode/profit',
            component: lazy(AssetProfit),
          }, {
            path: '/wallet/assetdetail/:fundcode/product',
            component: lazy(AssetProduct),
          },
        ],
      }, {
        path: '/wallet/fund',
        component: lazy(WalletFund),
      }, {
        path: '/wallet/tarndetail/:fundcode',
        component: lazy(WalletTranDetail),
      }, {
        path: '/wallet/funddetail/:fundcode',
        component: lazy(WalletFundDetail),
      }, {
        path: '/wallet/redeem/:fundcode',
        component: lazy(Redeem),
      }, {
        path: '/wallet/fundcastsurely/:fundcode',
        component: lazy(FundCastSurely),
      }, {
        path: '/wallet/castsurelyexplain',
        component: lazy(CastSurelyExplain),
      }, {
        path: '/wallet/applyfund/:fundcode',
        component: lazy(ApplyFund),
      }, {
        path: '/wallet/applyredresult/:value',
        component: lazy(ApplyRedResult),
      }, {
        path: '/wallet/search',
        component: lazy(WalletSearch),
        routes: [
          {
            path: '/wallet/search/trade',
            component: lazy(TradeIndex),
          }, {
            path: '/wallet/search/profit',
            component: lazy(ProfitIndex),
          },
        ],
      }, {
        path: '/wallet/plan',
        component: lazy(WalletPlan),
      }, {
        path: '/wallet/historyplan',
        component: lazy(WalletHistoryPlan),
      },
    ],
  }, {
    path: '/me',
    component: lazy(Me),
    routes: [
      {
        path: '/me/user',
        component: lazy(MeIndex),
      },
      {
        path: '/me/about',
        component: lazy(AboutIndex),
      },
      {
        path: '/me/risk/:status', // result retest testing testconfirm
        component: lazy(RiskIndex),
      },
    ],
  }, {
    path: '/static',
    component: lazy(Static),
    routes: [
      {
        path: '/static/fastredeem',
        component: lazy(FastRedeemAgreement),
      }, {
        path: '/static/fastpay',
        component: lazy(FastPayAgreement),
      }, {
        path: '/static/econtract',
        component: lazy(EContractAgreement),
      }, {
        path: '/static/investornotes',
        component: lazy(InvestorNotes),
      }, {
        path: '/static/qabindcard',
        component: lazy(QABindCard),
      }, {
        path: '/static/qacommon',
        component: lazy(QACommon),
      }, {
        path: '/static/about',
        component: lazy(About),
      },
    ],
  },
];

export default (
  <Router history={history}>
    <div>
      <Switch>
        {/* empty path to favorate product page */}
        <Redirect exact from="/" to="/product/favorate" />
        {/* 404 page */}
        <Route exact path="/404" component={lazy(PageNotFound)} />
        {/* routes */}
        {
          routes.map((route, i) => (
            <RouteWithSubRoutes key={i} {...route} />
          ))
        }
        {/* 404 page */}
        <Route path="/:any" component={lazy(PageNotFound)} />
      </Switch>
    </div>
  </Router>
);

#3

参见 https://github.com/YutHelloWorld/Blog/issues/5 分别有react-router v3 和v4配合webpack的动态加载