First, why do this?

Adding buried points in the project is an important part of data analysis. Every time the project falls, there will be more or less demand for buried points. Then, can we add these buried points in the form of automation?

Answer: For most buried points, it can be added automatically

What is it?

This is a very basic function plug-in. Add a buried code to a function under methods whose function name ends in _track, for example:

/ / the vue source code
export default {
  data () {
    return {
      baseTrackProps: {
        appName: 'ardf'}}},methods: {
    getApp_track (param_01, params_02) {
      console.log(param_01, params_02, this.baseTrackProps)
    }
  }
}

Copy the code

The above code, when packaged, will add one such code to the getApp_track function

this.$track('getApp_track', {
    param_01: param_01,
    params_02: params_02,
    baseTrackProps: this.baseTrackProps
})
Copy the code

Three, how to do it?

Write a Babel plug-in that uses Babel’s operations on the AST (abstract syntax tree) to find the corresponding function and insert a statement inside the function

Iv. Project design

Plan to write a development framework that can be published on NPM for other projects to introduce

Auto - track ├ ─. Gitignore ├ ─ README. Md ├ ─ Babel. Config. Js ├ ─ lib │ ├ ─ index. The js │ └ ─ index. The js. Map ├ ─ package. The json ├ ─ ├─ SRC │ ├─ ├─ ├─ ├─ ├─ ├─ ├.htm // Insert statement │ ├ ─ index. Js │ ├ ─ lib │ │ └ ─ util. Js │ └ ─ webpackPlugins │ └ ─ removeBabelLoaderCache. Js └ ─ yarn. The lockCopy the code

Babel will not be executed every time webpack uses babel-loader, so the Babel plug-in needs to be removed before it runs. Therefore, a Webpack plug-in is used to delete babel-Loader’s cache when Webpack starts

Core code:

index.js

const addTrack = require('./babelPlugins/addTrack')
const RemoveBabelLoaderCache = require('./webpackPlugins/removeBabelLoaderCache')

module.exports = {
  addTrack: addTrack,
  removeBabelLoaderCache: RemoveBabelLoaderCache
}
Copy the code

removeBabelLoaderCache.js

const util = require('.. /lib/util')

const pluginName = 'removeBabelLoaderCache'
class RemoveBabelLoaderCache {
  constructor({basePath}){
    // The parameters passed in are mounted on the instance of the class.
    this.basePath = basePath
  }
  apply(compiler) {

    compiler.hooks.run.tap(pluginName, (compilation) = > {
      console.log('***** Webpack build process begins! * * * * * ');
      const babelLoaderCachePath = `The ${this.basePath}/node_modules/.cache/babel-loader`
      
      // Delete the babel-loader cache
      util.removeDir(babelLoaderCachePath)
    })

    compiler.hooks.done.tap(pluginName, (stats) = > {
      console.log('***** Webpack build over! * * * * * ')}}}module.exports = RemoveBabelLoaderCache;

Copy the code

addTrack.js

module.exports = function (babel, options) {
  console.log('** : Babel plugin starts executing ***')
  const { types, template } = babel
  return {
    name: 'add-track-babel-plugin'.visitor: {
      Identifier (path, state) {
        const { name } = path.node
        if (name.endsWith('_track')) {
          try {
            if (path.node.loc && path.node.loc.start) {
              const location = `---track: line ${path.node.loc.start.line}, column ${path.node.loc.start.column}.${state.filename}- `;
              console.log(location)
              const parentNode = path.parent
              const functionNode = parentNode.value
              if (types.isFunctionExpression(functionNode)) {
                const body = functionNode.body
                if (types.isBlockStatement(body)) {
                  const params = functionNode.params
                  var s = '{'
                  params.forEach(p= > {
                    s = s + p.name + ':' + p.name + ', '
                  })
                  s = s + 'baseTrackProps: this.baseTrackProps}'
                  const tName = ` '${name}'`
                  const addCodeStr = `this.$track(${tName}.${s}) `
                  
                  // Insert a buried statement into the functionbody.body.unshift(template.statement(addCodeStr)()); }}}}catch (error) {
            console.error(error)
          }
        }
      }
    }
  }
}
Copy the code

To write code that parses AST statements, you can use astExplorer to write similar code to quickly find the TYPE of AST node you need to observe

V. How to use it in VUE project?

Step 1: In main.js, add the buried method

The demo code

. Vue.prototype.$track = (name, data={}) => { if (data.baseTrackProps) { const baseTrackProps = { ... data.baseTrackProps } delete data.baseTrackProps const params = { ... data, ... BaseTrackProps} the console. The log (` * * * * track: ${name},${JSON.stringify(params)}******`) } else { delete data.baseTrackProps const params = { ... Data} the console. The log (` * * * * track: ${name}, ${JSON. Stringify (params)} * * * * * * `)}}...Copy the code

Step 2: In vue.config.js, configure to use the WebPack plug-in

const autoTrack = require('auto-track') module.exports = { ... / / omit other configureWebpack: (config) = > {config. Plugins. Push (new autoTrack. RemoveBabelLoaderCache ({basePath: __dirname })) } ... }Copy the code

Step 3: In babel.config.js, configure the use of the Babel plug-in

const autoTrack = require('auto-track') module.exports = { presets: [ ... ] Plugins: [... // autotrack.addtrack]}Copy the code

That’s it. After that, add _track after the name of the function where you want to add the buried statement, and the packed code will automatically add the buried statement

Complete source code, visible github: github.com/lcl6659/aut…

Special note: Inspired by ZxG_ God said to have light “Babel Plug-in Secrets”