webpack4 配置解析和實戰

webpack4特性

webpack4比較熱門的兩大特性,零配置速度快(號稱提速上限98%)javascript

通常狀況下,webpack4相比於低版本,production場景下第三方依賴打包速度 和 development場景下本地服務首次啓動速度 都獲得顯著提高css

零配置
經過mode指定當前場景爲開發模式仍是生產模式,自動設置好當前場景的默認配置,用戶便可立刻使用,不須要多餘的配置html

打包速度快
打包速度之因此能獲得顯著提高,多虧了Optimization這個新增的選項,下文會說到java

配置選項說明

1.入口(entry)node

是應用程序,或者說一個頁面的起點入口,若是傳遞一個數組,那麼數組的每一項都會執行
每一個html頁面都有一個入口起點
單頁面應用(SPA):一個入口
多頁面應用(MPA :多個入口webpack

entry: {
  home: "./home.js",
  about: "./about.js",
  contact: "./contact.js"
}

若是entry的值是一個字符串,那麼打包以後的chunk名即爲默認的main
若是entry的值是一個對象,則每一個key都會是chunk的名字,每一個key對應的值都是入口起點git

2.輸出(output)github

output的值必須爲一個對象,至少包含下面兩個屬性web

filename: webpack打包以後輸出文件的路徑
path: 決定了每一個輸出的bundle的名稱(即打包後的文件名字),這些bundle將寫入到output.path指定的目錄下npm

例如:
單入口

output: {
    path: '/dist',
    filename: 'bundle.js'
}

這個配置將會在根目錄的dist文件夾下輸出打包後的bundle.js,這是單頁面應用的配置

多入口

output: {
    path: '/dist',
    filename: 'js/[name].js'
}

即在dist目錄下的js文件夾中輸出一系列的bundle


一個比較難理解的配置:ouput.publicPath

配置html中引用的靜態資源的目錄,在多數狀況下,此選項的值爲'/'

publicPath並不會對webpack打包文件後存放的目錄有所影響,是對生成的html中應用的靜態資源,好比圖片,css和js文件的引用路徑作對應的補足

對於按需加載或者加載外部資源來講,這個選項的值尤其重要,若是設置錯誤,加載資源的時候會返回404


3.模塊加載器(loader)

loaders能夠說是各類模塊的轉換器,能夠用來預處理文件,解析和打包除javascript以外的任何靜態資源

loader要下載才能配置使用,好比:
npm install --save-dev css-loader
npm install --save-dev ts-loader

而後在webpack的配置文件中,聲明,css後綴的文件使用css-loader解析,ts後綴的文件使用ts-loader解析

module.exports = {
  module: {
    rules: [
      { test: /\.css$/, use: 'css-loader' },
      { test: /\.ts$/, use: 'ts-loader' }
    ]
  }
};

更多loader的配置:webpack loaders

4.插件(plugins)

plugins用於自定義webpack的構建過程, 好比自定義打包以後的html模板,自定義js和樣式文件是否打包等等
plugins的值,是一個個new出來的插件實例

webpack4取消了四個經常使用的用於性能優化的pluginUglifyjsWebpackPlugin,CommonsChunkPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin
轉而提供了一個名爲optimization的配置項,用於替代以上四個插件(並非說以上插件不能使用了,只是webpack4自己有替代的方案,能夠不用插件)

html-webpack-plugin
經過new 該插件的實例,可讓webpack幫咱們編譯出一個html文件
須要注意的是,多頁面的配置下,有多少個頁面,就要new多少個實例,傳入到plugins中,後面有代碼示例。

html-webpack-inline-source-plugin
這個插件用於生產模式下,讓webpack在打包的時候,將js和css直接插入到html中,從而減小請求的消耗
要注意的是,並非全部狀況下都適合用,文件較大時,仍是推薦經過標籤去引入資源(運行時文件通常比較小,下面會經過另外一個插件將runtime的代碼直接插入html中)

更多插件及其配置:webpack plugins

5.模式(mode)

mode是webpack4新增的參數選項,它有三個值,development、production、none,
因爲開發模式和生產模式所須要的webpack的配置稍微有單不一樣(可是大部分是相同的)
因此能夠創建兩個webpack的配置文件,分別用於開發模式和生產模式,除此以外,指明當前處於哪一個模式下,有利於webpack內部作優化
好比,有一些插件是在生產模式下才啓用的。

經過指定mode的值爲developmentproduction中的一個,來表示webpack處於何種模式下,默認值是production

mode爲 development 時,注重提高代碼的構建速度和開發體驗

module.exports = {
  mode: 'development',
  cache: true,
  devtools: "eval",
  plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") })
  ]
};

mode爲 production 時,提供代碼優化,如壓縮、做用域提高等

