細說webpack 4. webpack的常見配置(上)

大家好!我是蘿蔔,這一章跟大家介紹 webpack 4 常見的配置。

webpack.config.js配置文件

webpack 是可配置的模塊打包工具,可以通過修改 webpack.config.js 的配置文件對 webpack 進行配置,webpack 的配置文件遵循 Nodejs 的 CommonJS 模塊規範,可通過 require() 語法導入其他文件或者使用 Nodejs 內置的模塊,其實 webpack.config.js 是一個 Nodejs 的模塊。

一個簡單的 webpack.config.js 例子

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './entry.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'entry.bundle.js'
  }
};

上面例子中使用CommonJS的 require 引入 Nodejs 內置的 path 模塊,然後通過 module.exports 將 webpack 的配置導出。

Tips: webpack 的配置是一個 Nodejs 模塊,並不是 JSON 對象。

webpack 配置支持多種語言

webpack 不僅僅支持 js 配置,還支持 TypeScript 、CoffeeScript 甚至 JSX 語法的配置,但是不論使用什麼語言,核心配置項是相同的,只不過是語法不同。除了配置文件的語法多樣之外,對於配置的類型也是多樣的,最常見的是作爲一個對象來使用,除了對象,webpack 還支持函數、Promise 和多配置數組。

如何使用 webpack.config.js 配置文件

默認情況下,webpack 會查找執行目錄下的 webpack.config.js 作爲配置,如果需要指定某個配置文件,可以使用命令:

npx webpack --config webpack.config.js

或者在項目目錄下運行

node ./node_modules/webpack/bin/webpack --config webpack.config.js

webpack 的核心概念

雖然 webpack 的功能強大且配置項多,但是隻要理解了以下的幾個核心概念,就能隨心應手的使用它,webpack 有以下幾個核心概念:

  • entry: 項目入口,webpack 執行構建的第一步將從 entry 開始,可抽象成輸入。
  • module: 模塊,在 webpack中一切皆模塊,一個模塊對應一個文件,模塊不侷限於js,也可以是 css、圖片等。webpack 會從配置文件的 entry開始遞歸找出所有依賴的模塊。
  • chunk: 代碼塊,一個 chunk 可以由多個模塊組合而成,用於代碼合併與分割。
  • loader: 模塊轉換器,用於將模塊的原內容按照需求轉換成新內容。
  • plugin: 擴展插件,在 webpack 構建流程中的特定時機注入擴展邏輯,可以完成 loader 完不成的任務。
  • output: 輸出結果,在 webpack 經過一系列處理並得出最終想要的代碼後輸出結果。

webpack 的入口(entry)和輸出(output)

webpack 是一個模塊打包工具,能夠從一個需要處理的 javascript 文件開始,構建一個依賴關係圖(dependency graph),該圖映射到了項目中每個模塊,然後將這個依賴關係圖輸出到一個或者多個 bundle 中。
webpack 是從指定的入口文件(entry)開始,經過加工處理,最終按照 output 輸出固定內容的 bundle。而這個加工處理的過程,就用到了 loader 和 plugin 兩個工具,loader 是源代碼的處理器,plugin 解決的是 loader 處理不了的事情。

entry 入口

webpack 的 entry 支持多種類型,包括字符串、對象、數組。從作用上說,包括單文件入口和多文件入口兩種方式。

單文件入口

module.exports = {
  entry: 'path/index.js'
}

// 使用對象的方式
module.exports = {
  entry: {
    main: 'path/index.js'
  }
}

單文件入口可以快速創建一個只有單一文件入口的情況,但是相對簡單,在擴展配置時靈活性較低。

module.exports = {
  mode: 'development',
  entry: ['./src/index1.js', './src/index2.js']
}

無論是字符串還是字符串數組的 entry ,實際上都是隻有一個入口,但是在打包產出上會有差異:
如果直接是 string 的形式,那麼 webpack 就是直接把該 string 指定的模塊作爲入口模塊。
如果是數組的形式,那麼 webpack 會自動生成另一個入口模塊,並將數組中的每個元素指定的模塊加載進來,並將最後一個模塊的 module.exports 作爲入口模塊的 module.exports 導出。

多文件入口

多文件入口是使用對象語法來通過支持多個 entry ,多文件入口的對象語法相對於單文件入口,具有更高的靈活性,例如多頁應用、頁面模塊化分離優化。

