事情缘由

近段时间在做基于scratch3.0的改造项目。基于scratch-gui改造,项目本身已经很大了,然后里面还要用到scratch-blocks,scratch-vm,scratch-render等外部第三方项目。官方的配置是所有的东西打入一个lib中,所有的html都使用这一个lib。

现在有一个需求是:h5页面仅仅展示scratch做出来的作品,但是目前加载很慢,需要优化。

scratch原生的打包配置如下(html-webapck-plugin@3.2.0)

打包结果全部js在lib.min中,有26M左右

优化思路

第一阶段(不更改代码,仅仅做分包的优化):

  • 利用webpack optimization.splitChunks的vendors配置将所有的第三方包提取到vendors中【本人额外配置了一个所有入口都使用的第三方包bundle:‘vender.min'】;
  • 利用webpack optimization.splitChunks的default配置【默认的配置】自动提取各个入口js的共用代码组成bundle的功能。
  • 分离出manifest文件,确保没有更改的包打包结果不会更改。

上面基本都利用了默认的配置【不配置的属性即使用默认值】,webpack默认的配置【每一个版本还不太一样,比如最近的maxAsyncRequests已经是6了,maxInitialRequests为4】如下

module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};

优化配置如下,

打包结果如下:chunks中

其中vendors*.js 和 blocksonly~compatibilitytesting~gui~player.js即是默认的vendors和default配置提取出来的bundle。

是小了一点,但是项目还是太大了,特别是vendor.min.js。查看包发现工程引用的第三方模块中用到很多相同的模块

解决办法:使用别名

resolve: {
symlinks: false,
extensions: ['.js', '.jsx', '.json'],
alias: {
// 别名,防止node_modules多个地方引入同样的包会打多份
'scratch-l10n': path.resolve(__dirname, './node_modules/scratch-l10n'),
'scratch-blocks': path.resolve(__dirname, './node_modules/scratch-blocks'),
'scratch-render': path.resolve(__dirname, './node_modules/scratch-render'),
'scratch-svg-renderer': path.resolve(__dirname, './node_modules/scratch-svg-renderer'),
'scratch-audio': path.resolve(__dirname, './node_modules/scratch-audio'),
'immutable': path.resolve(__dirname, './node_modules/immutable')
}
},

打包后结果

小了3M。到目前为止,如果不更改代码基本已经无法再压缩了。

第二阶段:更改代码,一切与展示作品无关的东西都剥离后打包

  • 修改maxInitialRequests为4
  • 配置了公用vendors,优先提取大模块(默认情况是不用更改的,本人的项目比较特殊,原因看后面的描述)
  • player代码和gui的代码分开,去掉player中不必要的代码引入

这一阶段player的代码进行精简,不和blocksonly / compatibilitytesting / gui公用一套代码。项目后面加上了一些hash.

由于项目中需要对scratch-blocks做更改,将scratch-blocks作为项目的git子模块。

不配置vendors则和默认配置等同,等同于如下代码

vendors配置如下:

为什么要自定义配置vendors?这和配置maxInitialRequests也有很大关系。

按照webpack默认的default和vendors配置会自动提取公用代码生成新bundle,其中有两个参数对这个提取影响比较大:maxAsyncRequests和maxInitialRequests。意思是,webpack会提取各个入口中的相同代码组成一个个被至少两个入口使用的bundle,比如下面

chunks/vendors~blocksonly~compatibilitytesting~gui.302b4bd4e64a213f38f4.js 表示是vendors提取出来给blocksonly | compatibilitytesting | gui 这三个入口公用的

chunks/vendors~blocksonly~compatibilitytesting~gui~player.aa28b51afdced7c4a928.js  表示是vendors提取出来给blocksonly | compatibilitytesting | gui | player 这四个入口公用的

如果不限制,则vendors~*.js这样的组合会很多。一个player.html初始化加载时需要请求很多js。所以maxAsyncRequests和maxInitialRequests限制了这个请求数,让打包后提取公共代码js时保证每一个入口异步请求和初始化请求的js数量控制在设定的值。这样就会出现某些多个入口使用的公用代码不能被单独提取出来的情况。

由于默认的初始化js请求数量限制为3,本人更改为4(当然也可以更大,本人这块不想有跟多js请求,这块根据各自的项目而定)

然后本人想把一写体积比较大的(比如scratch-blocks)块在有maxInitialRequests限制的情况下优先提取出来,其他的就打入各自的包。就直接更改了vendors

没有配置vendors和配置了vendors的对比(后面的就是配置了vendors)

没有配置vendors,子模块scratch-blocks在多处打包,没有被提取出来。修改vendors,去掉了只匹配“node_moddules”;只要三个以上chunks用到的模块都提取到vendors。

配置vendors打包后的结果可以看到,在网页端访问player页面,只需要引入三个js

vendor.min.938f6588ea10bb385ceb.js    7844K

vendors~blocksonly~compatibilitytesting~gui~player.b694ee6564cf5e22ed72.js   2998K

player.cb540c9b28aafd8d9503.js   95K

一共就10M多一点,比起之前要加载26M要好很多了。

这里面有一个点需要注意:

按照webpack默认的default和vendors配置会自动提取公用代码生成新bundle,然后自动被html-webpack-plugin配置的html引用。但是,3.X的html-webpack-plugin如果不指定chunk,且在HtmlWebpackPlugin中显式配置chunk的名称,则不起作用。

比如:

上面的vendors~blocksonly~***.js文件生成了,但是没有被引入到index.html代码中,导致访问index.html缺少这个文件直接展示不出来。

3.x的配置例子如下

一旦指定splitChunks.name的名称,那么所有的入口必然引用这个bundle,无法生成各自入口的个性化bundle。所以建议升级html-webpack-plugin到4

