一個loader
能夠看作是一個node
模塊,也能夠看作一個loader
就是一個函數 (loader會導出一個函數),衆所周知webpack
只能識別js
文件,loader
在webpack
中擔任的角色就是翻譯工做,它可讓其它非js
的資源(source)能夠在webpack
中經過loader
順利加載。javascript
Loader的方式css
來看一下案例前端
module.exports = () => {
return 343
}
複製代碼
上面這種會報錯,咱們上面說過laoder
的方式了,統一原則,輸出輸入必須是字符串。而咱們上面代碼則輸出是數字,則報錯。java
loader導出儘可能別使用箭頭函數,loader內部屬性都是靠this來獲取的,如this.callback,this.syncnode
爲何要手寫loader
呢,假若有一些loader
插件不知足咱們的需求時,咱們會採用手寫loader
來定製化咱們功能。webpack
首先新建一個js
文件git
module.exports = function(source) {
}
複製代碼
函數裏面暴露了一些方法,this.query
獲取loader
傳過來的參數github
module.exports = function(source) {
console.log(this.query)
}
複製代碼
固然裏面還能夠引入一個庫,來處理參數,該狀況用於有時候咱們傳給loader
的參數不是一個對象,多是一個字符串。web
module: {
rules: [
{
test: /\.css/,
use: [{
loader: "testLoader",
query: "前端娛樂圈"
}]
}
]
}
複製代碼
const loaderUtils = require('loader-utils')
module.exports = function(source) {
console.log(loaderUtils.getOptions(this))
}
複製代碼
webpack.config.jsnpm
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則纔回執行成功
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都仍是寫絕對路徑引入進來,那麼怎麼直接寫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
的文件名
這種方法直接起別名,把路徑引入過來就ok
module.exports = {
resolveLoader: {
"per-loader": path.resolve(__dirname, "./loaders/per-loader.js")
},
module: {
rules: [
{
test: /\.js/
use: {
loader: "per-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
新建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
已實現完畢。若有幫助歡迎點贊+分享哦
歡迎關注個人公衆號:前端娛樂圈
謝謝你讀完本篇文章,但願對你能有所幫助,若有問題歡迎各位指正。
我是蛙人(✿◡‿◡),若是以爲寫得能夠的話,請點個贊吧❤。
感興趣的小夥伴能夠加入 [ 前端娛樂圈交流羣 ] 歡迎你們一塊兒來交流討論
寫做不易,「點贊」+「在看」+「轉發」 謝謝支持❤