代碼分割(Code Splitting)
來自專欄 前端譯欄Code-Splitting - React
一 打包
React應用流行用類似Webpack和Browserify打包(bundled)。打包就是把導入的多個文件合併到一個文件的過程: 這個bundle就可以被引入到一個網頁進行載入。
例子
- 原始代碼
//app.jsimport { add } from ./math.js;console.log(add(16, 26));//math.jsexport function add(a,b){ return a+b;}
- 打包之後:
function add(a,b){ return a+b;}console.log(add(16, 26));
二 代碼分割
隨著應用擴展,包(bunle)會越來越大。尤其是如果引入了龐大的第三方庫。你必須留意你引入的包的大小。防止你打包之後,app載入需要太長時間。
為了防止弄出來一個大包,代碼分割是一個比較好的解決辦法。代碼分割是Webpack和Browserify(通過factor-bundle)的一個特性。允許創建多個包,然後在運行時(runtime)載入。
代碼分割可以幫助App實現『懶載入』當前用戶需要的那一部分,而不必全部載入。這樣動態載入能提高應用性能表現。
使用 import()語法
引入代碼分割的最好方式是使用動態import語法。
import { add } from ./math;console.log(add(16,26));
使用動態import()語法之後
import("./math").then(math=>{ console.log(math.add(16, 26));})
- 注意: 動態import()語法是ECMAScript提案,不是標準。
當Webpack遇到這個語法,它就會自動切割你的app.如果你使用CreateReactApp腳手架,可以立即使用.
如果你自己使用Webpack來配置,那麼你的Webpack配置大致應該像這樣
如果用Babel,你要確保Babel可以解析動態import語法而不是轉譯這個語法。這需要用 babel-plugin-syntax-dynamic-import。
使用庫實現代碼分割
React Loadable用一種React方式友好地封裝了動態import語法
- 使用之前
import OtherComponent from .OtherComponent;const MyComponent = () =>( <OtherComponent/>)
- 使用React Loadable之後
import Loadable from react-loadable;const LoadableOtherComponent = Loadable({ loader: ()=> import(./OtherComponent), loading:()=> <div>Loading...</div>})const MyComponent = () => ( <LoadableOtherComponent/>)
React Loadable幫助你創建很多,比如:
function Loading() { return <div>Loading...</div>;}Loadable({ loader: () => import(./WillFailToLoad), // oh no! loading: Loading,});
function Loading(props) { if (props.error) { return <div>Error! <button onClick={ props.retry }>Retry</button></div>; } else { return <div>Loading...</div>; }}
3.超時提示
function Loading(props) { if (props.error) { return <div>Error! <button onClick={ props.retry }>Retry</button></div>; } else if (props.timedOut) { return <div>Taking a long time... <button onClick={ props.retry }>Retry</button></div>; } else if (props.pastDelay) { return <div>Loading...</div>; } else { return null; }}
4.預載入
const LoadableBar = Loadable({ loader: () => import(./Bar), loading: Loading,});class MyComponent extends React.Component { state = { showBar: false }; onClick = () => { this.setState({ showBar: true }); }; onMouseOver = () => { LoadableBar.preload(); }; render() { return ( <div> <button onClick={this.onClick} onMouseOver={this.onMouseOver}> Show Bar </button> {this.state.showBar && <LoadableBar/>} </div> ) }}
5.服務端渲染
以路由為基礎代碼分割
在什麼地方決定使用代碼分割是比較麻煩的地方。
先從路由開始是一個比較好的方法。大多數人會用頁間動畫切換,這需要一些時間。頁間切換的時候,用戶不太會跟頁面上的元素交互。
下面是一個以路由為基礎的代碼分割例子:
import { BrowserRouter as Router, Route, Switch } from react-router-dom;import Loadable from react-loadable;const Loading = () => <div>Loading...</div>;const Home = Loadable({ loader: () => import(./routes/Home), loading: Loading,});const About = Loadable({ loader: () => import(./routes/About), loading: Loading,});const App = () => ( <Router> <Switch> <Route exact path="/" component={Home}/> <Route path="/about" component={About}/> </Switch> </Router>);
推薦閱讀:
※AI 代碼長啥樣?
※sqli-labs注入工具(第六關利用注入POC)
※你若眼熟,真的純屬巧合。
※【實驗】Adversarial Video Generation