webpack-plugin

Plugins

插件,是一个带有apply方法的对象。可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。
插件的目的是为了增强webpack在项目自动化构建方面的能力,范围更广,用途更多

插件的组成

  • 一个JavaScript命名函数
  • 在插件函数的prototype上定义一个apply方法
  • 指定一个绑定到webpack自身的事件钩子
  • 处理webpack内部实例的特定数据
  • 功能完成后调用webpack提供的回调

常见的应用场景:

清除打包之前的目录
自动生成html文件
压缩文件
自动发布打包结果到服务器实现自动部署

原理

插件使用钩子机制,webpack在每一个环节提供一个钩子,在不同的环节挂载不同的任务
通过loader处理特殊资源的加载,通过plugin实现自动化的构建任务,例如:自动压缩、自动发布

plugins:[
  new HtmlWebpackPlugin({ // 打包html资源
    template:'./src/index.html', // 复制 ./src/index.html文件,并自动引入打包输出的所有资源
  }),
]

插件的生命周期钩子

钩子说明参数类型
afterPlugins启动一次新的编译compiler同步
compile创建compilation对象之前compilationParams同步
compilationcompilation对象创建完成compilation同步
emit资源生成完成,输出之前compilation异步
afterEmit资源输出到目录完成compilation异步
done完成编译stats同步
entryOption在处理了webpack选项的entry配置后调用context,entrySyncbailHook

自定义插件

tapable

Tapable暴露了tap、tapAsync和tapPromise方法,根据钩子的同步/异步方式选择一个方法注入逻辑

tap:同步钩子。不能包含异步调用
tapAsync:异步钩子,通过callback回调告诉webpack异步执行完毕
tapPromise:异步钩子,返回一个promise告诉webpack异步执行完毕

compiler和compilation的区别

compiler对象表示不变的webpack环境,是针对webpack的
compilation对象针对的是随时可变的项目文件,只要文件有改动,compilation就会被重新创建

实现

// 校验插件配置的工具库
const {
  validate
} = require('schema-utils');
// node内置模块
const path = require('path');
const util = require('util');

const webpack = require('webpack');
const {
  RawSource
} = webpack.sources
const globby = require('globby');
const {
  schema
} = require('webpack-dev-server');
const {
  readFile
} = require('fs');
class CopyWebpackPlugin {
  constructor(options = {}) {
    // 验证options是否符合规范
    validate(schema, options, {
      name: 'CopyWebpackPlugin'
    });
    this.options = options;

  }
  apply(compiler) {
    // 初始化complation
    compiler.hooks.thisCompilation('CopyWebpackPlugin', (compilation) => {
      compilation.hooks.additionalAssets.tapAsync('CopyWebpackPlugin', async (cb) => {
        // 将from中的资源复制到to中,输出出去
        const {
          from,
          ignore
        } = this.options;
        const to = this.options.to ? this.options.to : '.';
        // 1. 读取from中的所有资源
        // context就是webpack配置
        // 运行指令的目录
        const context = compilation.options.context;
        // 将输入路径变成绝对路径
        const absolutePath = path.isAbsolute(from) ? from : path.resolve(from);
        // 1. 过滤掉ignore文件
        const paths = await globby(absolutePath, {
          ignore
        });
        // 2. 读取from中的所有资源
        const files = Promise.all(path.map(async (absolutePath) => {
          const data = await readFile(absolutePath);
          const relativePath = path.basename(absolutePath);
          const fileName = path.join(to, relativePath);
          return {
            data,
            fileName
          }
        }))

        // 3. 生成webpack格式的文件
        const assets = files.map((file) => {
          const source = new RawSource(file.data);
          return {
            source,
            filename: file.filename
          }
        });
        // 4. 添加compliation中,输出出去
        assets.forEach(asset => {
          compilation.emitAsset(asset.filename, asset.source);
        });
        cb();
      });
    });
  }
}
module.exports = CopyWebpackPlugin;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端御书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值