loader
是將指定格式的資源文件轉化成必定格式輸出,例如sass-loader
將scss
文件轉化成css
文件, babel-loader
將ES6
轉化成ES5
.一個loader
的結構就是一個函數,最簡單loader
以下:css
module.exports = function(content){ // content就是你要處理文件的內容,如處理App.vue文件,content就是你在App.vue寫的代碼 //... 中間能夠對content處理 return content // 這裏你也能夠用this.callback(null, content)導出 }
loader
的使用,配置webpack
文件html
{ test: /\.css$/, // easy-css-loader就是下面我要寫的loader use: ['style-loader', 'css-loader', 'easy-css-loader'] }
loader
解析順序是:從右向左, 上一個loader
處理完的content
傳遞給下一個loader
, 通常每種loader
功能是單一的vue
easy-css-loader
將實現一些css
代碼的簡寫(雖然sass
等已經有這個功能,可是每次都要寫個.scss
文件在導入,不大方便).webpack
效果圖git
例:
對應代碼github
<div> <div class="easy-css">2</div> </div> <style > .easy-css{ border: 1px solid red; posC; wh(100px, 80px); font(20px, blue, center); comB(http://ww1.sinaimg.cn/large/b44313e1gy1fyz1li77jzj20q411wdop.jpg); } </style>
下面講講font(..)
解析過程web
<!--你代碼寫的樣式--> <style > .easy-css{ font(20px, yellow); } </style> <!-- 會解析成 --> <style > .easy-css{ font-size: 20px; color: yellow; text-align: left; } </style>
上面的代碼, 若是在webpack
配置解析.css
的自定義的loader
, 那麼在loader
裏,前面說的content
就長成這樣了npm
.easy-css{ font(20px, yellow); }
是否是隻要正則匹配font(20px, yellow)
,替換成數組
font-size: 20px; color: yellow; text-align: left;
下面是loader
的代碼緩存
/** * @param {*} fontStr 待解析字符串的`font(..)` * @returns 解析完css字體樣式 */ function fontParse(fontStr) { let start = fontStr.indexOf('(') + 1 // ‘(’後面一個字符位置 let args = fontStr.slice(start, -1) // 就是取font(..)括號裏面字符串,按例子args爲'20px, yellow' let argsList = args.split(',') // 分割成數組['20px', 'yellow'] switch (argsList.length) { // 判斷開發者傳遞參數個數 case 2: argsList.push('left') break case 1: argsList.push('#000', 'left') break } cssName = ['font-size', 'color', 'text-align'].map((item, index) => { return `${item}:${argsList[index]}` // 組合成新的樣式數組 }) let cssStr = cssName.join(';') //造成新css字符串 return cssStr // 回調 } module.exports = function (content) { // content就是在<style>..</style>寫的裏面的內容,或者引入的.css文件 content = content.replace(/font\((.|\n)*?\)/ig, (str) => fontParse(str)) this.cacheable() // 緩存 this.callback(null, content) // 回調 }
上面的正則會匹配到font(..)
, str
就匹配到的font(20px, yellow)
字符串, 最終會被fontParse(str)
值替換.就已經完成font
的解析
其它樣式的解析能夠寫成鏈式
module.exports = function (content) { // content就是在<style>..</style>寫的裏面的內容,或者引入的.css文件 content = content.replace(/font\((.|\n)*?\)/ig, (str) => fontParse(str)) // 解析font()字體樣式 .replace(/wh\((.|\n)*?\)/ig, (str) => whParse(str)) // 解析wh()寬高樣式 .replace(/posC(.|\n)*?;/ig, (str) => posCParse(str)) // 解析posC居中樣式 .replace(/flex(.|\n)*?;/ig, (str) => flexParse(str)) // 解析flex佈局樣式 .replace(/comB(.|\n)*?;/ig, (str) => backParse(str)) // 解析comB(..)背景圖片樣式 .replace(/posL(.|\n)*?;/ig, (str) => posLRParse(str, 'left')) // 解析posL(..)居左樣式 .replace(/posR(.|\n)*?;/ig, (str) => posLRParse(str, 'right')) // 解析posR(..)居右樣式 this.cacheable() // 緩存 this.callback(null, content) // 回調 }
一個loader
大功告成
具體的能夠去看源碼,在github上,以爲能夠的話幫忙star
一下
我發佈npm
包easy-css-loader
使用以下配置
{ module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader', 'easy-css-loader'] // 順序必定要注意 } ] } }