媒介webpack是一个优异的打包东西,其本身为我们做了大批优化,同时也为我们供应了大批的设置项让我们能够自定义,从而有优化空间。在讲webpack优化篇之前,因为楼主主要以vue
媒介
webpack 是一个优异的打包东西,其本身为我们做了大批优化,同时也为我们供应了大批的设置项让我们能够自定义,从而有优化空间。
在讲 webpack 优化篇之前,因为楼主主要以 vue 脚手架最先的,而且是已晋级为 webpack4 以后的优化,假如对 vue脚手架设置不太相识的同砚。能够看我上一篇文章
怎样文雅的晋级到webpack4,或许直接看
webpack3 vue脚手架注解
下面我先讲讲vue脚手架为我们做的一些优化,不喜欢看的请跳过,然后会讲怎样在优化的基础上升华一下,内容从浅到深,然则一切的要领都经由楼主考据,内容较长,请自带板凳瓜子。
vue-cli 脚手架自带优化
babel
Babel 是一个 Javascript 编译器,能将 ES6 代码转为 ES5 代码,让你运用最新的言语特征而不必忧郁兼容性题目,而且能够经由过程插件机制依据需求天真的扩大。这里我不讲babel ,而是讲官方用的插件 transform-runtime,对应的插件全名叫做 babel-plugin-transform-runtime,其作用是削减冗余代码,究竟是怎样削减的呢?
比方在转换 class extent 语法时会在转换后的 ES5 代码里注入 _extent 辅佐函数用于完成继续:
function _extent(target) {
for (var i = 1; i var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
}
这会致使每一个运用了 class extent 语法的文件都被注入反复的_extent 辅佐函数代码,babel-plugin-transform-runtime 的作用在于不把辅佐函数内容注入到文件里,而是注入一条导入语句:
var _extent = require('babel-runtime/helpers/_extent');
如许能减小 Babel 编译出来的代码的文件大小。
注重:babel-plugin-transform-runtime 必需和 babel-runtime 须要配套运用
说来惭愧,楼主试了一下,把这个插件去掉,天生文件的hash和大小并没有变化(汗,别砸,翻材料webpack 规范入门、前端工程化-webpack篇之babel-polyfill与babel-runtime(三)上有写,而且脚手架上有)。厥后发明,楼主的代码中并没有es6。厥后换了一个大项目,做了对照
能够发明,图右侧是去掉插件的。体积显著大了一点。运用此插件能够削减反复代码,减少项目体积。
减少文件搜刮局限
loader
运用 Loader 时能够经由过程 test 、 include 、 exclude 三个设置项来掷中,关于我们的项目大部份都是 js,下面看看官方脚手架 js 的 babel-loader:
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
]
}
}
因为经由过程 npm 装置的第三方的库,都是经由 webpack 打包 es5 化了,所以这里就能够只对 include 包含的文件运用 babel-loader 剖析
注重了。因为 css、less 的引入是要插进去到js中的,所以并不适用于这个(把 node_modules 消除在外)要领。说到这里,多说一句,也是曾很搅扰我的 css 的 loader 剖析递次,use 的 loader 剖析递次跟数组的位置是反着的,以 less 为例,细致来说
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.less$/,
// less 文件的处置惩罚递次为先 less-loader 再 css-loader 再 vue-style-loader
use: [
// style-loader 会把 CSS 代码转换成字符串后,注入到 Javascript 代码中去,
'vue-style-loader',
// css-loader 会找出 CSS 代码中的 @import 和 url() 如许的导入语句,通知 Webpack 依靠这些资本。同时还支撑 CSS Modules、紧缩 CSS 等功用。处置惩罚完后再把结果交给 vue-style-loader 去处置惩罚。
{
loader: 'css-loader',
options: {
sourceMap: config.dev.cssSourceMap
}
},
//经由过程 less-loader 把 less 源码转换为 CSS 代码,再把 CSS 代码交给 css-loader 去处置惩罚。
{
loader: 'less-loader'
}
]
},
]
}
}
关于减少局限增添掷中这个头脑,还能够做许多事变,这里只讲了vue脚手架优化做的事变,更多设置请今后看,看我怎样自定义的
node 选项
webpack 的官方脚手架内里的node选项能够防备node包,另有 setImmediate 的 profill注入到代码中
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
好不好,看疗效。那末细致的疗效怎样呢,楼主一样的代码,做了对照,结果以下:
经由过程对照能够看到,两次打包css的hash值悉数变了,js部份hash发作转变(这个打包没看出js变化,然则另一个项目标部份js的hash变了)。整体打出来的包的体积相差不大。去掉node选项打包时候差异不显著,所以用不必,见仁见智吧。我看create-react-app中也运用了,所以照样发起运用吧,晓得更多的,能够留言区议论。
js、css 紧缩
css 紧缩这个就不多说了,人人都懂,
值得一提的是因为 UglifyJsPlugin 插件晋级到1.0以后有了 parallel选项,开启了多线程紧缩
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true // 开启多线程紧缩
})
这两个插件都有设置项,合理设置能够优化项目。背面会讲。
代码支解
代码支解就是将动态引入的代码支解成一个一个的代码块(chunk),依据需求加载到html上。注重:要运用代码支解功用,在项目中要合营运用组件、路由懒加载的体式格局(能够经由过程import完成)
webpack4 的 mode 为 production 时,默许会对代码举行支解。楼主看了 webpack3 的代码支解体式格局是运用 CommonsChunkPlugin 插件,目标就是支解出几类代码:
- vendor 也就是第三方库打包这里。
- manifest 当编译器最先实行、剖析和映照应用程序时,它会保存一切模块的细致要点。这个数据鸠合称为 “Manifest”
- app 这个是代码中的大众部份
HashedModuleIdsPlugin
嗯 webpack 天生 js 的 hash 是怎样盘算我并不清晰,然则假如不必这个插件的话,一切天生 js 的 hash 是一样的,而且只需有一点点修改,一切文件的 hash 值都邑变化。那形成什么样的结果呢?
比方你只改了 b 页面的 js 里的一行代码,假如不必此插件的话,一切页面的 js 的 hash 悉数会变化,浏览器要从新要求悉数的js。机能糟蹋到怒不可遏。而运用了 HashedModuleIdsPlugin 这个插件,只要你修改的谁人 chunk 的 hash会发作变化,其他稳定,因为浏览器的缓存机制,浏览器只从新要求修改的js。是否是很棒。而且上一小节对代码支解那边的支解体式格局,也是为了把不常常更改的文件零丁打包,hash 能够坚持稳定。
运用要领也很简单
new webpack.HashedModuleIdsPlugin(),
什么?为何就算去掉 HashedModuleIdsPlugin 插件 用脚手架第一次打包项目天生的 js 的 hash 不悉数一样,而且修改以后,也不是悉数发作变化啊。这个也是楼主碰到的题目。楼主不必脚手架搭建的项目,js 的 hash 是一样的,晓得为何涌现初始打包的 js hash 值为何不悉数一样的同砚,迎接批评区议论。
作用域提拔(scope hoisting)
过去 webpack 打包时的一个弃取是将 bundle 中各个模块零丁打包成闭包。这些打包函数使你的 Javascript 在浏览器中处置惩罚的更慢。相比之下,一些东西像 Closure Compiler 和 RollupJS 能够提拔(hoist)或许预编译一切模块到一个闭包中,提拔你的代码在浏览器中的实行速率。
个插件会在 webpack 中完成以上的预编译功用。
new webpack.optimize.ModuleConcatenationPlugin()
这类贯穿连接行动被称为“作用域提拔(scope hoisting)
记着,此插件仅适用于由 webpack 直接处置惩罚的 ES6 模块。在运用转译器(transpiler)时,你须要禁用对模块的处置惩罚(比方 Babel 中的 modules 选项)。
css 优化
因为css加载不会壅塞dom的剖析,所以把css抽取出来。不占用js的大小是一个明智的挑选 OptimizeCSSPlugin 插件做的就是这个,而且代码复用,会减小css体积
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
总结
整体来说 webpack 为我们做的优化有
- babel-plugin-transform-runtime 插件去除反复垫片代码
- module.rules 的 js 剖析,运用 include 进步掷中
- node 选项,防备 node 的自带包(dgram、fs、net、tls、child_process)注入到我们的代码中
- js、css 紧缩,代码支解,大众部份抽离
- 保持打包后稳定chunk的hash值稳定
- 作用域提拔(scope hoisting)
- css 抽离。大众部份抽离
大抵就如许了,有无讲到的也请批评区提出,那末怎样在此基础上做优化呢,这个也许是人人都很体贴的题目。接下来我会在 《关于webpack优化,你须要晓得的事(下篇)》讲到。