后记:

====================================

2019.12.20 笔记写的时候是19年6月左右。现在"vendor"的配置名称改成了“lib.min”,毕竟vendors是第三方包的意思。html-webpack-plugin 4.x也不用再配置中指定“vendor.min”,只需要配置入口chunks就行,插件会自动查找入口chunk被提取出的公共代码的路径。

优化要点:

1.代码压缩/图片压缩

2.公用代码提取,稳定资源最好提取到单独的包(比如node_modules中的包)

3.非相关代码拆分

4.tree shaking的使用。这块难点比较大,特别是用babel处理的时候。

5. chunkhash和contenthash合理使用

纯属个人经验,有错误请大家多指正!

webpack打包优化实践的更多相关文章

  1. Webpack 打包优化之速度篇

    在前文 Webpack 打包优化之体积篇中,对如何减小 Webpack 打包体积,做了些探讨:当然,那些法子对于打包速度的提升,也是大有裨益.然而,打包速度之于开发体验和及时构建,相当重要:所以有必要 ...

  2. Webpack 打包优化之体积篇

    谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...

  3. [转] Webpack 打包优化之体积篇

    谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...

  4. 记一次webpack打包优化

    未进行打包优化的痛点: 随着项目的不断扩大,引入的第三方库会越来越多,我们每次build的时候会对所有的文件进行打包,耗时必定很长,不利于日常开发. 解决思路: 第三方库我们只是引入到项目里来,一般不 ...

  5. webpack打包优化之外部扩展externals的实际应用

    目录 前言 externals定义 用法 string array object function regex 实际案例 打包时间 打包之后包的大小 浏览器加载 需要注意 参考 前言 使用vue-cl ...

  6. webpack打包优化并开启gzip

    应用场景:项目使用webpack2.x进行打包,打包后静态资源通过nginx转发配置: 问题:webpack打包后的资源文件特别,特别大,没打包之前页面一个页面js有2M左右(其中已经抽离了css)? ...

  7. 基于CommonsChunkPlugin,webpack打包优化

    前段时间一直在基于webpack进行前端资源包的瘦身.在项目中基于路由进行代码分离,http://www.cnblogs.com/legu/p/7251562.html.但是打包的文件还是很大,特别是 ...

  8. webpack 打包优化的四种方法(多进程打包,多进程压缩,资源 CDN,动态 polyfill)

    如今,webpack 毫无疑问是前端构建领域里最耀眼的一颗星,无论你前端走哪条路线,都需要有很强的webpack 知识.webpack 的基本用法这里就不展开讲了.主要探讨一下如何提高 webpack ...

  9. webpack打包优化点

    目录 1. noParse 2. 包含和排除目录 3. IgnorePlugin 4. happypack 5. DllPlugin动态链接库 6. 热更新 7. 开发环境 tree-shaking ...

随机推荐

  1. 前端最佳实践——DOM操作

    1.浏览器渲染原理 在讲DOM操作的最佳性能实践之前,先介绍下浏览器的基本渲染原理. 分为以下四个步骤: 解析HTML(HTML Parser) 构建DOM树(DOM Tree) 渲染树构建(Rend ...

  2. 升鲜宝V2.0_杭州生鲜配送行业,升鲜宝供应链B端订货系统使用说明_升鲜宝生鲜供应链管理系统_15382353715_余东升

    升鲜宝V2.0_杭州生鲜配送行业,升鲜宝供应链B端订货系统使用说明_升鲜宝生鲜供应链管理系统_15382353715             升鲜宝生鲜配送供应链系统经过这些年的发展,形成一套独特的订 ...

  3. Oracle VirtualBox安装CentOS 8

    1.下载CentOS CentOS下载地址: https://wiki.centos.org/Download 这里以CentOS8为例 选择一个比较快的地址,这里以jdcloud mirror为例 ...

  4. 极客必备 Chrome 浏览器插件

    本文微信公众号「AndroidTraveler」首发. 自己平时使用的最多的就是 Chrome 浏览器,因此本文主要分享自己添加的一些扩展程序. 介绍扩展程序的时候也是以我本人的实际使用为主,有些功能 ...

  5. CSS3 更改字体被选中样式

    CSS3  更改字体被选中样式

  6. 表单生成器(Form Builder)之伪造表单数据mongodb篇

    这篇文章终于回到了正轨:为mongodb伪造数据.之前的随机数.随机车牌照.随机时间还有这篇笔记中的获取指定长度的中文字符串,都是为这篇笔记做准备.看一下我们的准备(基础代码) // 1.获取指定范围 ...

  7. 千万级数据迁移工具DataX实践和geom类型扩展

    ## DataX快速入门参考 > 官方https://github.com/alibaba/DataX/blob/master/userGuid.md ## 环境要求 > Linux JD ...

  8. centos7 链路聚合+KVM桥接连网

    一.两个物理网卡做链路聚合(em3,em4) 1)创建team类型的网卡,连接别名为team0,使用的模式为activebackup-主备/loadbalance-负载均衡nmcli con add ...

  9. TYUT程序设计入门第四讲练习题题解--数论入门

    程序设计入门第四讲练习题题解--数论入门 对于新知识点的学习,需要不断地刷题训练,才能有所收获,才能更好地消化知识点. 题组链接: 程序设计入门第四讲练习题--数论 by vjudge 题解: A. ...

  10. 【pat】C++之刷题常用STL容器整理

    1.vector 动态数组,方便的动态扩容,方便的变量初始化(int类型默认初始化为0,bool默认初始化为false),可以用来实现邻接表(结点数太多的图). 头文件 #include<vec ...