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 值
    }),
  ],
};
本實例提供項目完整代碼
相關文章
相關標籤/搜索