上篇文章我们实现了一个简易版的webpack,可以打包我们的js代码,但是还不能处理我们的 css、less、scss、图片等,这些都是需要loader和plugin来处理,所以,为了打包器更强大,需要增加loader
和plugin
的支持,接着我们就手写实现一个简单的loader
定义一个index.less文件
body{
background: red;
}
在index.js文件里面引入
let str = require('./a.js')
require('./index.less')
console.log(str)
'./src/a.js'
手写两个loader
less.loader和style-loader
less-loader.js
let less = require('less')
function loader(source){
let css = ''
//将源码用less渲染
less.render(source,function(err,c){
css = c.css
})
css = css.replace(/
/g, '\n') //将
转换成\n,就是换行了,不然代表转义
return css
}
module.exports = loader
这个loader的主要作用是将我们编写的less文件渲染成浏览器可识别的css文件
style-loader.js
//创建一个style标签,将转换的源码插入到页面的head部分
function loader(source){
//创建style标签
//style.innerHTML = ${JSON.stringify(source)} 将css源码转成一行
let style = `
let style = document.createElement('style')
style.innerHTML = ${JSON.stringify(source)}
document.head.appendChild(style)
`
return style
}
module.exports = loader
这个文件的主要作用是创建一个style标签,将转换好的less源码插入到页面的head部分
在webpack.config.js里面引用这两个loader
let path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname,'dist')
},
module:{
rule:[
{
test: /.less$/,
use:[
path.resolve(__dirname,'loader','style-loader'),
path.resolve(__dirname,'loader','less-loader')
]
}
]
}
}
我们在webpack引入了两个loader,现在就需要根据路径来读我们写的less文件,并将less文件源码传给这两个loader来处理,在我们上一篇的基础上来写。
getSource(modulePath){ //读源码
//拿到模块内容
let content = fs.readFileSync(modulePath,'utf8')
//拿到配置的loader
let rules = this.config.module.rules
//拿到每个规则来处理
for(let i = 0; i< rules.length; i++){
let rule = rule[i]
let {test,use} = rule
let len = use.length-1
//如果当前路径和规则匹配 那就说明这个模块是需要loader来转化的
if(test.test(modulePath)){
//因为loader解析是从右往左,所有先从最后一个loader来处理use[len]
function normalLoader(){
//拿到loader对应的函数
let loader = require(use[len--])
//将源码内容通过loader处理
content = loader(content)
//递归处理所有的loader
if(len>=0){
normalLoader()
}
}
normalLoader()
}
}
return content
}
判断我们当前路径和我们要处理的路径是否匹配,比如index.less和我们需要处理的less文件就是匹配的,这个时候就需要调用我们写的loader递归处理。
处理的最终结果如图所示: