使用Webpack4優化Web性能(一)

webpack.png

利用 Webpack 來優化 Web 性能屬於_加載性能優化_的一部分: ☛ Web Performance Optimization with webpack

1、減小前端資源體積

一、webpack 4 開啓production模式

production模式下 webpack 會對代碼進行優化,如減少代碼體積,刪除只在開發環境用到的代碼。

能夠在 webpack 中指定:css

module.exports = {
  mode: 'production' // 或 development
};

或者 package.json 中配置:前端

"scripts": {
    "dev": "webpack-dev-server --mode development --open --hot",
    "build": "webpack --mode production --progress"
}

二、壓縮代碼

使用 bundle-level minifier 和 loader options 壓縮代碼。
  • Bundle-level minification

Bundle-level 的壓縮會在代碼編譯後對整個包進行壓縮。react

在 webpack 4 中,production 模式下會自動執行 bundle-level 的壓縮,底層使用了 the UglifyJS minifier。(若是不想開啓壓縮,能夠採用 development 模式或者設置 optimization.minimize 爲 false)webpack

  • Loader-specific options

經過 loader 層面的選項配置來對代碼進行壓縮,是爲了壓縮 bundle-level minifier 沒法壓縮的內容,好比,經過 css-loader 編譯後的文件,會成爲字符串,就沒法被 minifier 壓縮。所以,要進一步壓縮文件內容,可進行以下配置:git

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          { loader: 'css-loader', options: { minimize: true } },
        ],
      },
    ],
  },
};

三、使用 ES 模塊

當使用 ES 模塊時, webpack 可以進行 tree-shaking。

tree-shaking 是指 bundler 遍歷整個依賴關係樹,檢查使用了哪些依賴關係,並刪除未使用的依賴關係。所以,若是使用ES模塊語法,webpack 能夠消除未使用的代碼。github

★ 注意:在 webpack 中,若是沒有 minifier,tree-shaking 就沒法工做。webpack 只刪除不使用的導出語句,而 minifier 則會刪除未使用的代碼。所以,若是在編譯時不使用 minifier,代碼量並不會減少。(除了使用 wbpack 內置的 minifier,其它的插件如 Babel Minify plugin 也能對代碼進行壓縮)。web

✘ 警告:不要意外地將 ES 模塊編譯成 CommonJS 模塊。若是你使用 Babel 的時候,採用了 babel-preset-env 或者 babel-preset-es2015,請檢查這些預置的設置。默認狀況下,它們會將 ES 的導入和導出轉換爲 CommonJS 的 requiremodule.exports,能夠經過傳遞 { modules: false } 選項來禁用它。json

Introduction to ES Modules
一口(很長的)氣了解 babel
➹ Webpack docs about tree shaking瀏覽器

四、壓縮圖片資源

針對具體的依賴項進行優化( dependency-specific optimization

圖像佔了頁面大小的一半以上。雖然它們不像JavaScript那樣重要(例如,它們不會阻塞呈現),但它們仍然佔用了很大一部分帶寬。在 webpack 中可使用 url-loadersvg-url-loaderimage-webpack-loader 來優化它們。性能優化

url-loader 能夠將小型靜態文件內聯到應用程序中。若是不進行配置,它將把接受一個傳遞的文件,將其放在已編譯的包旁邊,並返回該文件的url。可是,若是指定 limit 選項,它將把小於這個限制的文件編碼爲Base64 數據的 url 並返回這個url,這會將圖像內聯到 JavaScript 代碼中,從而能夠減小一個HTTP請求。

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif)$/,
        loader: 'url-loader',
        options: {
          // Inline files smaller than 10 kB (10240 bytes)
          limit: 10 * 1024,
        },
      },
    ],
  }
};
// index.js
import imageUrl from './image.png';
// → If image.png is smaller than 10 kB, `imageUrl` will include
// the encoded image: 'data:image/png;base64,iVBORw0KGg…'
// → If image.png is larger than 10 kB, the loader will create a new file,
// and `imageUrl` will include its url: `/2fcd56a1920be.png`

★ 注意:須要在增大代碼體積和減小 HTTP 請求數以前進行權衡。

svg-url-loader 的工做原理與 url-loader 相似 — 只是它使用的是URL編碼而不是Base64編碼來編碼文件。這對SVG圖像頗有用 — 由於SVG文件只是純文本,這種編碼更高效。

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        loader: 'svg-url-loader',
        options: {
          // Inline files smaller than 10 kB (10240 bytes)
          limit: 10 * 1024,
          // Remove the quotes from the url
          // (they’re unnecessary in most cases)
          noquotes: true,
        },
      },
    ],
  },
};

★ 注意: svg-url-loader 有一些選項能夠改進Internet Explorer的支持,但會使其餘瀏覽器的內聯更加糟糕。若是須要支持此瀏覽器,請應用 iesafe: true 選項。

image-webpack-loader 可支持JPG、PNG、GIF和SVG圖像的壓縮。

這個加載器不嵌入圖像到應用程序,因此它必須與 url-loadersvg-url-loader 成對工做。爲了不將其複製粘貼到兩個規則中(一個用於JPG/PNG/GIF圖像,另外一個用於SVG圖像),咱們經過 enforce: 'pre' 將這個加載器設爲一個單獨的規則:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/,
        loader: 'image-webpack-loader',
        // This will apply the loader before the other ones
        enforce: 'pre',
      },
    ],
  },
};

五、優化第三方依賴

JavaScript 的大小平均有一半以上來自依賴項,而其中的一部分多是沒必要要的。咱們能夠對這些依賴的庫進行優化➡️ webpack-libs-optimizations

好比:moment.js 刪除未使用的地區、react-router 移除未使用的模塊,生產環境去除 react propTypes 聲明等。

六、對於ES6模塊開啓模塊鏈接

也叫作做用域提高(Scope Hoisting)

早期的時候,爲了隔離 CommonJS/AMD 模塊,webpack 在打包的時候,會把每一個模塊都打包到一個函數中,這樣就會增大每一個模塊的大小和性能開銷。webpack 2 的時候支持了 ES 模塊,而後 webpack 3 的時候使模塊鏈接成爲了可能。

【原理】:它會分析模塊間的依賴關係,儘量將被打散的模塊合併到一個函數中,但不能形成代碼冗餘,因此只有被引用一次的模塊才能被合併。因爲須要分析模塊間的依賴關係,因此源碼必須是採用了ES6模塊化的,不然Webpack會降級處理不採用Scope Hoisting。

開啓模塊鏈接以後,打出的包將會具備更少的模塊,以及更少的模塊開銷。若是在生產模式下使用 webpack 4,則模塊鏈接已經啓用。

// webpack.config.js (for webpack 4)
module.exports = {
  optimization: {
    concatenateModules: true,
  },
};

★ 注意:爲何默認狀況下不啓用此行爲?鏈接模塊很酷,可是它增長了構建時間,並中斷了熱模塊替換。這就是爲何應該只在生產中啓用它。

三十分鐘掌握Webpack性能優化

七、若是以爲有意義的話,使用 externals

具體請參考:webpack-configuration-externals

相關文章
相關標籤/搜索