module.exports = {
  mode: 'production',
  plugins: [
    new UglifyJsPlugin(/* ... */),
    new webpack.DefinePlugin({
        "process.env.NODE_ENV": JSON.stringify("production")
    }),
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
  ]
}

也能夠經過命令行運行下面的命令來指定模式
webpack --mode=production

6.優化(optimization)

這個選項也是wepack4新增的,主要用來自定義一些優化打包的策略

minimizer
在production模式下,該配置會默認爲咱們壓縮混淆代碼,但配置項過於少致使沒法知足咱們對於優化代碼的訴求,下面是一套比較靈活的優化配置

var UglifyJsPlugin = require('uglifyjs-webpack-plugin')
var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
  optimization: {
    minimizer: [
      // 自定義js優化配置,將會覆蓋默認配置
      new UglifyJsPlugin({
        exclude: /\.min\.js$/, // 過濾掉以".min.js"結尾的文件,咱們認爲這個後綴自己就是已經壓縮好的代碼,不必進行二次壓縮
        cache: true,
        parallel: true, // 開啓並行壓縮,充分利用cpu
        sourceMap: false,
        extractComments: false, // 移除註釋
        uglifyOptions: {
          compress: {
            unused: true,
            warnings: false,
            drop_debugger: true
          },
          output: {
            comments: false
          }
        }
      }),
      // 用於優化css文件
      new OptimizeCssAssetsPlugin({
        assetNameRegExp: /\.css$/g,
        cssProcessorOptions: {
          safe: true,
          autoprefixer: { disable: true }, //這裏注意下!!!!!
          mergeLonghand: false,
          discardComments: {
            removeAll: true // 移除註釋
          }
        },
        canPrint: true
      })
    ]
  }
}

UglifyJsPlugin是你們常用的插件,這裏比較亮的地方是能夠過濾自己已經壓縮的js,能夠提高打包速度,而且避免二次混淆壓縮形成的未知bug

OptimizeCssAssetsPlugin用來優化css文件的輸出,優化策略包括:擯棄重複的樣式定義、砍掉樣式規則中多餘的參數、移除不須要的瀏覽器前綴等
這裏注意插件的參數autoprefixer: { disable: true },必定要指定爲true。不然的話該插件會把咱們用autoprefix加好的前綴都移除掉(由於該插件以爲多餘)

runtimeChunk
分離出webpack編譯出來的運行時代碼,也就是咱們以前成爲manifest的代碼塊,方便咱們作文件的之就好緩存
這個參數項(runtimeChunk)有多種類型的值,其中,single即將全部的chunk的運行時代碼打包到一個文件中,multiple即針對每一個chunk的運行時代碼分別打包出一個runtime文件
咱們能夠配合上面說到的 InlineManifestWebpackPlugin插件,將運行時代碼直接插入html文件中,由於這段代碼很是少,這樣作能夠避免一次請求的開銷
InlineManifestWebpackPlugin插件的順序必定要在HtmlWebpackPlugin以後,不然會致使編譯失敗

var HtmlWebpackPlugin = require('html-webpack-plugin')
var InlineManifestWebpackPlugin = require('inline-manifest-webpack-plugin')
module.exports = {
  optimization: {
    runtimeChunk: 'single'
    // 等價於
    // runtimeChunk: {
    //   name: 'runtime'
    // }
  },
  plugins: [
     new HtmlWebpackPlugin({
       template: '../src/index.html',
       filename: 'article.html',
       chunks: ['article', 'vendors', 'runtime']
     }),
     new InlineManifestWebpackPlugin(), //放在htmlWebpackPlugin的後面才能生效
  ]
}

splitChunks
這是比較難理解的一個配置項
webpack4移除了CommonsChunkPlugin插件,取而代之的是splitChunks
比較優雅的分離打包配置以下

splitChunks: {
  cacheGroups: {
    vendors: {
      test: /[\\/]node_modules[\\/]/,
      name: 'vendors',
      minSize: 30000,
      minChunks: 1,
      chunks: 'initial',
      priority: 1 // 該配置項是設置處理的優先級,數值越大越優先處理
    },
    commons: {
      test: /[\\/]src[\\/]common[\\/]/,
      name: 'commons',
      minSize: 30000,
      minChunks: 3,
      chunks: 'initial',
      priority: -1,
      reuseExistingChunk: true // 這個配置容許咱們使用已經存在的代碼塊
    }
  }
}

這段配置,首先是將node_modules中的模塊統一打包成vendors.js
它限制了分離文件的最小體積爲30k(壓縮以前的),由於webpack認爲,小於30k的代碼分離出來,還要額外小號一次請求去加載它,成本過高,這個值是經過大量的時間總結出來的
其次,還分離除了共享模塊,好比src目錄下有幾個全局公用的js文件如utils等,能夠單獨抽出來打包成一個commons.js
因爲這部分文件不常常改變,有利於持久緩存

完:demo地址

相關文章
相關標籤/搜索