webpack4 的生產環境優化

webpack4 的生產環境優化

webpack4完整配置的能夠參考: https://github.com/ziwei3749/...css

本文主要介紹了 webpack4 生產環境我都作了哪些優化html

文章的結構以下:前端

  • 1.靜態資源路徑。
  • 2.hash 緩存。
  • 3.代碼分割。
  • 4.壓縮混淆代碼。
  • 5.開啓 gzip 壓縮。
  • 6.關閉 devtool。
  • 7.Tree Shaking

1.靜態資源路徑。對靜態資源路徑的處理和驗證

靜態資源包括: js css image,node

靜態資源的路徑的組成: 前綴 + 本身設置的路徑webpack

前綴 :靜態資源的路徑配置的前綴經過 output.publicPath 設置git

關於publicPath的解釋 https://juejin.im/post/5ae9ae...github

本身設置的路徑web

js 的路徑配置

js 的路徑配置在 output.filenameexpress

output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'static/js/[name].[contenthash:8].js'
}
css 路徑配置

css 的路徑配置在分離 css 的插件裏。例如以前的 extract-text-webpack-plugin 或者 mini-css-extract-pluginnpm

plugins: [
    new MiniCssExtractPlugin({
        filename: "static/css/[name].[contenthash:8].css"
    })
];
image 路徑配置

img 的路徑配置在 url-loader 裏配置

modules: {
    rules: [
        {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            use: [
                {
                    loader: "url-loader",
                    options: {
                        limit: 10000,
                        name: "static/images/[name].[hash:7].[ext]"
                    }
                }
            ]
        }
    ];
}

ps: 有的前端同窗,可能像我同樣不太清楚如何驗證打包壓縮後的的文件內路徑配置的是否正確

推薦一個簡單的方法。下載 express 項目腳手架生成一個 node 項目,將打包後的 dist 扔到 public,啓動 node 服務器

npm install express-generator -D

固然也能夠直接去打開 dist 文件夾裏的路徑,去確實路徑是否正確。

2.hash 緩存。

將業務代碼、第三方類庫、runtime 代碼、css 單獨打包,給他們不一樣 hash,來最大化利用緩存

webpack3 中分離業務代碼、第三方類庫須要用 CommonChunksPlugin。
webpack4 的新增 optimization,能夠方便的分離代碼,並且 hash 的穩定性的問題也有改進。

單獨打包業務代碼、第三方類庫、runtime

optimization: {
        splitChunks: {      // 打包 node_modules裏的代碼
            chunks: 'all'
        },
        runtimeChunk: true,  // 打包 runtime 代碼
    }

單獨打包 css 代碼

webpack4 推薦 mini-css-extract-plugin

注意: 以前的 extract-text-webpack-plugin 須要 beta 版本才支持,並且 contenthash 沒法使用。

分配不一樣的 hash

關於 hash 穩定性的坑

注意區分

  • [hash] : 整個項目有變更時,hash 變化。
  • [chunkhash] : chunk 有變更,chunkhash 變化
  • [contenthash] : 目前文檔沒有明肯定義和說明,可是和文件內容的變化相關

在分離 js 和 css 時,都用設置 contenthash.

output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'static/js/[name].[contenthash:8].js',
    publicPath: '/'
  },
new MiniCssExtractPlugin({
      filename: 'static/css/[name].[contenthash:8].css'
    }),
配置js的文件名時,以前webpack3都是用chunkhash也沒問題,可是實踐後發現webpack4中用chunkhash,會致使,修改css時引起js的chunkhash變化,從而緩存失效。

經測試這樣的設置,的確能夠分離打包,而且各自的 hash 值互相不會干擾,若是有問題的話,能夠共同討論

3.代碼分割

代碼分割或者說懶加載,是 webpack 從誕生就一直標榜的功能吧。

它的做用就是把 js 分割成幾份,在用戶須要加載時才加載,這樣不用一次性加載全部 js。

那麼在 webpack 裏實現代碼分割並非用配置的方式,而是經過咱們寫代碼的方式來告訴 webpack 哪些代碼要分割

webpack 裏有 2 種 webpack 分割方法

  • webpack 內置方法 : require.ensure() 和 require.include()
  • es2015 定義的 動態 import,import 返回 promise

require.ensure 使用 demo

// require.ensure()的 4 個參數 : []依賴 、 callback 、 errorCallback 、 chunkName
require.ensure(
    ["./subPageA"],
    () => {
        var subPageA = require("./subPageA");
    },
    "subPageA"
);