module.exports = {
  entry: {
    home: 'path/home.js',
    search: 'path/search.js',
    list: 'path/list.js'
  }
}

上面的語法將 entry 分成了 3 個獨立的入口文件,這樣會打包出來三個對應的 bundle。

Tips: 對於一個 html 頁面,我推薦只用一個 entry ,通過統一入口,解析出來的依賴關係更方便管理和維護。

output 輸出

webpack 的 output 是指定了 entry 對應文件編譯打包後的輸出 bundle 。output 的常用屬性是:

  • path: 規定了打包後輸出的 bundle 的存放路徑。
  • filename: 這個是 bundle 的名稱。
  • publicPath: 指定了一個在瀏覽器中被引用的 URL 地址。
Tips: 當不指定 output 的時候,默認輸出到 dist/main.js,即 output.path 是
dist,output.filename 是 main。

一個 webpack 的配置,可以包含多個 entry ,但是只能有一個 output 。對於不同的 entry 可以通過 output.filename 佔位符來區分。

module.exports = {
  entry: {
    home: 'path/home.js',
    search: 'path/search.js',
    list: 'path/list.js'
  },
  output: {
    filename: '[name].js',
    path: __dirname + '/dist'
  }
}

其中 [name] 就是佔位符,它對應的是 entry 的 key (home、search、list)。
目前 webpack 支持的佔位符有:

  • [hash] 模塊標識符的 hash
  • [chunkhash] chunk 內容的 hash
  • [name] 模塊名稱
  • [id] 模塊標識符
  • [query] 模塊的 query,例如,文件名 ? 後面的字符串
  • [function] 一個 return 出一個 string 作爲 filename 的函數

[hash] 和 [chunkhash] 的長度可以使用[hash:16] (默認爲 20) 來指定,或者通過指定output.hashDigestLength 在全局配置長度,那麼他們之間的區別是什麼?

  • [hash]:是整個項目的 hash 值,其根據每次編譯內容計算得到,每次編譯之後都會生成新的 hash,即修改任何文件都會導致所有文件的 hash 發生改變;在一個項目中雖然入口不同,但是 hash 是相同的;hash 無法實現前端靜態資源在瀏覽器上長緩存,這時候應該使用 chunkhash;
  • [chunkhash] :根據不同的入口文件(entry)進行依賴文件解析,構建對應的 chunk,生成相應的 hash;只要組成
    entry 的模塊文件沒有變化,則對應的 hash
    也是不變的,所以一般項目優化時,會將公共庫代碼拆分到一起,因爲公共庫代碼變動較少的,使用 chunkhash 可以發揮最長緩存的作用;
  • [contenthash]:使用 chunkhash 存在一個問題,當在一個 JS 文件中引入了 CSS 文件,編譯後它們的 hash
    是相同的。而且,只要 JS 文件內容發生改變,與其關聯的 CSS 文件 hash 也會改變,針對這種情況,可以把 CSS 從 JS 中使用
    mini-css-extract-plugin 或 extract-text-webpack-plugin 抽離出來並使用
    contenthash。

[hash]、[chunkhash] 和 [contenthash] 都支持 [xxx:length] 語法。

Tips: 佔位符是可以組合使用的,例如 [name]-[hash:8]

output.publicPath

我們構建出的靜態資源文件都是通過 <script> 或者 <link> 標籤進行加載的,而且這些靜態資源文件都是需要部署在靜態資源服務器或者 CDN 上,那麼如何將這些靜態資源文件放在不同的域名或者 CDN 上面呢?這時就要用到 output.publicPath 來進行配置:

module.exports = {
  output: {
    filename: '[name]_[chunkhash:8].js',
    publicPath: 'https://cdn.ezample.com/assets/'
  }
}

則輸出:

<script src="https://cdn.ezample.com/assets/a_456456456.js"></script>

output.library 與 output.libraryTarget

我們在實際開發中總是需要去打包一些供團隊其他小夥伴使用的庫,這時就需要用到 output.library 與 output.libraryTarget,output.library 用來指定庫的名稱,output.libraryTarget 用來指定打包出來的規範,比如:commonjs2、amd、umd2等。

小結

這一章我們從 webpack 的配置文件 webpack.config.js 基本語法入手,講解了配置的基本用法以及 mode、context、entry、output基礎概念,希望能給大家帶來一些幫助,如果想了解更多,請持續關注我的文章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章