zoukankan      html  css  js  c++  java
  • 手写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(/
    /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递归处理。

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

      

    不积跬步无以至千里
  • 相关阅读:
    程序包管理
    磁盘篇
    centos7上常用软件安装
    这个端午
    字节码技术及动态代理
    浅析同步异步阻塞非阻塞
    String拾遗
    Java注解拾遗
    设计模式之总结篇
    设计模式之访问者模式
  • 原文地址:https://www.cnblogs.com/lyt0207/p/12583828.html
Copyright © 2011-2022 走看看