上篇文章手寫簡易打包器的功能是不完善的,比如,只支持JS文件,連CSS都不支持 :)
如何加載CSS?
思路
- 我們的打包器只支持JS
- 我們想要加載CSS
- 如果把CSS變成JS那么就可以加載CSS啦
怎么把CSS變成JS?
在獲取依賴文件內容的時候對于不同文件類型做一些小的處理
// 獲取文件內容,將內容放至 depRelation
let code = readFileSync(filepath).toString()
if(/\.css$/.test(filepath)){ // 如果文件路徑以 .css 結尾
// 把css改造成js
code = `
const str = ${JSON.stringify(code)}
if(document){
// 生成style標簽
const style = document.createElement('style')
style.innerHTML = str
// 將style標簽插入head
document.head.appendChild(style)
}
export default str
`
}
const { code: es5Code } = babel.transform(code, {
presets: ['@babel/preset-env']
})
最后再將bundle.js
引入index.html
,樣式即可生效
把剛才代碼優化成css-loader
新建css-loader.js
// css-loader.js
const transform = code => `
con st str = ${JSON.stringify(code)}
if(document){
// 生成style標簽
const style = document.createElement('style')
style.innerHTML = str
// 將style標簽插入head
document.head.appendChild(style)
}
export default str
`
export default transform
這個函數實際就是將css代碼 變成js代碼
然后在打包文件里面引入它
// bundle.js
if(/\.css$/.test(filepath)){ // 如果文件路徑以 .css 結尾
code = require('./css-loader.js')(code)
}
運行發現報錯了,原來是node不識別export default transform
的寫法,需要改成這
// 避免export關鍵字
module.exports = transform
搞定,這下可以使用自己的css-loader加載css文件了
總結:所以loader到底是什么
- 一個loader可以是一個普通的函數
- loader也可以是一個異步函數
async function transform(code) { const code2 = await doSomting(code) return code2 } module.exports = transform // 舊版本Node.js不支持export關鍵字
另外,為什么使用require
而不是import
,主要是為了方便動態加載,且舊版本Node.js只能支持require