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也可以在項目中進行本地安裝。這是建議的安裝方式,因為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代碼中使用import
或require
語句,不僅可以導入其他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'
]
}
/*...*/
}
插件
插件就像是載入器的增強版。它們可以執行載入器無法執行的操作,是Webpack的主要模組。
看這個示例:
module.exports = {
/*...*/
plugins: [
new HTMLWebpackPlugin()
]
/*...*/
}
HTMLWebpackPlugin
插件的作用是自動創建一個HTML文件,並添加輸出JS捆綁路徑,使JavaScript可以隨時提供服務。
有許多可用的插件。
一個有用的插件是CleanWebpackPlugin
,可以在創建任何輸出之前清除dist/
文件夾,這樣在更改輸出文件名時就不會留下文件了:
module.exports = {
/*...*/
plugins: [
new CleanWebpackPlugin(['dist']),
]
/*...*/
}
Webpack模式
此模式(從webpack 4開始引入)設置webpack工作的環境。它可以設置為development
或production
(默認為production,所以只有在轉到development時才需要設置):
module.exports = {
entry: './index.js',
mode: 'development',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
}
}
開發模式:
- 建立速度很快
- 沒有生產模式優化好
- 不刪除註釋
- 提供更詳細的錯誤消息和建議
- 提供更好的調試體驗
生產模式的構建速度較慢,因為需要生成一個更優化的捆綁包。生成的JavaScript文件大小更小,因為它刪除了許多在生產環境中不需要的東西。
我做了一個僅打印console.log語句的示例應用程序。
以下是生產捆綁包:
以下是開發捆綁包:
運行Webpack
如果全局安裝了Webpack,可以從命令行手動運行,但通常你會在package.json
文件中編寫一個腳本,然後使用npm
或yarn
運行它。
例如,你可以在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-loader
、css-loader
和style-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內嵌源代碼映射