基於vue和react的spa進行按需載入
基於vue和react的spa進行按需載入
由於最近打算將所有的管理系統採用同一套登陸方法,然後在登陸後進行系統的切換選擇,不需要每個系統都去重新登陸一次,所以前端這邊思考將所有的系統用一套spa的應用進行構建,但是各個系統的合併之後,打包後的程式碼應該是相當大的,單頁需要一次性載入所有系統的資源,顯得不合實際,所以打算將不同系統的資源進行分離,再選擇後在載入該系統的相應資源。自己發現這個業務和每個系統的路由比較類似,因此將系統的配置基於vue-router或者react-router的基礎進行按需載入處理。因此自己瞭解了一下按需載入的應用和配置方案。
基於該業務大家有其他解決方案歡迎交流(_O_ )
按需載入
隨著單頁應用的發展,整個系統的所有功能都集合在一個頁面,該頁面一次性載入所有的資源,隨著系統的不斷擴充套件,因此所載入的資源會不斷的增大,雖然經過壓縮處理,大大的減小了資源的內容量,但是不能從本質上減小資源內容的增多。
其實我們的模組對應不同的資源,就類似之前所做的多頁系統,不同的頁面載入對應的資原始檔,所以可以參考之前的的多頁系統的做法,在單頁系統中根據不同的模組載入其對應的資原始檔。就是使用者當前需要用什麼功能就只加載這個功能對應的程式碼,也就是所謂的按需載入。
如何按需載入
在單頁應用做按需載入,一般採用以下原則
- 把整個系統劃分成一個個小功能,再按照功能的相關程度劃分為幾類。
- 把每一類合併為一個Chunk,按需載入對應的Chunk
- 對於首屏看到的內容直接放到入口Chunk中,以降低網頁首次載入資源的個數
-
對於其他的模組可以做按需載入。
被分割出去的程式碼的載入需要一定的機制去觸發,也就是當用戶即將操作到對應的功能時再去載入。被分割出去的程式碼的載入時機需要開發者根據自己系統的需求去衡量確定。
因為被分割出去的程式碼載入也需要一定的時間,所以可以提前做預載入處理。
import()
在開始下面的案例之前先了解一下import(),這裡的import()不同於引入模組的import xxx from 'xxx',這裡的import是指一個動態載入模組的函式,傳入的引數就是相應的模組,但是import()會返回一個Promise物件,因此可以在import()完成後根據其狀態進行處理。
//eg import('/component/details').then(mod=>{ console.log(mod) },error=>{ console.log(error) })
vue按需載入的應用
1.模組分割
根據自己系統的情況,個人根據vue-router的模組來進行分割,
//roter配置的分割程式碼 import Vue from 'vue' import Router from 'vue-router' const listnav=()=> import('@/components/listnav') const adminav=()=> import('@/components/adminav') Vue.use(Router) const router = new Router({ routes:[{ path:'/listnav', name:'listnav', component:listnav }, { path:'/adminav', name:'adminav', component:adminav } ] }) export default router
2.webpack輸出檔案配置
//webpack.base.conf.js moudle.exports = { entry:{ app:'./src/main.js' }, output:{ path:"../dist", filename:'js/[name].js', chunkFilename:'js/[name].js' } }
react按需載入應用
1,模組分割
同樣模組分割可採用react-router進行劃分
//router配置分割程式碼 import React, {PureComponent, Component ,createElement} from 'react'; import {HashRouter as Router, Route,Link,withRouter} from 'react-router-dom'; import Home from "../component/home" function getAsyncComponent(load) { return class AsyncComponent extends PureComponent { constructor(props) { super(props); } componentDidMount() { // 在高階元件 DidMount 時才去執行網路載入步驟 load().then(({default: component}) => { // 程式碼載入成功,獲取到了程式碼匯出的值,呼叫 setState 通知高階元件重新渲染子元件 this.setState({ component, }) }); } render() { const {component} = this.state || {}; // component 是 React.Component 型別,需要通過 React.createElement 生產一個元件例項 return component ? createElement(component) : null; } } } const Routes = () =>( <HashRouter> <Route path="/home/:test" exact component={Home}/> <Route path='/details/:id' component={getAsyncComponent( // 非同步載入函式,非同步地載入 details元件 () => import('../component/details') )}/> </HashRouter> ) export default Routers;
2.webpack輸出檔案配置
//webpack.base.config.js module.exports = { entry:{ main: "../src/index.js", //入口檔案 }, output:{ path:"../dist",//出口檔案 filename:"js/[name].js", chunkFilename:"js/[name].js", publicPath: '' } }
3.按需載入元件中的props傳遞
在按需載入劃分後,按需載入的元件不能接收到傳遞來的props,因此不能通過this.props.match.params來獲取router配置時所帶入的引數。
解決方法利用react-router中的withRouter
可以在按需載入的元件中進行配置處理
//component/details.js import React, { Component } from 'react'; import {withRouter} from 'react-router-dom'; class Details extends Component { constructor(props) { super(props); } render() { console.log(this.props) return ( <div></div> ) } } export default withRouter(Details);
參考連結
vue-router路由懶載入 [ofollow,noindex">https://router.vuejs.org/zh/guide/advanced/lazy-loading.html]
React按需載入[http://webpack.wuhaolin.cn/4%E4%BC%98%E5%8C%96/4-12%E6%8C%89%E9%9C%80%E5%8A%A0%E8%BD%BD.html]
更多參考大家自行查詢。