webpack学习笔记--压缩代码

浏览器从服务器访问网页时获取的 JavaScript、CSS 资源都是文本形式的,文件越大网页加载时间越长。 为了提高网页加速速度和减小网络传输流量,能够对这些资源进行压缩。 压缩的方法除了能够经过 GZIP 算法对文件压缩外,还能够对文本自己进行压缩。

对文本自己进行压缩的做用除了有提高网页加载速度的优点外,还具备混淆源码的做用。 因为压缩后的代码可读性很是差,就算别人下载到了网页的代码,也大大增长了代码分析和改造的难度。javascript

下面来一一介绍如何在 Webpack 中压缩代码。css

压缩 JavaScript

目前最成熟的 JavaScript 代码压缩工具是 UglifyJS , 它会分析 JavaScript 代码语法树,理解代码含义,从而能作到诸如去掉无效代码、去掉日志输出代码、缩短变量名等优化。html

要在 Webpack 中接入 UglifyJS 须要经过插件的形式,目前有两个成熟的插件,分别是:java

  •  UglifyJsPlugin :经过封装 UglifyJS 实现压缩。
  •  ParallelUglifyPlugin :多进程并行处理压缩,4-4使用ParallelUglifyPlugin 中有详细介绍。

因为 ParallelUglifyPlugin 在 4-4使用ParallelUglifyPlugin 中介绍过就再也不复述, 这里重点介绍如何配置 UglifyJS 以达到最优的压缩效果。react

UglifyJS 提供了很是多的选择用于配置在压缩过程当中采用哪些规则,全部的选项说明能够在 其官方文档 上看到。 因为选项很是多,就挑出一些经常使用的拿出来详细讲解其应用方式:webpack

  •  sourceMap :是否为压缩后的代码生成对应的 Source Map,默认为不生成,开启后耗时会大大增长。通常不会把压缩后的代码的 Source Map 发送给网站用户的浏览器,而是用于内部开发人员调试线上代码时使用。
  •  beautify : 是否输出可读性较强的代码,即会保留空格和制表符,默认为是,为了达到更好的压缩效果,能够设置为 false
  •  comments :是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,能够设置为 false
  •  compress.warnings :是否在 UglifyJs 删除没有用到的代码时输出警告信息,默认为输出,能够设置为 false 以关闭这些做用不大的警告。
  •  drop_console :是否剔除代码中全部的  console  语句,默认为不剔除。开启后不只能够提高代码压缩效果,也能够兼容不支持 console 语句 IE 浏览器。
  •  collapse_vars :是否内嵌定义了可是只用到一次的变量,例如把 var x = 5; y = x 转换成 y = 5,默认为不转换。为了达到更好的压缩效果,能够设置为 false
  •  reduce_vars : 是否提取出出现屡次可是没有定义成变量去引用的静态值,例如把  x = 'Hello'; y = 'Hello'  转换成  var a = 'Hello'; x = a; y = b, 默认为不转换。为了达到更好的压缩效果,能够设置为  false 。

也就是说,在不影响代码正确执行的前提下,最优化的代码压缩配置为以下:git

const UglifyJSPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
module.exports = {
  plugins: [
    // 压缩输出的 JS 代码
    new UglifyJSPlugin({
      compress: {
        // 在UglifyJs删除没有用到的代码时不输出警告
        warnings: false,
        // 删除全部的 `console` 语句,能够兼容ie浏览器
        drop_console: true,
        // 内嵌定义了可是只用到一次的变量
        collapse_vars: true,
        // 提取出出现屡次可是没有定义成变量去引用的静态值
        reduce_vars: true,
      },
      output: {
        // 最紧凑的输出
        beautify: false,
        // 删除全部的注释
        comments: false,
      }
    }),
  ],
};

从以上配置中能够看出 Webpack 内置了 UglifyJsPlugin,须要指出的是 UglifyJsPlugin 当前采用的是 UglifyJS2 而不是老的 UglifyJS1, 这两个版本的 UglifyJS 在配置上有所区别,看文档时注意版本。es6

除此以外 Webpack 还提供了一个更简便的方法来接入 UglifyJSPlugin,直接在启动 Webpack 时带上  --optimize-minimize  参数,即  webpack --optimize-minimize , 这样 Webpack 会自动为你注入一个带有默认配置的 UglifyJSPlugin。本实例提供项目完整代码github

压缩 ES6

虽然当前大多数 JavaScript 引擎还不彻底支持 ES6 中的新特性,但在一些特定的运行环境下已经能够直接执行 ES6 代码了,例如最新版的 Chrome、ReactNative 的引擎 JavaScriptCore。web

运行 ES6 的代码相比于转换后的 ES5 代码有以下优势:

  • 同样的逻辑用 ES6 实现的代码量比 ES5 更少。
  • JavaScript 引擎对 ES6 中的语法作了性能优化,例如针对  const  申明的变量有更快的读取速度。

因此在运行环境容许的状况下,咱们要尽量的使用原生的 ES6 代码去运行,而不是转换后的 ES5 代码。

在你用上面所讲的压缩方法去压缩 ES6 代码时,你会发现 UglifyJS 会报错退出,缘由是 UglifyJS 只认识 ES5 语法的代码。 为了压缩 ES6 代码,须要使用专门针对 ES6 代码的 UglifyES

UglifyES 和 UglifyJS 来自同一个项目的不一样分支,它们的配置项基本相同,只是接入 Webpack 时有所区别。 在给 Webpack 接入 UglifyES 时,不能使用内置的 UglifyJsPlugin,而是须要单独安装和使用最新版本的 uglifyjs-webpack-plugin。 安装方法以下:

npm i -D uglifyjs-webpack-plugin@beta

Webpack 相关配置代码以下:

const UglifyESPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
  plugins: [
    new UglifyESPlugin({
      // 多嵌套了一层
      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-preset-env  负责把 ES6 代码转换为 ES5 代码。本实例提供项目完整代码

压缩 CSS

CSS 代码也能够像 JavaScript 那样被压缩,以达到提高加载速度和代码混淆的做用。 目前比较成熟可靠的 CSS 压缩工具是 cssnano,基于 PostCSS。

cssnano 能理解 CSS 代码的含义,而不只仅是删掉空格,例如:

margin: 10px 20px 10px 20px 被压缩成 margin: 10px 20px
color: #ff0000 被压缩成 color:red

还有不少压缩规则能够去其官网查看,一般压缩率能达到 60%。

把 cssnano 接入到 Webpack 中也很是简单,由于 css-loader 已经将其内置了,要开启 cssnano 去压缩代码只须要开启 css-loader 的 minimize 选项。 相关 Webpack 配置以下:

const path = require('path');
const {WebPlugin} = require('web-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
  module: {
    rules: [
      {
        test: /\.css/,// 增长对 CSS 文件的支持
        // 提取出 Chunk 中的 CSS 代码到单独的文件中
        use: ExtractTextPlugin.extract({
          // 经过 minimize 选项压缩 CSS 代码
          use: ['css-loader?minimize']
        }),
      },
    ]
  },
  plugins: [
    // 用 WebPlugin 生成对应的 HTML 文件
    new WebPlugin({
      template: './template.html', // HTML 模版文件所在的文件路径
      filename: 'index.html' // 输出的 HTML 的文件名称
    }),
    new ExtractTextPlugin({
      filename: `[name]_[contenthash:8].css`,// 给输出的 CSS 文件名称加上 Hash 值
    }),
  ],
};
本实例提供项目完整代码
相关文章
相关标签/搜索