背景
创建一个 Webpack 插件来自动注册 Vue 指令,并使用第三方实例自动进行埋点跟踪。这个插件会自动注册一个 Vue 指令,获取指令绑定的字符串,并使用从第三方获取的埋点实例的方法和字符串进行调用。
实现步骤
1.创建 Webpack 插件:在插件中注册 Vue 指令。 2.从第三方获取埋点实例:假设我们已经有一个方法可以获得埋点实例。 3.在 Vue 指令中调用埋点方法:根据指令绑定的字符串调用埋点方法。
示例代码
Class AutoTrackingPlugin {
constructor(options) {
this.options = options || {};
}
apply(compiler){
// Webpack 的 compile 阶段进行处理
compiler.hooks.emit.tapsAsync('AutoTrackingPlugin', (compilation,callback)=>{
// 构建一个指令注册的 Vue 代码
const directiveCode = `
import Vue from Vue;
import trackingInstance from '${this.options.trackingInstance}';
// 自定义指令
Vue.directive('auto-track', {
bind(el, binding) {
const eventName = binding.value; // 获取指令绑定的字符串
// 保存事件处理函数的引用
const trackEvent = ()=>{
// 实例,调用埋点实例的方法,一般看各自业务代码的各自实现
if(trackingInstance && typeof trackingInstance.track==='function') {
trackingInstance.track(eventName);
}else {
console.warn('Tracking instance is not avaliable or track method is not a function.')
}
}
// 注册事件监听
el.addEventListener('click', trackEvent)
// 将事件处理函数保存在元素上,以便在unbind中使用
el._trackEvent = trackEvent;
},
unbind(el){
// 移除事件监听
el.removeEventListener('click', el._trackEvent)
// 清除引用
delete el._trackEvent;
}
})
`;
// 将指令代码添加到一个新的文件中
compilation.assets['auto-tracking-directive.js']= {
source:()=>directiveCode,
size:()=>directiveCode.length
};
callback();
})
}
}
module.exports = AutoTrackingPlugin;
使用实例
使用插件
// webpack.config.js
// path 是引入插件的路径,可能是本体,可能是线上包
const AutoTrackingPlugin = require('path')
module.exports = {
// ...其他配置项
plugins: [
new AutoTrackingPlugin({
trackingInstance:'path/to/your/tracking/instance', // 埋点实例路径
})
]
}
使用vue指令
<template>
<button v-auto-track="'button_click_id'">Click me</button>
</template>
<script>
export default {
// ...
}
</script>
插件代码解析
1.构造函数:接受一个 options 参数,其中可以传递第三方埋点实例的路径。
constructor(options) {
this.options = options || {};
}
2.apply方法:在 emit 钩子中添加代码,将 Vue 指令注册到生成的 JavaScript 文件中。
apply(compiler) {
compiler.hooks.emit.tapAsync('AutoTrackingPlugin', (complilation,callback)=>{
// ...
callback();
})
}
3.注册 Vue 指令:
- 创建一个名为 auto-track 的自定义指令。
- 在 bind 方法中,获取指令绑定的字符串 binding.value ,并将其作为事件名称。
- 为元素添加一个 click 事件监听器,在事件触发时调用埋点实例的方法。
Vue.directive('auto-track',{
bind(el,binding) {
const eventName = binding.value; // 获取字符串作为参数
// ...
},
unbind(el){
// ...
}
})
4.添加到输出文件:将生成的 Vue 指令代码添加到 auto-tracking-directive.js 文件中,供 Vue 组件使用。
拓展
可以使用 schema-utils 来校验插件输入项
schema-utils 是一个 JSON Schema 校验库,内部使用了 ajv(Another JSON Schema Validator) 库,这个库被大多数校验工具所使用,是一个快速、灵活的 JSON Schema 验证器,支持最新的 JSON Schema 规范和许多额外的功能,像 element-ui 的表单校验就能看出来和下面要写的很类似。
使用 ajv 的好处。性能:性能高效,能快速处理验证;灵活性:支持复杂的 schema 功能,如 allOf、anyOf、oneOf等;扩展性:可以通过插件扩展 ajv。
1.安装 schema-utils : 确保安装了 schema-utils,一般可以考虑使用 npm 或者 yarn 安装到开发环境
npm install schema-utils --save-dev
或者
yarn add schema-utils --dev
2.定义 schema: 可以定义一个 JSON Schema 来描述插件的配置选项。
3.在插件中校验选项: 在插件的构造函数中使用 schema-utils 来验证选项。
部分示例代码
// AutoTrackingPlugin.js
const {validate} = require ('schema-utils');
const schema = {
type:'object',
properties: {
trackingInstance: {
type: 'string',
minLength:1,
},
},
required: ['trackingInstance']
}
class AutoTrackingPlugin {
constructor(options) {
// 验证传入的选项
validate(schema,options,{
name:'AutoTrackingPlugin',
baseDataPath:'options',
});
this.options = options || {};
}
}
代码解释
validate 中的参数说明
- name:用于指定验证的上下文名称。主要作用:1、上下文描述:name 主要作用于在验证过程中为特定的插件或模块提供一个上下文名称,帮助识别是哪个插件的选项正在被验证。这在错误信息中会非常有用,尤其是在大型项目中,有多个插件同时使用时。 2、错误信息的清晰度:当选项不符合 schema 时,name 会出现在错误信息中,帮助开发者快速定位问题。例如,如果你在调用 validate 时传入 name: 'AutoTrackingPlugin',当验证失败时,错误信息可能会显示为:
AutoTrackingPlugin: options.trackingInstance must be a string
- baseDataPath: 用于在验证选项时提供基准路径信息。主要作用:1、描述上下文:在验证过程中,如果出现错误,baseDataPath 将帮助用户理解错误信息中的数据结构层次。例如,当插件选项不符合定义的 schema 时,baseDataPath 将指示错误发生的位置。 2、清晰的错误信息:如果你设置 baseDataPath 为 'options',当选项不符合 schema 时,错误信息会更清晰地指向具体的选项问题,例如 'options.trackingInstance',而不只是显示 'trackingInstance'
总结
通过自定义一个 Webpack 的自定义插件去自动给 Vue 项目添加指令,方便快捷给项目代码添加埋点代码,减少重复及繁琐性。