dynamic import不知道爲何有不少叫法,什麼按需加載,懶加載,Code Splitting,代碼分頁等。
總之,就是在SPA,把JS代碼分紅N個頁面份數的文件,不在用戶剛進來就所有引入,而是等用戶跳轉路由的時候,再加載對應的JS文件。
這樣作的好處就是加速首屏顯示速度,同時也減小了資源的浪費。html
GitHub項目地址react
這個一個完整的項目,這節相關的內容可在router/routerMap.jsx中找到。webpack
babel用的是babel-env,使用方法能夠去babel官方學習,實踐可看我項目的源代碼。git
npm i -D babel-plugin-syntax-dynamic-import
之後, 在.babelrc文件的plungins中加上"syntax-dynamic-import"
。github
npm i -S react-loadable
之後,咱們就能愉快得作dynamic import了。web
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的區別 >>)npm
Code Splitting in Create React Appjson
有同窗表示,個人方法作頁面分離並無什麼好處,由於每一個頁面都依賴了三方庫的代碼,因此其實頁面有不少冗餘代碼,能想到這點很棒,已經開始有架構思惟了。不過,注意這個想法在dev
環境下,這個同窗是對的。segmentfault
那到了build
環境,或者說到了發佈環境,又是怎麼樣的呢?的確,這篇文章我沒有提到,請見個人另外一篇文章devDependencies和dependencies的區別。這篇文章主要解釋了npm的package.json中devDependencies和dependencies區別是什麼。babel
看完之後,咱們就能夠知道,爲何我以前說「注意這個想法在dev
環境下,這個同窗是對的」了。由於,咱們npm run build
之後,webpack會把三方包打包到vendor.js文件,頁面邏輯代碼不會牽涉其中,每一個頁面都會引用vendor.js這個文件,這樣的話,就不會出現重複引入冗餘代碼的狀況了。