今天為大家帶來一篇前端技術文章,其實也是想給那些不僅希望解決問題,也想知道問題出現的原因的”鉆牛角尖“程序猿刨析一下,抹掉你腦袋的種種“疑問”!
遇到這個問題的概率可能很小,當然了能夠出現這個疑問,證明你已經開始對你的技術進行提升,并希望通過更便捷的方式來提升效率。
是怎么遇到這個問題的呢?
前提:
1、基于vue-cli腳手架創建的Vue工程
2、只有一個.vue文件包含/deep/透傳語法
整體來講一下,是因為node-sass這個css編譯器目前官方已經宣布停止更新了,并建議切換到dart-sass編譯器,所以整個前端工程需要升級一下這個編譯器,切換到dart-sass上面。
整體來說,升級切換到dart-sass并不難,因為我們只需要執行一下下面的命令:
npm uninstall node-sass;
npm install sass -D;
然后很開心的就執行了:npm run serve;
結果編譯失敗,并沒有成功運行:
一般解決辦法:
很明顯,在.vue文件當中,我們在進行樣式透傳的時候,采用了/deep/語法,而dart-sass并不支持,但是dart-sass是支持::v-deep語法的。
那么我們第一時間能夠想到的就是全部手動打開文件將所有/deep/替換成::v-deep,來進行解決。
不過這種辦法可以說非常緩慢,要知道我們的項目可能已經累積到成千上百個文件,每一個打開都需要進行替換,是非常耗費時間和精力的。
當然了有些同學或許會采用工具進行文件目錄下對文件整體替換,這也是一種解決辦法。
但是他們最終都會導致之前的所有代碼都需要更改變動,那么有沒有什么辦法在不改動原有代碼的情況下,實現語法的替換呢?甚至說,我們依然可以采用原有的/deep/語法來寫,但是最終編譯的時候自動轉換為::v-deep?
Webpack自定義Loader預處理器解決辦法
.vue文件之所以能夠被webpack處理,是因為他有vue-loader預處理器,可以將.vue文件進行編譯,轉換成js,而且每一個預處理是可以進行級聯調用的,前一個loader輸出的內容可以作為下一個loader的內容傳入進去。
所以我們可以采用自定義loader的方法,來實現上面的進行自動替換,于是我就寫了一個非常簡單的預處理器Loader,通過正則表達式來匹配文件內容,如果包含/deep/我們就對內容進行替換,然后返回替換后的內容。
第一步:新建一個preSassLoader.js處理器
constloaderUtils=require('loader-utils');
module.exports=function(content,map,meta){
if(/\/deep\//g.test(content)){
console.log('找到含有/deep/的文件');
content=content.replace(/\/deep\//,'::v-deep');
}
returncontent;
};
第二步:在vue.config.js文件中,我們增加對.vue文件的自定義loader處理器
chainWebpack:config=>{
config.module
.rule('vue').use('preSassLoader')
.loader('./src/loaders/preSassLoader');
}
第三步:啟動工程項目
執行:npm run serve;
結果是編譯成功,一般來說,到這兒其實就算是解決了上面自動替換的需求,但是我們有沒有發現圖中標出的4個紅框中的內容,這個自定義preSassLoader其實對于同一個.vue文件來說執行了4次,(本項目為測試項目,只有一個.vue文件當中有/deep/語法)
對于講究效率的我來說,這是難以接受的,一個文件只需要替換一次就夠了,不用執行這么多遍,所以我就開始分析為什么走了4遍?
我開始在網上搜索,這個內容可以說少之又少,不過也有人提出了這樣的疑問,不過并沒有人來為他解答,不知道那個提問的人現在心中的疑問消除了沒?
不過我仔細一想也基本就能理解了,很少有人會這樣自定義一個loader來進行處理吧,大部分人都采用第一種解決辦法就完事了。
既然網上找不到,那就只能自己進行分析了,開啟Debug
通過vscode配置npm 調試模式:
通過觀察分析,我們發現在我們自定義loader處理器里面有個resourceQuery字段是不一樣的
那么我們增加一個輸出,將resourceQuery進行打印
從上圖紅框中,我們就不難發現,4次的resourceQuery已經解釋了,其實一個.vue單文件當中,有3大塊,template模板,script,和style,構成了一個頁面所需的元素,而vue-loader就是對這個.vue單文件進行編譯轉換,而多出來的那個處理應該是cache-loader,也就是說對于一個.vue文件來說,會生成四種請求鏈接:
1、test.vue
2、test.vue?vue&type=template&id=fac91d24&scoped=true&
3、test.vue?vue&type=script&lang=js&
4、test.vue?vue&type=style&index=0&id=fac91d24&scoped=true&lang=scss&
所以我們可以通過resourceQuery來進行過濾處理,此處我們用/type=style/來進行過濾
加上過濾條件后,這個真的就執行一次了。
你以為到這兒就完事了?還差得遠呢?。。?br/>
雖然我們的處理邏輯執行了一遍,但是你有沒有發現,其實進入到這個preSassLoader的.vue請求是一個也沒有減少,我們其實只需要一個.vue文件只進入一次就可以了,而不是這一個文件的4次不同請求都被這個預處理器接收到。
這是因為我們在配置自定義preSassLoader的時候,捕獲的是.vue文件而沒有匹配resourceQuery后面的請求串,導致只要是.vue?xxx的請求這個預處理器都能接收到。
所以我們自己新建一個rule規則來進行精確匹配:
在vue.config.js中注釋掉之前的匹配:
chainWebpack:config=>{
//注釋掉
//config.module
//.rule('vue')
//.use('preSassLoader')
//.loader('./src/loaders/preSassLoader');
config.module
.rule('preDeep')
.test(/\.vue$/)
.use('preSassLoader')
.loader('./src/loaders/preSassLoader');
}
就暫時到這兒吧,希望可以解答遇到這個問題時候的你的疑問!
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.