阅读《深入浅出的webpack》——压缩代码
一、为什么要压缩代码?
浏览器通过服务器访问网页时获取的JavaScript、CSS资源都是文本形式的,文件越大,网页加载的时间越长。对这些资源进行压缩:
1) 可以提升网页加载速度和减少网络传输流量
2) 还有混淆源码的作用。由于压缩后的代码可读性非常差,所以就算别人下载了网页的代码,也很难进行代码的分析和改造。
方式:除了可以通过GZIP算法对文件进行压缩,还可以对文本本身进行压缩。
二、如何在webpack中压缩代码?
压缩代码:压缩JS、压缩ES6、压缩CSS
1.压缩JavaScript :
1)需要通过插件的形式在webpack中接入UglifyJS。
目前有两个成熟的插件:
UglifyJsPlugin: 通过封装UglifyJS实现压缩
ParallelUglifyPlugin: 多进程并进行处理压缩
2)如何配置UglifyJS以达到最优的压缩效果?
常用配置选项:
sourceMap: 是否为压缩后的代码生成对应的Source Map,默认为不生成,开启后耗时会大大增加。一般不会将压缩后的代码的
Source Map 发送给网站用户的浏览器,而是在内部开发人员调试线上代码时使用。
beautify: 是否输出可读性较强的代码,即会保留空格和制表符,默认输出,为了达到更好的压缩效果,可以设置为false.
comments: 是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,可以设置为false。
compress.warnings: 是否在UglifyJS删除没有用到的代码时输出警告信息,默认为输出,可以设置为false以关闭这些作用不大的警告。
drop_console.log: 是否删除代码中的所有console.log语句,默认为不删除。开启后不仅可以提升代码压缩的效果,也可以兼容不支持
console语句的IE浏览器
collapse_vars: 是否内嵌虽然已定义了但是只用到一次的变量,例如var x = 5;y=x;转换成y=5,默认不转换。为了达到更好的压缩效果,可
以设置为false。
reduce_vars: 是否提取出现了多次但是没有定义成变量去引用的静态值,例如将 x = 'hello';y = 'hello'转换成vars a = 'hello'; x = a; y = b,默
认为不转换。为了达到更好的压缩效果,可以设置为false。
上代码,在不影响代码正确执行的前提下,最优化的压缩配置,如下:
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports ={
plugin: [
//压缩输出的Javascript代码
new UglifyJsPlugin({
compress:{
// 在UglifyJS删除没有用到的代码时不输出警告
warnings: false,
// 删除所有`console`语句,可以兼容IE浏览器
drop_console: true,
// 内嵌已定义但是只用到一次的变量
collapse_vars: true,
// 提取出现了多次但是没有定义成变量去引用的静态值
reduce_vars: true,
},
output: {
// 最紧凑的输出
beautify: false,
// 删除所有注释
comments: false,
}
})
]
}
2. 压缩ES6 :
1)运行ES6的代码相对于转换后的ES5代码的有点:
a. 对于一样的逻辑,用ES6实现的代码量比ES5更少
b. JavaScript引擎对于ES6中的语法做了性能优化,例如针对const声明的变量有更快的读取速度。
注:所以在运行环境允许的情况下,我们要尽可能地使用原生的ES6代码去运行,而不是使用转换后的ES5代码。
2)压缩ES6代码,需要使用专门针对ES6的UglifyES
【注:UglifyES与UglifyJS来自一个项目的不同分支,它们的配置项基本相同,只是接入Webpack时有所区别。在为Webpack接入UglifyES时,
不能使用内置的UglifyJsPlugin,而是需要单独安装和使用最新版本的uglifyjs-webpack-plugin。】
安装方法:
npm i -D uglifyjs-webpack-plugin@beta
Webpack相关配置的代码如下:
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports ={
// 压缩ES6
plugins: [
new UglifyJsPlugin({
//多嵌套了一层
uglifyOptions:{
compress:{
// 在UglifyJS删除没有用到的代码时不输出警告
warnings: false,
// 删除所有`console`语句,可以兼容IE浏览器
drop_console: true,
// 内嵌已定义但是只用到一次的变量
collapse_vars: true,
// 提取出现了多次但是没有定义成变量去引用的静态值
reduce_vars: true,
},
output: {
// 最紧凑的输出
beautify: false,
// 删除所有注释
comments: false,
}
}
})
]
}
【注:同时,为了不让babel-loader输出ES5语法的代码,需要去掉 . babelrc 配置文件中的babel-preset-env,但还是要保留其他babel插件如,babel-preset-react,因为正是babel-prese-env负责将ES6代码转换为ES5代码。】
3、 压缩CSS
【目前比较成熟、可靠的CSS压缩工具是cssnano,基于PostCSS。】
将cssnano接入webpack中也非常简单,因为css-loader已经将cssnano内置了,要开启cssnano去压缩代码,
则只需开启css-loader的minimize选项。
webpack相关配置如下:
const path = require('path')
const { WepPlugin } = reuqire('web-webpack-plugin') // 生成对应的HTML文件
const ExtractTextPlugin = require('extract-text-webpack-plugin'); // 提取Chunk中的CSS代码到单独的文件中
const HtmlWebpackPlugin = require("html-webpack-plugin"); // 找到(提取)HTML,并输出HTML
module.exports ={
module: {
rules: [
{
//增加对css文件的支持
test: /\.css/,
// 提取Chunk中的CSS代码到单独的文件中
use:ExtractTextPlugin.extract({
// 通过minimize选项压缩CSS代码
use: ['css-loader?minimize']
}),
}
]
},
plugins: [
// 用WebPlugin生成对应的HTML文件
new HtmlWebpackPlugin({
// HTML模板文件所在的文件路径
template: './template.html',
// 输出的HTML的文件名称
filename: 'index.html'
}),
new ExtractTextPlugin({
// 为输出的CSS文件名称加上Hash值
filename: `[name]_[contenthash:8].css`,
}),
]
}
三、总结:
const path = require('path')
// const { WepPlugin } = reuqire('web-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports ={
// 压缩CSS
module: {
rules: [
{
test: /\.css/,//增加对css文件的支持
// 提取Chunk中的CSS代码到单独的文件中
use:ExtractTextPlugin.extract({
// 通过minimize选项压缩CSS代码
use: ['css-loader?minimize']
}),
}
]
},
plugin: [
// 压缩CSS
new HtmlWebpackPlugin({ // 用WebPlugin生成对应的HTML文件
template: './template.html', // HTML模板文件所在的文件路径
filename: 'index.html' // 输出的HTML的文件名称
}),
new ExtractTextPlugin({
// 为输出的CSS文件名称加上Hash值
filename: `[name]_[contenthash:8].css`,
}),
// 压缩JS
//压缩输出的Javascript代码
new UglifyJsPlugin({
compress:{
// 在UglifyJS删除没有用到的代码时不输出警告
warnings: false,
// 删除所有`console`语句,可以兼容IE浏览器
drop_console: true,
// 内嵌已定义但是只用到一次的变量
collapse_vars: true,
// 提取出现了多次但是没有定义成变量去引用的静态值
reduce_vars: true,
},
output: {
// 最紧凑的输出
beautify: false,
// 删除所有注释
comments: false,
}
}),
// 压缩ES6
new UglifyJsPlugin({
//多嵌套了一层
uglifyOptions:{
compress:{
// 在UglifyJS删除没有用到的代码时不输出警告
warnings: false,
// 删除所有`console`语句,可以兼容IE浏览器
drop_console: true,
// 内嵌已定义但是只用到一次的变量
collapse_vars: true,
// 提取出现了多次但是没有定义成变量去引用的静态值
reduce_vars: true,
},
output: {
// 最紧凑的输出
beautify: false,
// 删除所有注释
comments: false,
}
}
})
]
}