项目升级为react-router4后,就尝试着根据官方文档进行代码分割。https://reacttraining.com/react-router/web/guides/code-splitting

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

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

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

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

根据webpack文档 https://webpack.js.org/guides/code-splitting/ 推荐的代码分割的方式是  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 <div></div>
5 }
6 //注意props的传递,在组件与Switch,嵌套的时候会有涉及
7 //增加lazyKey属性,对应moduleA.router.jsx对应的key值
8 class Bundle extends Component {
9 state = {
10 mod: null
11 }
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: null
24 })
25 props.load(mod => {
26 this.setState({
27 mod: mod[key] ? mod[key] : mod
28 })
29 })
30 }
31 render() {
32 return this.state.mod?<this.state.mod {...this.props} />:<Loading/>
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 (<Route component={component[componentKey] || component} {...props}/>);
45 } else {
46 //通过this.componentMap进行缓存,防止不必要的组件重新加载
47 if (!this.componentMap[path]) {
48 this.componentMap[path] = function(props) {
49 return (<Bundle load={component} lazyKey={componentKey} {...props}></Bundle>)
50 }
51 }
52 return (<Route component={this.componentMap[path]} {...props}/>);
53 }
54 }
55 }
56 export {Bundle as default, LazyRoute}

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

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

参考文件

http://geek.csdn.net/news/detail/135599    使用 Webpack 打包单页应用的正确姿势

https://sebastianblade.com/using-webpack-to-achieve-long-term-cache/ 用 webpack 实现持久化缓存

[转] react-router4 + webpack Code Splitting的更多相关文章

  1. webpack Code Splitting浅析

    Code Splitting是webpack的一个重要特性,他允许你将代码打包生成多个bundle.对多页应用来说,它是必须的,因为必须要配置多个入口生成多个bundle:对于单页应用来说,如果只打包 ...

  2. react-router4 + webpack Code Splitting

    项目升级为react-router4后,就尝试着根据官方文档进行代码分割.https://reacttraining.com/react-router/web/guides/code-splittin ...

  3. [Webpack 2] Maintain sane file sizes with webpack code splitting

    As a Single Page Application grows in size, the size of the payload can become a real problem for pe ...

  4. webpack code splitting

    一.代码分割优化 const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin' ...

  5. webpack优化之code splitting

    作为当前风头正盛的打包工具,webpack风靡前端界.确实作为引领了一个时代的打包工具,很多方面都带来了颠覆性的改进,让我们更加的感受到自动化的快感.不过最为大家诟病的一点就是用起来太难了. 要想愉快 ...

  6. webpack 利用Code Splitting 分批打包、按需下载

    webpack中的解决方案——Code Splitting,简单来说就是按需加载(下载),如果是requireJS对应的AMD的方案中这本是在正常不过了.但是在webpack中All in one的思 ...

  7. webpack 和 code splitting

    Code Splitting指的是代码分割,那么什么是代码分割,webpack和code splitting又有什么样的联系呢? 使用npm run dev:"webpack-dev-ser ...

  8. webpack async load modules & dynamic code splitting

    webpack async load modules & dynamic code splitting webpack 按需/异步加载/Code Splitting webpack loade ...

  9. 借助Code Splitting 提升单页面应用性能

    近日的工作集中于一个单页面应用(Single-page application),在项目中尝试了闻名已久的Code splitting,收获极大,特此分享. Why we need code spli ...

随机推荐

  1. ibevent 和 libev 提高网络应用性能【转】

    转自:https://www.cnblogs.com/kunhu/p/3632285.html 构建现代的服务器应用程序需要以某种方法同时接收数百.数千甚至数万个事件,无论它们是内部请求还是网络连接, ...

  2. use snippet save dom to excel

    1.打开贴吧 http://tieba.baidu.com/f?ie=utf-8&kw=python&fr=search 2.打开console执行下面命令 Array.prototy ...

  3. Nginx 开启目录下载

    平时应用中,我们大都用apache搭建下载页面.毕竟Apache搭建起来非常方便,yum安装,创建目录就可以了. 但有时还是需要用nginx配置下载页面.这里就是一个简单的配置nginx下载页面的过程 ...

  4. C++ 解析Json——jsoncpp

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,和xml类似,本文主要对VS2008中使用Jsoncpp解析json的方法做一下记录.Jsoncpp是个跨 ...

  5. Android App签名打包

    Andriod应用程序如果要在手机或模拟器上安装,必须要有签名!  1.签名的意义 为了保证每个应用程序开发商合法ID,防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序 ...

  6. JS如何截取一段字符中,某一个字符的前面和后面的字符

    比如这里的1992631934@qq.com如何获取到@前面的1992631934和@后面的qq.com js代码如下: var mail="1992631934@qq.com" ...

  7. C# web Api ajax发送json对象到action中

    直接上代码: 1.Product实体

  8. python-面向对象入门

    一.面向对象介绍 介绍面向对象之前,先来回顾一下以前学的面向过程的编程思想 面向过程编程: 核心是过程二字,过程指的是解决问题的步骤,即先干什么,再干什么后干什么,基于该思想编程就好比是在设计一条流水 ...

  9. 并发性能的隐形杀手之伪共享(false sharing)

    在并发编程过程中,我们大部分的焦点都放在如何控制共享变量的访问控制上(代码层面),但是很少人会关注系统硬件及 JVM 底层相关的影响因素.前段时间学习了一个牛X的高性能异步处理框架 Disruptor ...

  10. 手机CPU架构体系分类及各大厂商

    手机cpu相关知识,这对于开发Android应用程序适应各个机型有一定的辅助作用 . 手机cpu架构体系分类 指令集可分为复杂指令集(CISC)和精简指令集(RISC)两部分,代表架构分别是x86.A ...