Automate Vue Event Tracking Extraction with JSDoc, Webpack & ESLint

This article describes how to build a tool that automatically extracts event tracking (埋点) information from Vue H5 projects by leveraging custom JSDoc tags, Webpack dependency analysis, and an ESLint plugin, enabling one‑click generation of comprehensive tracking documentation and route mapping.

Huolala Tech
Huolala Tech
Huolala Tech
Automate Vue Event Tracking Extraction with JSDoc, Webpack & ESLint

Background

Event tracking is an important part of H5 projects, and tracking data is the basis for later business and technical optimization.

In daily work, product or business colleagues often ask "What tracking points does this project have?" or "Where are these points used?" which usually requires searching the code each time, resulting in low efficiency.

Because tracking points are relatively independent functions, developers find it hard to remember their purpose as the project evolves. Developers also need to organize tracking data for self‑testing. Therefore a tool can be built to scan code, analyze tracking‑related code, and transform it into specific data for use in other management platforms.

Implementation Idea

The tool can be divided into three parts: JSDoc extraction, route dependency analysis, and an ESLint plugin.

JSDoc generates API documentation from JavaScript comments; this tool uses JSDoc as the core to output tracking data.

A Webpack plugin provides route information to JSDoc.

An ESLint plugin serves as the final check to ensure every tracking code has a corresponding JSDoc comment.

Custom JSDoc Tag for Tracking

JSDoc can output documentation based on code comments. First we define a custom JSDoc tag to mark tracking comments, allowing other comments to be filtered out during processing. The following flowchart illustrates the process in the project.

Below is the concrete code implementation.

Write a JSDoc plugin and define a tag:

// jsdoc.plugin.js
// Custom @log tag; only comments with @log are considered tracking annotations
exports.defineTags = function (dictionary) {
  dictionary.defineTag('log', {
    canHaveName: true,
    onTagged: function (doclet, tag) {
      doclet.meta.log = tag.text;
    },
  });
};

Parse .ts and .vue files:

// jsdoc.plugin.js
exports.handlers = {
  beforeParse: function (e) {
    // Pre‑process files
    if (/.vue/.test(e.filename)) {
      // Parse Vue file
      const component = compiler.parseComponent(e.source);
      const ast = parse.parse(component.script.content, {
        // ...
      });
    }
    if (/.ts/.test(e.filename)) {
      // ts → js conversion
    }
  },
};

Custom JSDoc template:

// publish.js
exports.publish = function (taffyData, opts, tutorials) {
  // ...
  data().each(function (doclet) {
    // Only doclets with the log tag are tracking annotations
    if (doclet.meta && doclet.meta.log) {
      // Get route address, collect log data, etc.
      logData.push({});
    }
  });
  // Output markdown document
  fs.writeFileSync(outpath, mdContent, 'utf8');
};

At this point all tracking points can be fully output.

✅ Automatic extraction of tracking information and generation of documentation.

❌ Automatic addition of custom tag (@log) to tracking comments.

❌ Automatic addition of reporting information to tracking comments.

❌ Automatic addition of route information to tracking comments.

❌ Automatic addition of description to tracking comments.

❌ Automatic prompt for un‑commented tracking code.

From the above we can see:

Manual addition of annotation to each tracking point is required.

Manual lookup of the route for each tracking point is required.

What if a tracking point lacks annotation?

The tool aims to eliminate repetitive work; adding extra work defeats the purpose. Analyzing these problems leads to the following solutions:

Automatically add annotations → ESLint fix / VSCode plugin.

Automatically find component routes → Webpack dependency analysis.

Prompt when annotation is missing → ESLint plugin.

Next we look at the implementation of the Webpack and ESLint plugins.

Route Dependency Analysis

Webpack itself provides dependency analysis, making it easy to obtain parent‑child relationships between components.

compiler.hooks.normalModuleFactory.tap('routeAnalysePlugin', (nmf) =>
  nmf.hooks.afterResolve.tapAsync('routeAnalysePlugin', (result, callback) => {
    const { resourceResolveData } = result;
    // Child component
    const path = resourceResolveData.path;
    // Parent component
    const fatherPath = resourceResolveData.context.issuer;
    // Only process .vue files
    if (/.vue/.test(path) && /.vue/.test(fatherPath)) {
      // Store parent‑child relationship
    }
    callback();
  })
);

Combine component dependencies into the desired data format:

[
  {
    "path": "src/views/register-v2/index.vue",
    "deps": [
      {
        "path": "src/components/landing-banner/index.vue",
        "deps": []
      }
    ]
  }
  // ...
]

Parse routing files with AST to obtain component‑route mapping:

// Traverse route file
for (let i = 0; i < this.routePaths.length; i++) {
  // ...
  traverse(ast, {
    enter(path) {
      // Find component‑route pairs
      path.node.properties.forEach((item) => {
        if (item.key.name === 'component') {
          // component
        }
        if (item.key.name === 'path') {
          // route path
        }
      });
    },
  });
}

Combine route mapping and component dependencies to get each component's routes:

{
  "src/components/landing-banner/index.vue": [
    "/register_v2",
    "/register"
    // ...
  ]
  // ...
}

The AST traversal currently supports four common route definitions, covering most scenarios.

const page1 = (resolve) => {
  require.ensure([], () => {
    resolve(require('page1.vue'));
  }, 'page1');
};

const page2 = () => import(/* webpackChunkName: "page2" */ 'page2.vue');

export default [
  { path: '/page1', component: page1 },
  { path: '/page2', component: page2 },
  { path: '/page3', component: (resolve) => {
      require.ensure([], () => {
        resolve(require('page3.vue'));
      }, 'page3');
    }
  },
  { path: '/page4', component: () => import(/* webpackChunkName: "page4" */ 'page4.vue') },
];

After obtaining the mapping, the tracking data can be sent to the tracking management platform for one‑click query.

Write ESLint Plugin

There are three ways to report tracking in code:

// sensors SDK
sensors.track('xxx', {});

// mounted on Vue instance
this.$sa.track('xxx', {});

// decorator
@SensorTrack('xxx', {});

Since reporting uses the track function and SensorTrack, the ESLint plugin validates these calls.

function create(context) {
  // Objects that call track
  const checkList = ['sensor', 'sensors', '$sa', 'sa'];

  return {
    Literal(node) {
      // ... detect missing comment for track calls
      if (isNoComment && ((isTrack && isSensor) || (is$Track && isThisExpression))) {
        context.report({
          node,
          messageId: 'missingComment',
          fix(fixer) {
            // auto‑fix
          },
        });
      }
      // ... detect missing comment for decorator
      if (callee.name === 'SensorTrack' && sourceCode.getCommentsBefore(node).length === 0) {
        context.report({
          node,
          messageId: 'missingComment',
          fix(fixer) {
            // auto‑fix
          },
        });
      }
    },
  };
}

Result after completion:

Effect Comparison

Before optimization, only automatic extraction and documentation generation were available. After adding the plugins, the tool can also automatically add custom tags, reporting information, route information, and prompt for missing annotations, greatly reducing manual effort.

Summary

Integrating this tool into a project enables developers to quickly know which tracking points exist and on which pages, facilitating tracking organization and allowing backend applications to use the exported data, thereby improving development efficiency.

The tool is realized with JSDoc, Webpack, and ESLint plugins. Initially only the first step (one‑click query) was implemented; later enhancements automated annotation, route information, and missing‑annotation prompts, making the workflow largely automatic.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AutomationVuewebpackevent trackingESLintJSDoc
Huolala Tech
Written by

Huolala Tech

Technology reshapes logistics

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.