自定义loader和plugin

148 阅读1分钟

loader

loader是对模块的源代码进行转换处理,loader本质上一个导出为函数的javascript模块。

同步laoder

接下来我们就尝试来自定义一个同步loader:

module.exports = function(content){
//content是解析的模块的内容
  console.log('02');
  return content;
}

此时实际上我们就已经完成了一个loader的创建,然后在我们的项目使用它。

  rules: [{
       test: /.js$/,
       exclude: /node_modules/,
       use:{
            loader: 'lz-loader',
           },
        }
   ]

配置laoder的解析路径:默认是从node_modules中来解析我们安装的laoder,我们可以添加解析路径来解析我们的自定义loader.

resolveLoader:{
        modules: ['node_modules','./myloader'],
    },

异步laoder

只要在loader中调用async(),就会变为异步loader。就不会阻塞我们的主线程代码的执行了。

module.exports = function(content,map,meta){
  console.log(map,meta);
  const callback = this.async()

  setTimeout(() => {
    console.log('01');
    console.log(options);
    callback(null,content)
  }, 1000);
}


plugin

插件可以通过监听webpack的生命周期来我们完成一些操作。

下面是自定义了一个打包完成之后自动上传静态文件到服务器的插件。

插件一般都是定义为一个类,webpack内部会调用类实例中的apply()方法,因此我们需要实现apply()方法。

const {NodeSSH} = require('node-ssh')

class uploadPulgin {
  constructor(options){
    this.ssh = new NodeSSH()
    this.options = options
  }
  apply(complier){
     //监听webpack的afterEmit生命周期钩子函数(打包完成钩子)
    complier.hooks.afterEmit.tapAsync('uploadPlugin',async (compilation,callback)=>{
      console.log('myplugin');
      //获取输出文件夹
      const outputPath = compilation.outputOptions.path;

      //连接服务器
      await this.server()

      //删除原来的文件
      const remotePath = this.options.remotePath;
      await this.ssh.execCommand(`rm -rf ${remotePath}`)

      //上传文件
      await  this.uploadFiles(outputPath,remotePath);

      //关闭服务
      this.ssh.dispose()
      callback()
    })
  }

  async server(){
    await this.ssh.connect({
      host: this.options.host,
      username: this.options.username,
      password: this.options.password
    })
    console.log('连接成功');
  }

  async uploadFiles(localPath, remotePath) {
      const status = await this.ssh.putDirectory(localPath, remotePath, {
        recursive: true,
        concurrency: 10
      });
      console.log('传送到服务器: ', status ? "成功": "失败");
    }
}

module.exports = uploadPulgin;

使用自定义插件:

plugins: [
        new uploadPlugin({
            host:'39.105.207.123', //服务器地址
            username:'root',  //服务器用户名
            password:'123456', //服务器密码
            remotePath:'/text' //远程服务器的目标路径
                      }),
]

webpack中注册插件的源码部分:

// 2.注册所有的插件(传入的plugins)
	if (Array.isArray(options.plugins)) {
		for (const plugin of options.plugins) {
			if (typeof plugin === "function") {
				// 如果plugin是一个函数, 那么通过call调用plugin, 并且传入compiler
				// 第一个参数是this绑定值, 第二个是传入的参数
				plugin.call(compiler, compiler);
			} else {
				// 如果plugin是一个对象, 调用apply方法, 并且传入compiler
				plugin.apply(compiler);
			}
		}
	}

欢迎关注我们的个人博客(longzai1024.top/home ),谢谢关注!