什麼是Loader
一個loader
可以看做是一個node
模塊,也可以看做一個loader
就是一個函數 (loader會導出一個函數),衆所周知webpack
只能識別js
文件,loader
在webpack
中擔任的角色就是翻譯工作,它可以讓其它非js
的資源(source)可以在webpack
中通過loader
順利加載。
Loader的方式
- 單一職責,一個loader只做一件事
- 調用方式,loader是從右向左執行,鏈式調用
- 統一原則,loader輸入和輸出都字符串
來看一下案例
module.exports = () => {
return 343
}
上面這種會報錯,我們上面說過laoder
的方式了,統一原則,輸出輸入必須是字符串。而我們上面代碼則輸出是數字,則報錯。
loader導出儘量別使用箭頭函數,loader內部屬性都是靠this來獲取的,如this.callback,this.sync
Webpack手寫Loader
爲什麼要手寫loader
呢,假如有一些loader
插件不滿足我們的需求時,我們會採用手寫loader
來定製化我們功能。
開始
首先新建一個js
文件
module.exports = function(source) {
}
- 第一個參數:是當前要處理的內容
loader內置的方法
函數裏面暴露了一些方法,this.query
獲取loader
傳過來的參數
module.exports = function(source) {
console.log(this.query)
}
當然裏面還可以引入一個庫,來處理參數,該情況用於有時候我們傳給loader
的參數不是一個對象,可能是一個字符串。
module: {
rules: [
{
test: /\.css/,
use: [{
loader: "testLoader",
query: "前端娛樂圈"
}]
}
]
}
const loaderUtils = require('loader-utils')
module.exports = function(source) {
console.log(loaderUtils.getOptions(this))
}
webpack.config.js
module: {
rules: [
{
test: /\.css/,
use: [
"testLoader?name=前端娛樂圈"
]
}
]
}
可以使用上面loaderUtils
內置庫獲取loader
的參數。
webpack.config.js
module: {
rules: [
{
test: /\.css/,
use: [{
loader: "testLoader?name=前端娛樂圈",
options: {
name: "前端娛樂圈"
}
// or
query: {
name: "前端娛樂圈"
}
}]
}
]
}
上面這兩種傳參形式,如果options
存在,行內參數拼接則無效。上面還寫了一種傳參形式,query
也是可以傳參的,那options
和query
有什麼區別的。這倆沒啥區別就是,query
是webpack
老版本之前的(2.5),options
是最新支持的方式
loader異步
loader異步處理,假如說loader裏面需要處理一些邏輯操作,但這個操作是異步的,那麼loader就會編譯失敗,必須使用異步執行方法,來等待結果返回後,loader則纔回執行成功
module.exports = function(source) {
setTimeout(() => {
this.callback(1, source)
}, 3000)
}
官方解釋:this.callback參數
this.callback(
err: Error | null, // 錯誤信息
content: string | Buffer, // 最終生成的源碼
sourceMap?: SourceMap, // 對應的sourcemap
meta?: any // 其他額外的信息
);
還有一種方法是 this.async,async返回值也是一個callback所以這倆個是一樣的
module.exports = function(source) {
const callback = this.async()
setTimeout(() => {
callback(1, source)
}, 3000)
}
Loader起別名
resolveLoader - modules
我們現在手寫的loader都還是寫絕對路徑引入進來,那麼怎麼直接寫loader名呢,有兩種方法,我們來看一下
module.exports = {
resolveLoader: {
modules: ["node_modules", "./loaders"]
},
module: {
rules: [
{
test: /\.js/
use: {
loader: "per-loader"
}
}
]
}
}
我們可以看到上面,我們直接寫的per-loader
,我們是配置瞭解析loader
路徑,會先去node_modules
裏面查找,如果node_modules
裏面沒有則會去loaders
目錄下查找。然後我們下面寫loader: per-loader
,注意:這裏的per-loader
就是當前loader
的文件名
resolveLoader - alias
這種方法直接起別名,把路徑引入過來就ok
module.exports = {
resolveLoader: {
"per-loader": path.resolve(__dirname, "./loaders/per-loader.js")
},
module: {
rules: [
{
test: /\.js/
use: {
loader: "per-loader"
}
}
]
}
}
實現一個sass-loader && style-loader
sass-loader
首先安裝一下node-sass
插件,用於識別scss
語法並編譯爲css
npm i node-sass
新建sassLoader.js
文件,並引入node-sass
插件
const nodeSass = require("node-sass");
const path = require("path")
let result = nodeSass.renderSync({
file: path.resolve(__dirname, "../src/scss/index.scss"),
outputStyle: 'expanded',
});
module.exports = function() {
return result.css.toString()
}
上面採用node-sass
官方配置,如異步解析.scss
文件,上面對象中,file
爲當前要解析的文件地址,outputStyle
爲輸出風格包含:nested
(嵌套)、expanded
(展開)、compact
(緊湊,不換行)、compressed
(壓縮)。
導出result.css.toString
, 這裏爲什麼要toString
,如果不toString
的話返回的是一個Buffer
數據。因爲這裏的返回值提供給下一個loader
使用,爲了下一個loader
(style-loader)更好的使用我們這裏直接處理一下。
更多Api用法請參考node-sass
style-loader
新建styleLoader.js
文件
module.exports = function(source) {
const style = `
let style = document.createElement("style");
style.innerHTML = ${JSON.stringify(source)};
document.head.appendChild(style)
`
return style
}
上面導出的函數第一參數(source
)就是我們sassLoader
的返回值,然後在字符串裏面寫上創建style元素邏輯代碼,並最終返回。注意這裏返回值必須是字符串
上,剛開始我們就說過了,輸入輸出都必須是字符串。
完整配置
index.js
console.log("前端娛樂圈")
import "./scss/index.scss"
webpack.config.js
const path = require("path");
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
resolveLoader: {
alias: {
"sassLoader": path.resolve(__dirname, "./loaders/sassLoader.js"),
"styleLoader": path.resolve(__dirname, "./loaders/styleLoader.js")
}
},
module: {
rules: [
{
test: /\.scss/,
use: ["styleLoader", "sassLoader"]
}
]
}
}
上面配置中我們用到了解析loader
路徑配置(起別名),loader是從右到左,從下到上解析執行。先是把.scss
文件處理成css
語法,然後在傳遞給styleLoader
配置即可。以上一個簡單完整的loader
已實現完畢。如有幫助歡迎點贊+分享哦
歡迎關注我的公衆號:前端娛樂圈
作者:蛙人
鏈接:https://juejin.cn/post/6989461400535973896
來源:稀土掘金
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。