1、loader處理樣式做了什麼
- 把css當作模塊處理: es6 和commonjs 只是把
js當作模塊
,但我們希望css 可以用模塊化來細分
,以及一些別的語言,eg:ts等,這些代碼可以交給webpack來進行處理,打包。 - 把scss等轉爲css:還有一些css的樣式如scss,是
不能直接運行的
,要用loader進行轉換
2、手寫一個style-loader
- 樣式也是要打包的,所以我們把
樣式寫在源代碼
src文件夾下的assets文件夾–靜態資源裏:src/assets/...
- 打包的時候根據入口文件
./src/index.js
來打包的,打包時要把樣式生成到最終文件,所以css 也要被當作依賴引入:require('./assets/index.css')
,但理論上 es6 和commonjs 都不允許我們這樣做,但是require('./assets/index.css')
這句話不是交給 es6 和commonjs來運行的,而require(’./assets/index.css’)是給webpack看的,webpack 看到require() 就會把require()後面的路徑當作依賴
,而不會理會文件的內容,–> 然後讀取裏面的內容,–>然後根據配置裏的loader 進行處理,–>根據抽象語法樹記錄依賴
- css 讀取出來,
必須進行loader進行處理
,不然沒法進行抽象語法樹分析
,就找不到依賴 - 然後我們需要寫一個loader 來識別
.css後綴的文件
,當遇到.css後綴的依賴文件,就交給loader,loader返回一個可以識別的js代碼,讓其可以進行抽象語法樹分析,就可以了
// ./loaders/style-loader.jsloaders
// loaders和src同級
module.exports = function(sourceCode){
//注意:這裏的代碼,是在laoder處理的過程中運行,並不會出現在最後返回的代碼字符串裏,所以也不會參與最終運行,最終運行的代碼要return
//下面的\` 是轉義,將sourceCode放到字符串裏
return `var style = document.createElement('style');
style.innerHTML = \`${sourceCode}\`;
document.head.appendChild(style);`;
}
loader就是一個函數,用來處理源代碼字符串,然後返回處理後的代碼字符串
例如:sourceCode如下:
/* ./assets/index.css 中的內容*/ body{ background: #333; color: #fff; }
經loader轉換後把css文件內容 變成了如下一段js代碼
var style = document.createElement('style'); style.innerHTML =`body{ background: #333; color: #fff; }`; document.head.appendChild(style);
當require()的時候,就直接運行了上面的js代碼
- 有了loader後,需要在webpack.config.js中配置
模塊解析規則
module.exports = {
mode:'development',
devtool:'source-map',
module:{
rules:[{
test:/\.css$/,
use:['./loaders/style-loader'] //自己寫的loader用相對路徑
}]
}
}
這樣配置後就不會報錯了
3、得到css的源碼字符串
var content = require('./assets/index.css');
console.log(content); //得到css文件的源碼字符串
上面用require()得到模塊化的內容,只需要直接導出就可以了
// ./loaders/style-loader.jsloaders
module.exports = function(sourceCode){
return `
var style = document.createElement('style');
style.innerHTML = \`${sourceCode}\`;
document.head.appendChild(style);
module.exports = \`${sourceCode}\`;
`;
}
過程是:webpack通過require()找到依賴的模塊
–》 讀取css文件的內容 --》 然後根據webpack.config.js中配置的規則 進行loader解析 --》 loader解析 返回一段js代碼 --》 require()這段代碼,js代碼運行 --》導出源碼,賦值給content
這樣就可以打印出源碼了
總結:loader就是把一種代碼格式字符串,返回另一種代碼格式字符串