背景

我们平时在使用 console.log 打印日志的时候,如果有很多个,有时候会很难分辨是从哪里打印的这个日志,如下:

  1. /** ./src/index.js **/
  2. import { flatten, concat } from 'lodash';
  3. //按需加载相当于
  4. // import flatten from 'lodash/flatten';
  5. // import concat from 'lodash/concat';
  6. console.log(flatten, concat);
  7. console.log(111);

image.png
只打印了 111 ,我们需要把它的第几行,第几列都打印出来,方便我们查找问题。如下

  1. 'index.js' 9 0 111

如何实现

实现方法和 import.js 类似。
我们新建一个 showPosition.js,然后在 webpack.config.js 中引入。

/** ./webpack.config.js **/
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[hash:8].js'
  },
  devtool:'source-map',
  module:{
    rules:[
      {
        test:/\.js$/,
        use:{
          loader:'babel-loader',
          options: {
            plugins:[
              [path.resolve(__dirname, 'import'), {
                // 指定要按需加载的模块
                'libraryName': 'lodash',
                // 按需加载的目录,默认是 lib
                'libraryDirectory':'',
                'camel2DashComponentName':false
              }],
              [path.resolve(__dirname, 'showPosition')]
            ]
          }
        }
      }
    ]
  },
  plugins:[
    new webpack.CleanPlugin(),
    new HtmlWebpackPlugin({
      filename:'index.html',
      inject:'body'
    })
  ]
}

抽象语法树

我们来看一下 console 的抽象语法树
image.png

编写 showPosition 代码

const types = require('@babel/types');

const visitor = {
  CallExpression(path){
    if(types.isMemberExpression(path.node.callee)){
      if(path.node.callee.object.name === 'console'){
        if(['log', 'info', 'warn', 'error', 'debug'].includes(path.node.callee.property.name)){
          const { line, column } = path.node.loc.start;
          path.node.arguments.unshift(types.stringLiteral(`${line}:${column}`));
        }
      }
    }
  }
}

module.exports = ()=>{
  return {
    visitor
  }
}

再看打印结果
image.png
这样就实现了