手写webpack(二)增加loader功能

时间:2020-03-27
本文章向大家介绍手写webpack(二)增加loader功能,主要包括手写webpack(二)增加loader功能使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

上篇文章我们实现了一个简易版的webpack,可以打包我们的js代码,但是还不能处理我们的 css、less、scss、图片等,这些都是需要loader和plugin来处理,所以,为了打包器更强大,需要增加loaderplugin的支持,接着我们就手写实现一个简单的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(/\n/g, '\\n') //将\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递归处理。

处理的最终结果如图所示:

原文地址:https://www.cnblogs.com/lyt0207/p/12583828.html