前面三節,我主要給大家分享了有關webpack的一些配置的知識點,如何打包js檔案,而如果我們遇到其他類型的資源如圖檔、css、字型font等等,我們該如何處理呢?今天會介紹預處理器(loader),它賦予了Webpack可處理不同資源類型的能力,極大豐富了其可擴充性。
如果想了解Webpack的基礎配置可以參考以下位址:
Webpack實戰(一):Webpack打包工具安裝及參數配置
Webpack實戰(二):webpack-dev-server的介紹與用法
Webpack實戰(三):作為前端你不得不懂的Webpack資源入口和出口的配置
在一個項目中,我們要面臨着各種各樣的資源,如何讓Webpack很好的處理這些資源呢?這個時候我們需要借助于預處理器(loader),loader的字面意思是裝載器,在Webpack中它的實際功能則更像是預處理器。Webpack本身隻認識JavaScript,對于其他類型的資源必須預先定義一個或多個loader對其進行轉譯,輸出為Webpack能夠接收的形式再繼續進行,是以loader做的實際上是一個預處理的工作。
loader配置
-
loader引入
如果我們要引入css檔案,webpack是沒法處理的,如
// common.css
body {
font-size: 20px;
background: #0fc;
}
//index.js
import './common.css'
執行的結果如上圖,由此可見,Webpack是無法處理css檔案,我們需要給安裝預處理css-loader。安裝步驟如下
npm install --save-dev css-loader
然後我們将loader 引入項目中,配置webpack.config.js配置如下:
const path = require('path')
module.exports = {
context: path.join(__dirname, './src'),
entry: {
index: './index.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'index.js'
},
mode: 'development',
module: {
rules: [
{
test: /\.css$/i,
use: [ 'css-loader'],
},
],
}
}
與loader相關的配置都在module對象中,其中module.rules代表了子產品的處理規則。每條規則内部可以包含很多配置項,這裡我們隻使用了最重要的兩項—test和use。
- test可接收一個正規表達式或者一個元素為正規表達式的數組,隻有正則比對上的子產品才會使用這條規則。 如以/.css$/來比對所有以.css結尾的檔案。
- use可接收一個數組,數組包含該規則所使用的loader,也可以是字元串,對象等。
很多時候,在處理某一類資源時我們都需要使用多個loader。如,對于SCSS類型的資源來說,我們需要sass-loader來處理其文法,并将其編譯為CSS;接着再用css-loader處理CSS的各類加載文法;最後使用style-loader來将樣式字元串包裝成style标簽插入頁面。
下面引入style-loader,安裝指令如下:
npm install --save-dev style-loader
配置代碼如下:
const path = require('path')
module.exports = {
context: path.join(__dirname, './src'),
entry: {
index: './index.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'index.js'
},
mode: 'development',
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
}
}
此時再進行打包,樣式就會生效了,應該會看到頁面中插入了一個style标簽,包含了CSS檔案的樣式,這樣我們就完成了從JS檔案加載CSS檔案的配置。
打包效果如下圖:
運作效果如下圖
把style-loader放在css-loader前面,這是因為在Webpack打包時是按照數組從右邊往左邊的順序将資源交給loader處理的,是以要把最後生效的放在左邊。
loader作為預處理器通常會給開發者提供一些配置項,在引入loader的時候可以通過options将它們傳入
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader',
{
loader: 'css-loader',
options: {
// 有關css-loader的配置
}
}
],
},
],
}
-
其他配置
exclude與include是用來排除或包含指定目錄下的子產品,可接收正規表達式或者字元串(檔案絕對路徑),以及由它們組成的數組
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
exclude: /node_modules/
},
],
}
exclude規則内的使node_modules中的子產品不會執行這條規則。該配置項通常是必加的,否則可能拖慢整體的打包速度。
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
include: /src/
},
],
}
include代表該規則隻對正則比對到的子產品生效。假如我們将include設定為工程的源碼目錄,自然而然就将node_modules等目錄排除掉了。
如果exclude 和include同時存在,則exclude權限比較高
resource與issuer可用于更加精确地确定子產品規則的作用範圍,在Webpack中,我們認為被加載子產品是resource,而加載者是issuer
: {
rules: [
{
use: ['style-loader', 'css-loader'],
resource: {
test: /\.css$/i,
exclude: /node_modules/
},
issuer: {
test: /\.js$/i,
exclude: /node_modules/
}
},
],
}
通過添加resource對象來将外層的配置包起來,區分了resource和issuer中的規則,這樣就一目了然了。
enforce用來指定一個loader的種類,隻接收“pre”或“post”兩種字元串類型的值。事實上,我們也可以不使用enforce而隻要保證loader順序是正确的即可。配置enforce主要的目的是使子產品規則更加清晰,可讀性更強,尤其是在實際工程中,配置檔案可能達到上百行的情況,難以保證各個loader都按照預想的方式工作,使用enforce可以強制指定loader的作用順序。
常用的預處理器
- babel-loader用來處理ES6+并将其編譯為ES5,它使我們能夠在工程中使用最新的語言特性,同時不必特别關注這些特性在不同平台的相容問題。
npm install babel-loader babel-core babel-preset-env
- babel-loader:它是使Babel與Webpack協同工作的子產品。
- babel-core:顧名思義,它是Babel編譯器的核心子產品。
-
babel-preset-env:它是Babel官方推薦的預置器,可根據使用者設定的目标環境自動添加所需的插件和更新檔來編譯ES6+代碼。
配置檔案如下:
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
[
'env', {
modules: false
}
]
]
}
}
}
由于babel檔案很大沒,是以要排除node_modules|bower_components
對于babel-loader本身我們添加了cacheDirectory配置項,它會啟用緩存機制,在重複打包未改變過的子產品時防止二次編譯,同樣也會加快打包的速度
babel-loader支援從.babelrc檔案讀取Babel配置,是以可以将presets和plugins從Webpack配置檔案中提取出來,也能達到相同的效果。
-
ts-loader
ts-loader與babel-loader的性質類似,它是用于連接配接Webpack與Typescript的子產品,安裝指令如下:
npm install ts-loader typescript
webapck.config.js配置如下
rules: [
{
test: /\.ts$/,
use:'ts-loader'
}
]
-
html-loader
html-loader用于将HTML檔案轉化為字元串并進行格式化,這使得我們可以把一個HTML片段通過JS加載進來。
-
handlebars-loader
handlebars-loader用于處理handlebars模闆,在安裝時要額外安裝handlebars。
-
file-loader
file-loader用于打封包件類型的資源,并傳回其publicPath。