分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

前端性能优化之按需加载(React-router+webpack)

发布时间:2023-09-06 02:12责任编辑:白小东关键词:前端webpack性能优化React

一、什么是按需加载

和异步加载script的目的一样(异步加载script的方法),按需加载/代码切割也可以解决首屏加载的速度。

  • 什么时候需要按需加载

如果是大文件,使用按需加载就十分合适。比如一个近1M的全国城市省市县的json文件,在我首屏加载的时候并不需要引入,而是当用户点击选项的时候才加载。如果不点击,则不会加载。就可以缩短首屏http请求的数量以及时间。

如果是小文件,可以不必太在意按需加载。过多的http请求会导致性能问题。

二、实现按需加载的方法

  1. Webpack打包模块工具实现
  2. RequireJs实现

这里介绍React-router+Webpack实现按需加载的功能,效果如下:

三、实现过程(React-router4.0)

注意!我这里使用的是最新版本的React-router-dom^4.3.1.如果是4.0以下的react-route可直接看四

4.0相比以前实现方式要复杂。需要引入bundle-loader模块。并且自己创建bundle模型实现。

1.创建包装组件模型bundle.js
import React from ‘react‘;class Bundle extends React.Component { ???constructor(arg){ ???????super(arg) ???????this.state = { ???????????mod: null, ???????} ???} ???????componentWillMount() { ???????this.load(this.props); ???} ???componentWillReceiveProps(nextProps) { ???????if (nextProps.load !== this.props.load) { ???????????this.load(nextProps); ???????} ???} ???// load 方法,用于更新 mod 状态 ???load(props) { ???????// 初始化 ???????this.setState({ ???????????mod: null ???????}); ???????/* ???????????调用传入的 load 方法,并传入一个回调函数 ???????????这个回调函数接收 在 load 方法内部异步获取到的组件,并将其更新为 mod ????????*/ ????????props.load(mod => { ???????????this.setState({ ???????????mod: mod.default ? mod.default : mod ???????????}); ???????}); ???} ???render() { ???????/* ???????????将存在状态中的 mod 组件作为参数传递给当前包装组件的‘子‘ ???????*/ ????????return this.state.mod ? this.props.children(this.state.mod) : null; ???}}export default Bundle ;
2.创建包装组件的方法(函数)
// 懒加载方法import React from ‘react‘;import Bundle from ‘./Bundle‘;console.log(Bundle);// 默认加载组件,可以直接返回 nullconst Loading = () => <div>Loading...</div>;/* ??包装方法,第一次调用后会返回一个组件(函数式组件) ??由于要将其作为路由下的组件,所以需要将 props 传入*/const lazyLoad = loadComponent => props => ( ??<Bundle load={loadComponent}> ?????{Comp => (Comp ? <Comp {...props} /> : <Loading />)} ??</Bundle>);console.log(lazyLoad);export default lazyLoad; ???//实际上lazyLoad就是一个函数,组件调用即可

上面两个文件的关系:
lazyLoad.js从名字上看,叫懒加载.实际上是一个中间件的作用。最后lazyLoad会暴露一个函数出来供组件调用。lazyLoad导出的内容:

function lazyLoad(loadComponent) { ???return function(props) { ???????return ( ???????????<Bundle load={loadComponent}> ???????????????{Comp => (Comp ? <Comp {...props} /> : <Loading />)} ???????????</Bundle> ???????) ???}}

显而易见,loadComponent就是要加载的组件,在路由中调用,例如:异步调用page1组件

<Route path="/page1" component={lazyLoad(Page1)}/> 

Bundle.js作为按需加载的核心,在lazyLoad中间件就已经引入,并传入一个自定义的方法load,值为组件内容。以及动态的子内容children:

{Comp => (Comp ? <Comp {...props} /> : <Loading />)}

最终返回组件信息,并附带相应的props.如果不存在相关组件,则Loading

3. Route搭配使用
import React from ‘react‘;import { NavLink,Route,Switch,BrowserRouter as Router } from ‘react-router-dom‘import ‘./style/style.css‘import ‘bundle-loader‘// bundle模型用来异步加载组件import Bundle from ‘../routes/Bundle.js‘;import lazyLoad from ‘../routes/lazyLoad‘;import Page1 from ‘bundle-loader?lazy&name=page1!../components/page1/index‘;import Page2 from ‘bundle-loader?lazy&name=page2!../components/page2/index‘;import Page3 from ‘bundle-loader?lazy&name=page3!../components/page3/index‘;class AppPage extends React.Component{ ???constructor(arg){ ???????super(arg) ???????this.state={} ???} ???render(){ ???????return( ???????????<Router ?basename="/" > ???????????????<div className="appWried"> ???????????????????<div className="appBtn"> ???????????????????????<NavLink to="/page1" className="button" activeClassName="active"> ???????????????????????????PAGE1 ???????????????????????</NavLink> ???????????????????????<NavLink to="/page2" className="button" activeClassName="active"> ???????????????????????????PAGE2 ???????????????????????</NavLink> ???????????????????????<NavLink to="/page3" className="button" activeClassName="active"> ???????????????????????????PAGE3 ???????????????????????</NavLink> ???????????????????</div> ???????????????????<Route ???????????????????????path="/" ???????????????????????render={props => ( ???????????????????????????<Switch> ???????????????????????????????<Route path="/page1" component={lazyLoad(Page1)}/> ????????????????????????????????<Route path="/page2" component={lazyLoad(Page2)}/> ????????????????????????????????<Route path="/page3" component={lazyLoad(Page3)}/> ????????????????????????????</Switch> ???????????????????????)} ???????????????????/> ???????????????</div> ???????????</Router> ???????) ???}}export default AppPage;
  • 几个注意的点:
    1. import异步加载组件的时候,名字变更为‘bundle-loader?lazy&name=page1!../components/page1/index‘

    其中bundle-loader表示loader:‘bunle-loader‘(需加载bundle-loader模块)
    lazy表示lazy:true;懒加载
    name:表示异步生成的文件名字

    1. 去掉外层route,不用render渲染也是可行的
    <Switch> ???<Route path="/page1" component={lazyLoad(Page1)}/> ????<Route path="/page2" component={lazyLoad(Page2)}/> ????<Route path="/page3" component={lazyLoad(Page3)}/> </Switch>
//webpack.config.js... ???module.exports = { ???????... ???????output:{ ???????????path:path.join(__dirname + ‘/dist‘), ???//打包地方 ???????????filename:‘bundle.js‘, ???//打包名字 ???????????publicPath: ‘/‘, ???//自动生成html引入js的路径 ???????????//按需加载 ???????????chunkFilename:‘[name]_[chunkhash:8].js‘ ???????}, ???????... ???}...

这里要注意一下publicPath这个参数.
如果未设置publicPath参数,则默认打包生成的html引入bundle的时候为:

<script type="text/javascript" src="bundle.js"></script>

如果设置publicPath为publicPath: ‘/dist‘,则打包后html文件引入js格式为:

<script type="text/javascript" src="/dist/bundle.js"></script>

参考文章:React-router-v4 - Webpack 实现按需加载(code-splitting)

前端性能优化之按需加载(React-router+webpack)

原文地址:https://www.cnblogs.com/soyxiaobi/p/9535292.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved