谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣;从早期的王者BrowserifyGrunt,到后来赢得宝座的 Gulp, 以及独树一帜的 fis3, 以及下一代打包神器 Rollup ;在 browserify,grunt,gulp,rollup,webpack 可以一窥其中部分对比。在本文要探究的是,当前打包工具绝对霸者 Webpack

Webpack Package optimization

Webpack,当前各大主流框架默认配备的打包方案,对其如何使用,已有较完备中英文文档;并且,各主流框架也有对应 CLI 予以基础配置,故不作为探讨范畴。从产品层来讲,如何使得构建的包体积小、运行快,这有必要不断摸索实践,提炼升级,使之臻于最佳。本文将从以下些许方面,对 Webpack 打包体积方面,做下优化探讨(备注: Webpack实践版本: 3.3.0):

定位 webpack 大的原因

这里推荐使用 webpack-bundle-analyzer —— Webpack 插件和 CLI 实用程序,她可以将内容束展示为方便交互的直观树状图,让你明白你所构建包中真正引入的内容;我们可以借助她,发现它大体有哪些模块组成,找到不合时宜的存在,然后优化它。我们可以在 项目的 package.json 文件中注入如下命令,以方便运行她(npm run analyz),默认会打开 http://127.0.0.1:8888 作为展示。

“analyz”: “NODE_ENV=production npm_config_report=true npm run build”

webpack-bundle-analyzer

当然,同类型的还有 webpack-chart 以及 webpack-analyse,这两个站点也是以可视方式呈现构造的组件,可以让你清楚的看到模块的组成部分;不过稍显麻烦的是,你需要运行以下命令,生成工具分析所需要的 json 文件:

1
2
3
4
webpack --profile --json > stats.json

// 如果,运行指定的 weboack 文件,可用此命令
webpack --config build/webpack.prod.conf.js --profile --json > stats.json

引入 DllPlugin 和 DllReferencePlugin

DllPlugin 和 DllReferencePlugin 提供了以大幅度提高构建时间性能的方式拆分软件包的方法。其中原理是,将特定的第三方NPM包模块提前构建,然后通过页面引入。这不仅能够使得 vendor 文件可以大幅度减小,同时,也极大的提高了构件速度。鉴于篇幅,具体用法可参见:webpack.dll.conf.js

外部引入模块(CDN)

如今前端开发,自然是使用ES6甚至更高版本,撸将起来才更嗨。但由于浏览器兼容问题,仍得使用 babel 转换。而这 babel-polyfill 也得引入以确保兼容;还比如项目开发中常用到的 momentlodash等,都是挺大的存在,如果必须引入的话,即考虑外部引入之,再借助 externals 予以指定, webpack可以处理使之不参与打包,而依旧可以在代码中通过CMD、AMD或者window/global全局的方式访问。

1
2
3
4
5
6
7
8
9
10
// webpack 中予以指定
externals: {
// 'vue': 'Vue',
// 'lodash': '_',
'babel-polyfill': 'window'
} //
<script src="//cdn.bootcss.com/autotrack/2.4.1/autotrack.js"></script>
<script src="//cdn.bootcss.com/babel-polyfill/7.0.0-alpha.15/polyfill.min.js"></script>

需要补充的是 externals 中:key 是 require 的包名,value 是全局的变量。

让每个第三包“引有所值”

确定引入的必要性

前端发展到如今时期,倘若项目采用了 MVVM模式框架,数据双向绑定,那么像 jQuery 这般类库,不能说没有丝毫引入的必要,至少可以说确实没有引入的必要。对此,如果还有些顾虑,完全可以参考下 YOU MIGHT NOT NEED JQUERY;用原生写几行代码就可以解决的事儿,实在不易引入这么个庞然大物,平添烦恼。

避免类库引而不用

倘若这类情况发生,对整个打包体积,不仅大而且亏。项目一旦大了,很难人为保证每个引入的类库,都被有用到,尤其是二次开发。所以工具的利用十分必要,强烈推荐类如 Eslint 这般工具,并且注入对应规则,对声明却未使用的代码,给予强制提醒;这不仅可以有效的规避类似情形发生(也适用于普通变量的检测),而且还能使得团队代码风格,尽可能地保持相似;要知道代码足够遵守规则,也可让压缩工具更有效压缩代码,一举多得,何乐不为?

尽量使用模块化引入

如果说 jQuery 确实没有引入必要,很多人会同意;但对于 lodash 这类依赖的工具,并不是所有人都会去造一发轮子的。然而全包引入 400kb 的体量,可否有让你心肝一颤?幸好的是,lodash 提供了模块化的引入方式;可按需引入,快哉快哉:

1
2
3
4
5
6
7
import { debounce } from 'lodash'
import { throttle } from 'lodash' // 改成如下写法 import debounce from 'lodash/debounce'
import throttle from 'lodash/throttle'

擅懒如你的优秀程序员,是否也发现这样写颇为麻烦?那么恭喜你,这个问题已经被解决;lodash-webpack-plugin 和 babel-plugin-lodash 的存在(组合使用),即是解决这问题的。它可将全路径引用的 lodash, 自动转变为模块化按使用引入(如下例示);并且所需配置也十分简单,就不在此赘述(温馨提示:当涉及些特殊方法时,尚需些留意)。

1
2
3
4
// 引入组件,自动转换
import _ from 'lodash'
_.debounce()
_.throttle()

额外补充的是,即便采用如上写法,还是不够快捷,每个用到的文件,都写一遍 import,实在多有不便。更可取的是,将项目所需的方法,统一引入,按需添加,组建出本地 lodash 类库,然后 export 给框架层(比如 Vue.prototype),以便全局使用;详情可参见:vue-modular-import-lodash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// helper 文件夹下 lodash,统一引入你需要的方法
import _ from 'lodash' export default {
cloneDeep: _.cloneDeep,
debounce: _.debounce,
throttle: _.throttle,
size: _.size,
pick: _.pick,
isEmpty: _.isEmpty
} // 注入到全局
import _ from '@helper/lodash.js'
Vue.prototype.$_ = _ // vue 组件内运用
this.$_.debounce()

尽可能引入更合适的包

作为前端开发的你,想必知道有 momentjs 的存在(Parse, validate, manipulate, and display dates in javascript.);更多的是,你想必知道它很好用,然而它的体态却十分丰满(丰盈),没念及此,是否有重新造轮子的冲动?SpaceTime: A lightweight way to manipulate, traverse, compare, and format dates and times across planet Earth。 具有与 monent 相似 api 的新类库,其体积又相对小很多(当然,据观察其灵活度略逊一筹);date-fns:现代JavaScript日期实用程序库( Modern JavaScript date utility library ),如 lodash 一样,可支持模块化;知道这些或者更多的你,会如何选择?

按需异步加载模块

关于前端开发优化,重要的一条是,尽可能合并请求及资源,如常用的请求数据合并,压缩合并 js,构造雪碧图诸此等等(当然得适当,注意体积,过大不宜);但,同时也当因需制宜,根据需要去异步加载,避免无端就引入早成的浪费。webpack 也是内置对这方面的支持; 假如,你使用的是 Vue,将一个组件(以及其所有依赖)改为异步加载,所需要的只是把:

1
import Foo from './Foo.vue'

改为如下写法:

1
const Foo = () => import('./Foo.vue')

如此分割之时,该组件所依赖的其他组件或其他模块,都会自动被分割进对应的 chunk 里,实现异步加载,当然也支持把组件按组分块,将同组中组件,打包在同个异步 chunk 中。如此能够非常有效的抑制 Javascript 包过大,同时也使得资源的利用更加合理化。

生产环境,压缩混淆并移除console

现代化中等规模以上的开发中,区分开发环境测试环境生产环境,并根据需要予以区别对待,已然成为行业共识;可能的话,还会有预发布环境。对待生产环境,压缩混淆可以很有效的减小包的体积;同时,如果能够移除使用比较频繁的 console,而不是简单的替换为空方法,也是精彩的一笔小优化。如果使用 UglifyJsPlugin 插件来压缩代码,加入如下配置,即可移除掉代码中的 console

1
2
3
4
5
6
7
8
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: true,
pure_funcs: ['console.log']
},
sourceMap: false
})

Webpack3 新功能: Scope Hoisting

截止目前(17-08-06), Webpack 最新版本是 3.4.1;Webpack在 3.0 版本,提供了一个新的功能:Scope Hoisting,又译作“作用域提升”。只需在配置文件中添加一个新的插件,就可以让 Webpack 打包出来的代码文件更小、运行的更快:

1
2
3
4
5
module.exports = {
plugins: [
new webpack.optimize.ModuleConcatenationPlugin()
]
}

据悉这个 Scope Hoisting 与 Tree Shaking,最初都是由 Rollup 实现的。在个人中实践中,这个功能的注入,对打包体积虽有影响,却不甚明显,有兴趣的盆友可以试下;更对关于此功能讯息,可参见 Webpack 3 的新功能:Scope Hoisting

本文自本月(08)四号开始陆陆续续写,原本的内容意图是,涉及 Webpack 打包优化的体积和速度两个方面;岂料,临近写完的时候(06号晚),已记不得多久没关机的 Mac,竟然被重启了下;屋漏多半会偏逢连夜雨,那一向会自动同步保存(30min)的作业部落,竟然没给同步,WTF!整个周末的敲敲打打,皆付之东流,泪崩泪目。无奈之下,只得重新写过,直到夜深,才补齐关于体积优化那部分;毕竟涉及内容较多,干脆,就分成两部分来完成。也在此提醒广大笔友,及时备份数据并确认,这很重要。在此也预告下一篇 《Webpack 打包优化之速度篇》,当然,此文也扔在完善中。

深圳.南山 @17-08-04. Last Modify 17-08-07

原文链接: Webpack 打包优化之体积篇

Webpack 打包优化之体积篇的更多相关文章

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

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

  2. Webpack 打包优化之速度篇

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

  3. Vue发布过程中遇到坑,以及webpack打包优化

    前言 这段时间,本人自己做了一个vue画面部署到自己的服务器上,发现运行速度慢的的惊人,虽然服务器很渣(本人没什么钱,只能租最差的服务器,主要是给自己学习用的),但是这样开发出来的网站简直不能用,所以 ...

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

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

  5. webpack打包优化点

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

  6. 记一次webpack打包优化

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

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

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

  8. webpack打包优化并开启gzip

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

  9. 基于CommonsChunkPlugin,webpack打包优化

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

随机推荐

  1. ASP.NET Core3.x 基础(1)

    ASP.NET Core与2.x相比发生的一些变化: 项目结构 Blazor SignalR gRPC 关于Program类:Main方法,在系统执行时就会找到这个Main方法,实际上是配置了ASP. ...

  2. C#LeetCode刷题之#13-罗马数字转整数(Roman to Integer)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3842 访问. 罗马数字包含以下七种字符: I, V, X, L, ...

  3. asp.netcore3.1 将服务器配置为需要证书

    运行 asp.netcore 3.1应用程序时,弹出证书选择框. 将服务器配置为需要证书(Kestrel),在Program.cs中,按如下所示配置 Kestrel: public static vo ...

  4. Xor 思维题

    Xor 思维题 题目描述 小\(Q\)与小\(T\)正在玩一棵树.这棵树有\(n\)个节点,编号为 \(1\),\(2\) \(3...n\),由\(n-1\)条边连接,每个节点有一个权值\(w_i\ ...

  5. Python基础入门知识点——if 语句简介

    前言 if 语句是最简单的选择结构.如果满足条件就执行设定好的操作,不满足条件就执行其他其他操作. 判断的定义 如果 条件满足,才能做某件事情, 如果 条件不满足,就做另外一件事情,或者什么也不做 判 ...

  6. shell bash配置

    bash主要可以分为两种方式启动(login,no-login) 两种方式所读取的配置文件不同,所以环境不同 login形式启动如下图所示: no-login形式启动: 从 ~/.bashrc开始.

  7. ssh连接:Socket error Event: 32 Error: 10053.

    今天在使用xshell连接刚装的linux系统的时候,发现无法建立连接,会报如下错误: Connecting to 192.168.21x.x:22...Connection established. ...

  8. 第4篇scrum冲刺(5.24)

    一.站立会议 1.照片 2.工作安排 成员 昨天已完成的工作 今天的工作安排 困难 陈芝敏  完成云开发配置,初始化数据库:  线下模块(还剩下获取词的数据库) 倒计时模块的初加载还是有点慢  冯晓凤 ...

  9. Word Count(C语言)

    1.项目地址 https://github.com/namoyuwen/word-count 2.项目相关要求 2.1 项目描述 Word Count    1. 实现一个简单而完整的软件工具(源程序 ...

  10. 阿里云体验实验室 教你《搭建Hadoop环境》

    体验平台简介 面向开发者和中小企业打造的一站式.全云端的开发平台,打开浏览器就可以开发.调试.上线,所测即所得,并结合无服务器的模式,重新定义云原生时代的研发工作方法论.旨在降低开发者上手成本和中小企 ...