博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转] react-router4 + webpack Code Splitting
阅读量:6268 次
发布时间:2019-06-22

本文共 4420 字,大约阅读时间需要 14 分钟。

项目升级为react-router4后,就尝试着根据官方文档进行代码分割。

在实际项目中,js,css文件默认通过webpack打包的话会很大,动不动就好几兆。

在实际场景中,我们需要缩短首屏的时间展现时间,需要将 首屏没有 涉及到 其他页面的 业务和组件 进行代码分离,按需加载。

通过按需加载,如果只是修改了某个页面的逻辑,也不用整个项目文件加载,增加了浏览器缓存的利用

下面就一步一步的介绍在我的项目中是怎么实现Code Splitting的。

根据webpack文档  推荐的代码分割的方式是  import(), 当然 require.ensure() 作为兼容,还是支持的。

而react-router4 文档上说到的 bundle-loader 组件就是通过 require.ensure 实现的。

实际项目中

a.太小的文件打个包也没有太大的意义,最终考虑的是 每个一级菜单 作为分割点进行打包加载.

b.能够通过参数配置 分割打包 还是 整体打包,尽可能的在webconfig中进行配置,可以参数化

c.打包文件名字要有意义,每次打包只是某个module文件修改的话,不会影响其他js文件hash值,提高缓存利用

 

下面介绍下最终的结果,其中有些坎坷的心路历程,只能简单的略过了

1./router/moduleA.router.jsx,把需要打包在一起的文件整理到对用的文件下,方便统一管理

2.webpack.config.js

output: {        //[chunkhash:8] 设置文件摘要,用于缓存        filename: '[name].[chunkhash:8].bundle.js', //entry 对用生成文件的文件名规则        chunkFilename : '[name].[chunkhash:8].js',  //不是entry定义的文件(分离打包的模块文件,提取的共同文件),对用生成文件的文件名规则        path: TARGET,        publicPath: '/public/'    },    plugins: [        //...        //...        //** 设置打包id生成规则,以文件地址 + hash 形式,是生成的  webpack 模块id固定,参见参考文献        new webpack.HashedModuleIdsPlugin(),        //提取的共同文件插件配置        new webpack.optimize.CommonsChunkPlugin({            //在模块中如果存在的功用的话,也进行提取设置            //如moduleA,moduleB 中都用了编辑器,entry中没有,则会抽出公用打包在一个  数字.hash.js 中            async: true,             minChunks: 2 //有2处使用的js文件就提取        }),         //vendor: entry文件中用到的共用文件打包在vendor文件        //** manifest: 增加这个配置,则把一个加载的id信息统一到一个文件,这样就可以实现每次打包未改的文件生成的hash不变,参见参考文献        new webpack.optimize.CommonsChunkPlugin({            names: ['vendor', 'manifest']        }),        //对应的 chunks 加上 'manifest', 'vendor'        new HtmlWebpackPlugin({            filename: `${page.name}.html`,            template: `${ROOT_PATH}/template.ejs`,            chunks: ['manifest', 'vendor', page.name]        }    ],    module: {        rules: [{                test: /\.router\.jsx/,                loader: [                    //根据文件后缀.router.jsx 设置规则,主要是name 和 regExp 的实现,这个可以查看bundle-loader源代码就能发现相关的支持                    //现在的逻辑是取文件名,/router/moduleA.router.jsx 则打包成 moduleA.hash.js                    'bundle-loader?lazy&name=[1]&regExp=([^\\\\\\/]*)\\.router\\.jsx',                    'babel-loader',                ],                exclude: /node_modules|assets/            }, {                test: /\.jsx?$/,                loader: 'babel-loader',                exclude: /node_modules|assets/            }        ]    },
bundle-loader name参数,regExp参数的应用是查看的源代码,一开始想看看是通过什么实现异步加载,就看见了相关插件的源代码 require.ensure(),想要打包的文件打包在一起,只需要下面代码中的 chunkNameParam 设置成同一个值就可以了, 实际情况考虑到更好的管理文件,就通过取.router.jsx前面的文件名 进行命名

  

 3.Bundle.jsx

1 import React, { Component } from 'react' 2 import { Route } from 'react-router-dom'; 3 const Loading = function () { 4     return 
5 } 6 //注意props的传递,在组件与Switch,嵌套的时候会有涉及 7 //增加lazyKey属性,对应moduleA.router.jsx对应的key值 8 class Bundle extends Component { 9 state = {10 mod: null11 }12 componentWillMount() {13 this.load(this.props)14 }15 componentWillReceiveProps(nextProps) {16 if (nextProps.load !== this.props.load) {17 this.load(nextProps)18 }19 }20 load(props) {21 var key = props.lazyKey || 'default';22 this.setState({23 mod: null24 })25 props.load(mod => {26 this.setState({27 mod: mod[key] ? mod[key] : mod28 })29 })30 }31 render() {32 return this.state.mod?
:
33 }34 }35 //注意props的传递,在组件与Switch,嵌套的时候会有涉及36 //通过isLazy进行是否分离打包配置,LazyRoute组件不是必要的,各自需求各自处理37 class LazyRoute extends React.PureComponent{38 componentMap = {};39 render() {40 let {menu, ...props} = this.props;41 let {component, isLazy, componentKey, path} = menu;42 componentKey = componentKey || 'default';43 if (!isLazy) {44 return (
);45 } else {46 //通过this.componentMap进行缓存,防止不必要的组件重新加载47 if (!this.componentMap[path]) {48 this.componentMap[path] = function(props) {49 return (
)50 }51 }52 return (
);53 } 54 }55 }56 export {Bundle as default, LazyRoute}

 

实际的打包效果,还是可以的,代码得到了分离。有些地方还可以优化,比如 第3方lib包不怎么会变的,和 自己写的组件 进行不同的提取合并。文献中都有提及。

极致的按需加载 和 异步加载,对代码 组件了解的要求比较高,现在主要还是通过webpack 公共提取 做基本的优化

 

参考文件

    使用 Webpack 打包单页应用的正确姿势

 用 webpack 实现持久化缓存

转载于:https://www.cnblogs.com/chris-oil/p/8457528.html

你可能感兴趣的文章
html5游戏开发-简单tiger机
查看>>
Codeforces 712C Memory and De-Evolution
查看>>
编写的windows程序,崩溃时产生crash dump文件的办法
查看>>
Ural2110 : Remove or Maximize
查看>>
Django REST framework 的TokenAuth认证及外键Serializer基本实现
查看>>
《ArcGIS Runtime SDK for Android开发笔记》——问题集:如何解决ArcGIS Runtime SDK for Android中文标注无法显示的问题(转载)...
查看>>
Spring Boot日志管理
查看>>
动态注册HttpModule管道,实现global.asax功能
查看>>
使用 ES2015 编写 Gulp 构建
查看>>
[转]Using NLog for ASP.NET Core to write custom information to the database
查看>>
BZOJ 4766: 文艺计算姬 [矩阵树定理 快速乘]
查看>>
MySQL 的instr函数
查看>>
Hibernate的核心对象关系映射
查看>>
接口与抽象类的使用选择
查看>>
if __name__ == '__main__'
查看>>
CF 375D. Tree and Queries【莫队 | dsu on tree】
查看>>
Maven最佳实践 划分模块 配置多模块项目 pom modules
查看>>
Hadoop学习笔记——WordCount
查看>>
Unity应用架构设计(4)——设计可复用的SubView和SubViewModel(Part 1)
查看>>
Java-Spring-获取Request,Response对象
查看>>