// require.include('./moduleA.js')能夠提取異步模塊中的公共部分到父chunk

import 使用 demo

import("./subPageA").then(subPageA => {
    console.log(subPageA);
});

// 區別
//  import('./subPageA')會直接執行這個文件,
//  而require.ensure()不會直接執行,是在裏面的回調函數裏才執行的引入操做。
關於import的使用注意
@babel升級後,使用import的語法,須要下載插件 @babel/plugin-syntax-dynamic-import

如下的地址連接
https://babeljs.io/docs/en/next/babel-plugin-syntax-dynamic-import.html

4.壓縮混淆代碼

據說webpack4只須要設置mode:produciton,就自動打包混淆js代碼啦!

很好,如今咱們只須要壓縮css了能夠了呢,因而下載插件optimize-css-assets-webpack-plugin

const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
optimization: {
    splitChunks: {
      chunks: 'all'
    },
    runtimeChunk: true,
    minimizer: [
      new OptimizeCssAssetsPlugin({})
    ]
  },
new OptimizeCssAssetsPlugin({
      assetNameRegExp: /\.optimize\.css$/g,
      cssProcessor: require('cssnano'),
      cssProcessorOptions: { safe: true, discardComments: { removeAll: true } },
      canPrint: true
    }),

再看一眼咱們的代碼,坑爹的發現js的壓縮竟然失效了。

爲何呢?我在問答社區看到相似的問題,而且在官方文檔找到了解釋。

大體意思就是。默認optimization.minimize是true,因此js能夠自動幫你壓縮

可是自定義minimizer後,webpack默認配置會取消掉。

文檔還很皮的告訴你,若是你用了css壓縮,記得本身用uglifyjs壓縮js呀。。。

總之,仍是要本身用uglifyjs配置後壓縮js

minimizer: [
      new OptimizeCssAssetsPlugin({}), // 壓縮 css,使用minimizer會自動取消webpack的默認配置,因此記得用UglifyJsPlugin
      new UglifyJsPlugin({
        // 壓縮 js
        uglifyOptions: {
          ecma: 6,
          cache: true,
          parallel: true
        }
      })
    ]

5.開啓 gzip 壓縮。

開啓gzip壓縮,那麼壓縮的好處是什麼?

能夠減少文件體積,傳輸速度更快。

  • 服務端發送 response 時能夠配置 Content-Encoding:gzip,用戶說明數據的壓縮方式
  • 瀏覽器接受時,就能夠根據相應個格式去解碼。客戶端請求時,能夠用 Accept-Encoding:gzip,用戶說明接受哪些壓縮方法

因此 gzip 格式在 http 中傳輸文件的話,速度更快。那麼誰來壓縮文件?

不是服務端,就是客戶端咯。

  • 服務端好比 ngix 或者 node 去作壓縮,
  • 也能夠 webpack 打包上線時,經過插件去作壓縮。

服務端響應時壓縮,確定不如應用構建時壓縮更合適。由於壓縮也是要有時間開銷的

const CompressionWebpackPlugin = require('compression-webpack-plugin');

webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp('\\.(js|css)$'),
      threshold: 10240,
      minRatio: 0.8
    })
)

壓縮以後,文件體積減小的確顯著。

6.關閉devtool

devtool我沒有作很深刻的研究。

個人理解,開發環境必需要配置,不然確定沒法調試。

而生產環境能夠這一項,由於咱們不須要在生產環境調試代碼。若是理解有誤,歡迎指正哈~

7.Tree shaking

tree shaking 的原理

  • ES6 的模塊是靜態分析的。因此在編譯時能夠判斷哪些代碼沒有 exports
  • 分析程序流,判斷哪些變量沒有被使用、從而刪除代碼

webpack4的新增了sideEffects來指定「有反作用的文件」,

可是我在實際使用時,遇到一些坑,好比這樣配置後,我意思是指定.css文件不要被「搖」掉。

但這個配置依舊致使了css文件打包後被當作冗餘代碼被刪除。

"sideEffects": [
    "*.css"
  ],

關於tree shaking就貼一篇文章。關於tree shaking研究清楚後再更新吧

https://zhuanlan.zhihu.com/p/...

以上就是整個配置的說明啦,目前tree shaking目前尚未搞定,其餘功能我本身測試是沒有問題的。

貼一份,webpack4完整的配置文件的地址。

若是以爲有幫助但願star一下,若是遇到問題,也歡迎指教!

相關文章
相關標籤/搜索