webpack-实现loader、plugin

准备工做: npm init -y初始化一个项目 npm i webpack webpack-cli -D 建立一个webpack.config.js文件node

const path = require('path')

module.exports = {
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'dist')
    },
    mode: 'development',
}
复制代码

loader实现

经过实现一个简单的字符串替换loader来了解下loader的工做原理webpack

// index.js
console.log('yuxiaoyu')

// 建立一个loader文件夹 先建立个replaceLoader.js
// loader就是一个函数,须要用声明式函数,由于要取到上下文中的this,这个函数接受一个参数,是咱们要打包的源码
module.exports = function(source) {
    console.log(source, this.query)
    return source.replace('yuxiaoyu', '于晓俞')
}

// 而后修改webpack.config.js
const path = require('path')

module.exports = {
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'dist')
    },
    mode: 'development',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: path.resolve(__dirname, 'loader/replaceLoader.js'),
                    options: {
                        name: '实现loader'
                    }
                }
            }
        ]
    }
}
复制代码

npx webpack以后,咱们能够在main.js中看到index.js中的字符串已经被替换掉了 使用this.callback来返回多个结果信息,而不单单是源码web

/* 
    this.callback()接受四个参数
    err,content,sourceMap,meta
 */
// 修改replaceLoader.js
module.exports = function(source) {
    console.log(source, this.query)
    // return source.replace('yuxiaoyu', '于晓俞')
    this.callback(null, source.replace('yuxiaoyu', '于晓俞'))
}
复制代码

结果一样能够正常编译npm

处理异步

官方提供this.async处理loader内的异步markdown

// 修改loader
module.exports = function(source) {
    console.log(source, this.query)
    // 咱们使用this.async来处理,他会返回this.callback
    // 定义一个异步处理,告诉webpack,这个loader里有异步事件,在里面调用下这个异步
    // callback 就是 this.callback 注意参数的使用
    const callback = this.async()
    setTimeout(() => {
        callback(null, source.replace('yuxiaoyu', '于晓俞'))
    }, 3000)
}
复制代码

多个loader的使用

// 再建立一个同步的replaceLoaderSync.js
module.exports = function(source) {
    return source.replace('于晓俞', '程序猿')
}

//修改webpack.config.js文件
module: {
    rules: [
        {
            test: /\.js$/,
            use: [
                path.resolve(__dirname, 'loader/replaceLoaderSync.js'),
                {
                    loader: path.resolve(__dirname, 'loader/replaceLoader.js'),
                    options: {
                        name: '实现loader'
                    }
                }
            ]
        }
    ]
}
复制代码

处理loader的路径问题

咱们写的配置文件地址写法过于繁琐,怎么能像咱们npm i 下载的loader那样,直接写个loader名称就好了呢?这就须要咱们再配置下webpack.config.jsapp

// 配置resolveLoader, 告诉webpack去哪里查找loader,先去node_modules里查找,找不到再去loader文件夹汇总
resolveLoader: {
    modules: ['node_modules', './loader']
},
module: {
    rules: [
        {
            test: /\.js$/,
            use: [
                // 改为文件名
                'replaceLoaderSync',
                {
                    // 改为文件名
                    loader: 'replaceLoader',
                    options: {
                        name: '实现loader'
                    }
                }
            ]
        }
    ]
}
复制代码

一样能够编译成功!
异步

plugins实现

plugin: 开始打包,在某个时刻,帮助咱们处理一些什么事情的机制
一个插件由如下构成:
async

一个具名 JavaScript 函数。
在它的原型上定义 apply 方法。
指定一个触及到 webpack 自己的 事件钩子。
操做 webpack 内部的实例特定数据。
在实现功能后调用 webpack 提供的 callback。
咱们实现一个功能,在编译完成后,在输出文件时,同时输出一个txt文本
函数

// 建立一个plugin文件夹 建立文件TxtWebpackPlugin.js
/* 
    插件是由一个构造函数(此构造函数上的 prototype 对象具备 apply 方法)的所实例化出来的。这个 apply 方法在安装插件时,会被 webpack compiler 调用一次。apply 方法能够接收一个 webpack compiler 对象的引用,从而能够在回调函数中访问到 compiler 对象。
 */
class TxtWebpackPlugin {
    constructor() {}
    apply(compiler) {
        // compiler.hooks中存放这各类钩子,emit在编译成功时输出文件前执行的事件
        // 有些插件 hooks 是异步的。想要 tap(触及) 某些 hooks,咱们可使用同步方式运行的 tap 方法,或者使用异步方式运行的 tapAsync 方法或 tapPromise 方法。
        compiler.hooks.emit.tapAsync('TxtWebpackPlugin', (compilation, callback) => {
            // 处理异步的事情
            let content = '生成的文件列表:\n'
            for (var filename in compilation.assets) {
                content += filename + '\n'
            }
            compilation.assets['filelist.txt'] = {
                source: function () {
                    return content
                },
                size: function () {
                    return content.length
                }
            }
            callback()
        });
    }
}
module.exports = TxtWebpackPlugin
复制代码

相关文章
相关标签/搜索