Webpack是一個在過去幾年引起了很多關注的工具,現在幾乎在每個項目中都被使用。了解一下它吧。

什麼是Webpack?

Webpack是一個工具,可以讓你編譯JavaScript模塊,也稱為模塊打包工具

它可以將大量的文件生成一個(或多個)運行應用的文件。

它可以執行多種操作:

  • 幫助你將資源打包。
  • 監聽變化並重新執行任務。
  • 可以運行Babel將代碼編譯為ES5,讓你在不擔心瀏覽器支持的情況下使用最新的JavaScript特性。
  • 可以將CoffeeScript轉換為JavaScript。
  • 可以將內聯圖像轉換為數據URL。
  • 允許你使用require()導入CSS文件。
  • 可以運行開發Web服務器。
  • 可以處理熱模塊替換。
  • 可以將輸出文件分成多個文件,以避免首次頁面載入時需要加載大型JavaScript文件。
  • 可以執行樹狀抖動

Webpack不僅僅用於前端,它在後端Node.js開發中也非常有用。

Webpack的前身,以及仍然廣泛使用的工具,包括:

  • Grunt
  • Broccoli
  • Gulp

這些工具與Webpack的功能有很多相似之處,但主要區別在於這些被稱為任務運行器,而Webpack則是作為模塊打包工具誕生的。

它是一個更加專注的工具:你只需要指定應用程序的入口點(甚至可以是帶有腳本標籤的HTML文件),Webpack就會分析文件並將運行應用所需的所有內容打包到一個單獨的JavaScript輸出文件(或多個文件如果使用了程式碼分割)中。

安裝Webpack

Webpack可以全局安裝,也可以在每個項目中本地安裝。

全局安裝

以下是如何使用Yarn全局安裝:

yarn global add webpack webpack-cli

使用npm全局安裝:

npm i -g webpack webpack-cli

一旦安裝完成,你就可以運行以下命令:

webpack-cli

運行webpack-cli

本地安裝

Webpack也可以在項目中進行本地安裝。這是建議的安裝方式,因為Webpack可以按項目進行更新,且對於小型項目使用最新功能的抵抗力較小,而不需要更新使用Webpack的所有項目。

使用Yarn

yarn add webpack webpack-cli -D

使用npm

npm i webpack webpack-cli --save-dev

安裝完成後,將以下代碼添加到你的package.json文件中:

{
 //...
 "scripts": {
 "build": "webpack"
 }
}

添加完畢後,你可以在項目根目錄下運行以下命令運行Webpack:

yarn build

Webpack配置

默認情況下,Webpack(從版本4開始)不需要任何配置,只需遵循以下約定即可:

  • 應用程序的入口點./src/index.js
  • 輸出放置在./dist/main.js中。
  • Webpack工作在生產模式下

當然,你可以根據需要自定義Webpack的每一個細節。Webpack的配置存儲在專案根目錄中的webpack.config.js文件中。

入口點

默認情況下,入口點是./src/index.js 以下是使用./index.js文件作為起始點的簡單示例:

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

輸出

默認情況下,輸出文件生成在./dist/main.js中。以下示例將輸出捆綁到app.js中:

module.exports = {
 /*...*/
 output: {
 path: path.resolve(__dirname, 'dist'),
 filename: 'app.js'
 }
 /*...*/
}

載入器

使用Webpack,您可以在JavaScript代碼中使用importrequire語句,不僅可以導入其他JavaScript文件,還可以導入任何類型的文件,例如CSS。

Webpack旨在處理所有依賴項,不僅僅是JavaScript,載入器是實現此目的的一種方式。

例如,在您的代碼中您可以這樣使用:

import 'style.css'

使用以下載入器配置:

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

這個正則表達式目標是任何CSS文件。

載入器可以有選項:

module.exports = {
 /*...*/
 module: {
 rules: [
 {
 test: /\.css$/,
 use: [
 {
 loader: 'css-loader',
 options: {
 modules: true
 }
 }
 ]
 }
 ]
 }
 /*...*/
}

你可以為每個規則要求多個載入器:

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

在這個示例中,css-loader解釋了CSS中的import 'style.css'指示。然後,style-loader負責使用<style>標籤將CSS注入到DOM中。

順序很重要,並且是反向的(最後一個先執行)。

有什麼樣的載入器?有很多!你可以在這裡找到完整列表

常用的載入器之一是Babel,用於將現代JavaScript編譯為ES5代碼:

module.exports = {
 /*...*/
 module: {
 rules: [
 {
 test: /\.js$/,
 exclude: /(node_modules|bower_components)/,
 use: {
 loader: 'babel-loader',
 options: {
 presets: ['@babel/preset-env']
 }
 }
 }
 ]
 }
 /*...*/
}

這個示例使Babel預處理我們所有的React/JSX文件:

