我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么使用webpack在日志中记录文件行号

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么使用webpack在日志中记录文件行号

本文小编为大家详细介绍“怎么使用webpack在日志中记录文件行号”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用webpack在日志中记录文件行号”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

前言

在做前端项目时,会在各个关键节点打印日志,方便后续数据分析和问题排查。当日志越来越多之后,又会遇到通过日志反查代码所在文件和所在行的场景,于是一个很自然的需求就出来了:

在打印日志的时候,自动注入当前文件名、行号、列号。

举个例子,有个 logger 函数,我们在 index.js 的业务代码某一行添加打印逻辑:

const { logLine } = require('./utils')function getJuejinArticles() {  const author = 'keliq'  const level = 'LV.5'  // ... 业务代码省略,获取文章列表  logLine(author, level)  // ...}getJuejinArticles()

正常情况下会输出:

keliq LV.5

但是希望能够输出带文件名和行号,即:

[index.js:7:3] keliq LV.5

表明当前这次打印输出来源于 index.js 文件中的第 7 行第 3 列代码,也就是 logLine 函数所在的具体位置。那如何实现这个需求呢?我的脑海中浮现了两个思路:

通过提取 Error 错误栈

因为 error 错误栈里面天然带有此类信息,可以人工制造了一个 Error,然后捕获它:

exports.logLine = (...args) => {  try {    throw new Error()  } catch (e) {    console.log(e.stack)  }}

仔细观察打印的结果:

Error
    at logLine (/test/class="lazy" data-src/utils.js:3:11)
    at getJuejinArticles (/test/class="lazy" data-src/index.js:7:3)
    at Object.<anonymous> (/test/class="lazy" data-src/index.js:11:1)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47

第三行的内容不正是我们想要的结果吗?只需要把这一行的字符串进行格式化一下,提取出 index.js:7:3 即可:

at getJuejinArticles (/test/class="lazy" data-src/index.js:7:3)

由于代码结构是这样的:

.
└── class="lazy" data-src
    ├── index.js
    └── utils.js

只需要改成下面的代码即可:

exports.logLine = (...args) => {  try {    throw new Error()  } catch (e) {    const lines = e.stack.split('\n')    const fileLine = lines[2].split('/class="lazy" data-src/').pop().slice(0, -1)    console.log(`[${fileLine}]`, ...args)  }}

命令行试一试:

$ test node class="lazy" data-src/index.js [index.js:7:3] keliq LV.5

问题似乎完美解决,然而还是想的太简单了,上述场景仅限于 node.js 环境,而在 web 环境,所有的产物都会被 webpack 打到一个或多个 js 文件里面,而且做了压缩混淆处理,由于 error 是在运行时被捕获到的 ,所以我没根本无法拿到开发状态下的文件名、行号和列号,如下图所示:

怎么使用webpack在日志中记录文件行号

通过 webpack 预处理

那怎么办呢?解铃还须系铃人,既然 webpack 对代码进行了加工处理,那就只能在预处理最开始的阶段介入进来,写一个自定义的 loader 来解析源码文件,拿到文件名、行号和列号。说干就干,创建一个 inject-line.loader.js,写下模板代码:

module.exports = function (content) {  content = content.toString('utf-8')  if (this.cacheable) this.cacheable()  console.log(this.resourcePath) // 打印文件路径  console.log(content) // 打印文件内容  return content}module.exports.raw = true

然后在 webpack.config.js 中做配置:

module.exports = {  entry: './class="lazy" data-src/index.js',  output: {    filename: 'index.js',  },  module: {    rules: [      {        test: /.js$/,        exclude: [/node_modules/],        use: [          {            loader: require.resolve('./loaders/inject-line.loader'),          },        ],      },    ],  },}

一切准备就绪,先运行一下看看输出:

怎么使用webpack在日志中记录文件行号

可以看到,index.js 和 utils.js 被自定义的 inject-line.loader.js 给加载到了,通过 this.resourcePath 能够拿到文件名称,行号和列号的话只能通过分析 content 字符串进行提取了,处理的代码如下:

// 拿到文件路径const fileName = this.resourcePath.split('/class="lazy" data-src/').pop()// 文本内容按行处理后再拼接起来content = content  .split('\n')  .map((line, row) => {    const re = /logLine((.*?))/g    let result    let newLine = ''    let cursor = 0    while ((result = re.exec(line))) {      const col = result.index      newLine += line.slice(cursor, result.index) + `logLine('${fileName}:${row + 1}:${col + 1}', ` + result[1] + ')'      cursor += col + result[0].length    }    newLine += line.slice(cursor)    return newLine  })  .join('\n')

这里面的逻辑,如果光看代码的话可能会云里雾里,其实思路很简单,就是下面这样的:

怎么使用webpack在日志中记录文件行号

这样的话,即使代码经过各种压缩转换,也不会改变开发状态下代码所在的文件名、行与列的位置了。打开 webpack 打包后的文件看一下:

怎么使用webpack在日志中记录文件行号

到这里,功能就已经开发完了,不过还有一个小小的缺陷就是 logLine 函数名是写死的,能不能让用户自己定义这个函数名呢?当然可以,在 webpack 配置文件中,支持利用 options 属性传递 config 配置参数:

module.exports = {  entry: './class="lazy" data-src/index.js',  output: {    filename: 'index.js',  },  module: {    rules: [      {        test: /.js$/,        exclude: [/node_modules/],        use: [          {            loader: require.resolve('./loaders/inject-line.loader'),            options: {              config: {                name: 'customLogName',              },            },          },        ],      },    ],  },}

然后在 inject-line.loader.js 代码中通过 this.query.config 拿到该配置即可,不过正则表达式也要根据这个配置动态创建,字符串替换的时候也要换成该配置变量,最终代码如下:

module.exports = function (content) {  content = content.toString('utf-8')  if (this.cacheable) this.cacheable()  const { name = 'logLine' } = this.query.config || {}  const fileName = this.resourcePath.split('/class="lazy" data-src/').pop()  content = content    .split('\n')    .map((line, row) => {      const re = new RegExp(`${name}\((.*?)\)`, 'g')      let result      let newLine = ''      let cursor = 0      while ((result = re.exec(line))) {        const col = result.index        newLine += line.slice(cursor, result.index) + `${name}('${fileName}:${row + 1}:${col + 1}', ` + result[1] + ')'        cursor += col + result[0].length      }      newLine += line.slice(cursor)      return newLine    })    .join('\n')  return content}module.exports.raw = true

读到这里,这篇“怎么使用webpack在日志中记录文件行号”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么使用webpack在日志中记录文件行号

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么使用webpack在日志中记录文件行号

本文小编为大家详细介绍“怎么使用webpack在日志中记录文件行号”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用webpack在日志中记录文件行号”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。前言在做前
2023-07-04

C#怎么使用Log4.net记录日志文件

这篇文章主要讲解了“C#怎么使用Log4.net记录日志文件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#怎么使用Log4.net记录日志文件”吧!一、简介1.1 Log4.net优点几
2023-06-30

在springboot中怎么使用AOP进行全局日志记录

小编给大家分享一下在springboot中怎么使用AOP进行全局日志记录,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1、 spring AOP 是什么?spring 的两大核心就是 IOC 和 AOP,AOP 是 spr
2023-06-21

thinkphp6如何使用中间件记录行为日志

这篇文章主要介绍了thinkphp6如何使用中间件记录行为日志问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-03-24

怎么在python中利用 loguru记录日志

本篇文章为大家展示了怎么在python中利用 loguru记录日志,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。python有哪些常用库python常用的库:1.requesuts;2.scrapy
2023-06-14

laravel怎么使用中间件记录用户请求日志

这篇文章主要讲解了“laravel怎么使用中间件记录用户请求日志”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“laravel怎么使用中间件记录用户请求日志”吧!一、创建中间件可以使用命令创建
2023-06-30

如何使用logzero在Python中进行简单日志记录

这篇文章主要介绍如何使用logzero在Python中进行简单日志记录,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!logzero 库使日志记录就像打印语句一样容易,是简单性的杰出代表。我不确定 logzero 的名
2023-06-16

运行在Docker里的SpringBoot应用是如何查看记录在文件系统的日志

运行在Docker里的SpringBoot应用是如何查看记录在文件系统的日志,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。我有一个SpringBoot应用,将其
2023-06-04

怎么在Linux中使用cronolog切割服务器日志文件

这篇文章给大家介绍怎么在Linux中使用cronolog切割服务器日志文件,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1、下载(最新版本)代码如下:# wget http://cronolog.org/downlo
2023-06-12

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录