module.exports = {
 /*...*/
 module: {
 rules: [
 {
 test: /\.(js|jsx)$/,
 exclude: /node_modules/,
 use: 'babel-loader'
 }
 ]
 },
 resolve: {
 extensions: [
 '.js',
 '.jsx'
 ]
 }
 /*...*/
}

在這裡查看babel-loader的選項

插件

插件就像是載入器的增強版。它們可以執行載入器無法執行的操作,是Webpack的主要模組。

看這個示例:

module.exports = {
 /*...*/
 plugins: [
 new HTMLWebpackPlugin()
 ]
 /*...*/
}

HTMLWebpackPlugin插件的作用是自動創建一個HTML文件,並添加輸出JS捆綁路徑,使JavaScript可以隨時提供服務。

許多可用的插件

一個有用的插件是CleanWebpackPlugin,可以在創建任何輸出之前清除dist/文件夾,這樣在更改輸出文件名時就不會留下文件了:

module.exports = {
 /*...*/
 plugins: [
 new CleanWebpackPlugin(['dist']),
 ]
 /*...*/
}

Webpack模式

此模式(從webpack 4開始引入)設置webpack工作的環境。它可以設置為developmentproduction(默認為production,所以只有在轉到development時才需要設置):

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

開發模式:

  • 建立速度很快
  • 沒有生產模式優化好
  • 不刪除註釋
  • 提供更詳細的錯誤消息和建議
  • 提供更好的調試體驗

生產模式的構建速度較慢,因為需要生成一個更優化的捆綁包。生成的JavaScript文件大小更小,因為它刪除了許多在生產環境中不需要的東西。

我做了一個僅打印console.log語句的示例應用程序。

以下是生產捆綁包:

Production bundle

以下是開發捆綁包:

Development bundle

運行Webpack

如果全局安裝了Webpack,可以從命令行手動運行,但通常你會在package.json文件中編寫一個腳本,然後使用npmyarn運行它。

例如,你可以在package.json中定義以下腳本:

"scripts": {
 "build": "webpack"
}

這樣你就可以運行webpack命令,如下所示:

npm run build

或者:

yarn run build

或者:

yarn build

監聽變化

當您的應用程序發生變化時,Webpack可以自動重新構建捆綁包,並繼續監聽下一次變化。

只需添加以下腳本:

"scripts": {
 "watch": "webpack --watch"
}

然後運行:

npm run watch

或者:

yarn run watch

或者:

yarn watch

watch模式的一個很好的功能是,只有在構建沒有錯誤的情況下,捆綁包才會更改。如果出現錯誤,watch將繼續監聽變化並嘗試重新構建捆綁包,但當前工作的捆綁包不受這些有問題的構建的影響。

處理圖片

Webpack允許我們以一種方便的方式使用圖片,使用file-loader載入器。

以下是簡單的配置:

module.exports = {
 /*...*/
 module: {
 rules: [
 {
 test: /\.(png|svg|jpg|gif)$/,
 use: [
 'file-loader'
 ]
 }
 ]
 }
 /*...*/
}

這樣您就可以在JavaScript中導入圖片:

import Icon from './icon.png'

const img = new Image()
img.src = Icon
element.appendChild(img)

img是一個HTMLImageElement。查看Image docs

file-loader還可以處理其他類型的資源,例如字體、CSV文件、xml等等。

另一個處理圖片的好工具是url-loader載入器。

以下示例將小於8KB的任何PNG文件作為數據URL加載。

module.exports = {
 /*...*/
 module: {
 rules: [
 {
 test: /\.png$/,
 use: [
 {
 loader: 'url-loader',
 options: {
 limit: 8192
 }
 }
 ]
 }
 ]
 }
 /*...*/
}

處理SASS代碼並轉換為CSS

使用sass-loadercss-loaderstyle-loader

module.exports = {
 /*...*/
 module: {
 rules: [
 {
 test: /\.scss$/,
 use: [
 'style-loader',
 'css-loader',
 'sass-loader'
 ]
 }
 ]
 }
 /*...*/
}

生成源代碼映射

由於Webpack打包了代碼,所以必須生成源代碼映射來引用引發錯誤的原始文件。

您可以使用配置的devtool屬性告訴Webpack生成源代碼映射:

module.exports = {
 /*...*/
 devtool: 'inline-source-map',
 /*...*/
}

devtool許多可能的值,最常用的可能是:

  • none:不添加源代碼映射
  • source-map:適用於生產環境,提供單獨的源代碼映射,可以對其進行最小化,並在捆綁包中添加一個引用,以便開發工具知道源代碼映射可用。當然,你應該配置服務器以避免傳送這個,並且只在調試目的時使用它
  • inline-source-map:適用於開發,作為數據URL內嵌源代碼映射