rollup打包js库 占位符替换成文件名和行号输出日志中定位报错位置

这篇具有很好参考价值的文章主要介绍了rollup打包js库 占位符替换成文件名和行号输出日志中定位报错位置。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简易版

问题:在打包的js库中有很多日志或者error的控制台输出,但是打包后的js调用报错后无法从控制台看到堆栈信息,无法定位报错的位置是在哪个文件的哪一行

需求:能够从报错中观察到报错在哪个文件的那一行,便于排查错误

实现:自定义插件来实现此功能

思路:在打包时遍历要打包的文件,将文件内容按照换行符进行分割,得到的集合就是这个文件的代码,便可以拿到行号,然后通过正则表达式对占位符进行全局替换。

代码:

  • replace.js
// 导入path包获取文件名,也可以通过正则来自己获取
import path from 'path';

export default function replace(options = {}) {
    const { placeholders = [] } = options;
    let fileCount = 0;
    let replaceCount = 0;
    return {
        //插件名
        name: 'placeholder-replace',
        transform(code, id) {
            // 将代码转换为 UTF-8 编码
            code = code.toString('utf-8');

            // 获取文件名
            const fileName = path.basename(id);

            // 遍历每个占位符
            code = placeholders.reduce((modifiedCode, placeholder) => {
                // 构建占位符的正则表达式
                const placeholderRegex = new RegExp(`${placeholder}`, 'g');
                return modifiedCode
                    .split('\n')
                    .map((line, row) => {
                        let newLine = '';
                        let cursor = 0;
                        let result;
                        while ((result = placeholderRegex.exec(line))) {
                            const col = result.index;
                            // 替换占位符为文件名:行号=>>的形式
                            newLine += line.slice(cursor, result.index) + `${fileName}:${row + 1} =>> `;
                            cursor += col + result[0].length;
                        }
                        newLine += line.slice(cursor);
                        return newLine;
                    })
                    .join('\n');
            }, code);

            return code;
        },
        buildEnd() {
            console.log(`\n替换的文件数: ${fileCount}`);
            console.log(`\n替换的次数: ${replaceCount}`);
        },
    };
}


配置:

import replace from './replace.js';

export default {
  // ...其他配置项
  plugins: [
    replace({
      placeholders: ['log-position-placeholder', 'another-placeholder'], // 设置占位符数组
    }),
  ],
};

进阶版

使用简易版的存在一个问题, 打包后生成的sourceMap文件中的映射内容是空的,如果不需要这个文件的可以使用简易版的,进阶版则是完善了这个问题的解决

代码

replcae.js

import path from 'path';
// 导入 rollup-pluginutils 包,它提供了一些工具函数来处理 sourcemap
import {createFilter} from 'rollup-pluginutils';
// 导入 magic-string 包,它可以让你修改字符串并生成 sourcemap
import MagicString from 'magic-string';

export default function replace(options = {}) {

    const {placeholders = []} = options;
    let fileCount = 0;
    let replaceCount = 0;

    // 使用 createFilter 函数来过滤掉不需要处理的文件
    const filter = createFilter(options.include, options.exclude);

    return {
        // 插件名
        name: 'placeholder-replace',

        transform(code, id) {
            // 如果文件不符合过滤条件,直接返回
            if (!filter(id)) return null;

            // 将代码转换为 UTF-8 编码
            code = code.toString('utf-8');

            // 创建一个 MagicString 对象,用于修改代码和生成 sourcemap
            const magicString = new MagicString(code);

            // 获取文件名
            const fileName = path.basename(id);

            // 遍历每个占位符
            placeholders.forEach(placeholder => {
                // 构建占位符的正则表达式
                const placeholderRegex = new RegExp(`${placeholder}`, 'g');
                let result;
                while ((result = placeholderRegex.exec(code))) {

                    const start = result.index;
                    const end = start + result[0].length;

                    // 获取行号和列号
                    const line = getRow(result.input, start, '\n');

                    // 替换占位符为文件名:行号=>>的形式
                    magicString.overwrite(start, end, `${fileName}:${line} =>> `);

                    replaceCount++;
                }
            });

            fileCount++;

            // 返回修改后的代码和 sourcemap 对象
            return {
                code: magicString.toString(),
                map: magicString.generateMap({hires: true})
            };
        },

        buildEnd() {
            console.log(`\n替换的文件数: ${fileCount}`);
            console.log(`\n替换的次数: ${replaceCount}`);
        },
    };
}

/**
 * 获取行号
 * @param str 代码内容
 * @param end  截止位置
 * @param tag  换行符
 * @return {number} 行号
 */
function getRow(str, end, tag) {
    let slice = str.slice(0, end);
    let split = slice.split(tag);
    let length = split.length;
    return  length;
}



扩展版


import path from 'path';
// 导入 rollup-pluginutils 包,它提供了一些工具函数来处理 sourcemap
import {createFilter} from 'rollup-pluginutils';
// 导入 magic-string 包,它可以让你修改字符串并生成 sourcemap
import MagicString from 'magic-string';


/**
 *文件内容替换: 两个关键字fileName,row
 * @param options: {handles:
 * [{src: '', 待替换的字符串
 * target: ''}], 目标字符串
 * include: '', 包含的文件
 * exclude: ''} 排除的文件
 *
 * 示例配置: replace({
            handles: [{src: 'log-position-placeholder'}, {src: 'console\\.log\\(', target: 'console.log("调试输出:  fileName:row ==> " +'}], // 设置占位符数组
        })
 将log-position-placeholder替换成文件名加行号,以及将console.log( 替换成 console.log("调试输出: 文件名加行号
 注意src里面的特殊符合需要用两个\\来进行转义
 * @return
 */
export default function replace(options = {}) {
    options = Object.assign({handles: [{src: '', target: ''}]}, options);
    let fileCount = 0;
    let replaceCount = 0;
    // 使用 createFilter 函数来过滤掉不需要处理的文件
    const filter = createFilter(options.include, options.exclude);
    return {
        // 插件名
        name: 'placeholder-replace',

        transform(code, id) {
            // 如果文件不符合过滤条件,直接返回
            if (!filter(id)) return null;
            // 将代码转换为 UTF-8 编码
            code = code.toString('utf-8');

            // 创建一个 MagicString 对象,用于修改代码和生成 sourcemap
            const magicString = new MagicString(code);

            // 获取文件名
            const fileName = path.basename(id);
            // 遍历每个占位符
            options.handles.forEach(handle => {
                // 构建占位符的正则表达式
                const placeholderRegex = new RegExp(`${handle.src}`, 'g');
                let result;
                while ((result = placeholderRegex.exec(code))) {

                    const start = result.index;
                    const end = start + result[0].length;

                    // 获取行号和列号
                    const line = getRow(result.input, start, '\n');

                    // 替换占位符为文件名:行号=>>的形式
                    let target = handle.target;

                    if (target) {
                        target = target.indexOf('row') !== -1 ? target.replace('row', line) : target;
                        target = target.indexOf('fileName') !== -1 ? target.replace('fileName', fileName) : target;
                    } else {
                        target = `${fileName}:${line} =>> `;
                    }
                    magicString.overwrite(start, end, target);

                    replaceCount++;
                }
            });

            fileCount++;

            // 返回修改后的代码和 sourcemap 对象
            return {
                code: magicString.toString(),
                map: magicString.generateMap({hires: true})
            };
        },

        buildEnd() {
            console.log(`\n替换的文件数: ${fileCount}`);
            console.log(`\n替换的次数: ${replaceCount}`);
        },
    };
}

/**
 * 获取行号
 * @param str 代码内容
 * @param end  截止位置
 * @param tag  换行符
 * @return {number} 行号
 */
function getRow(str, end, tag) {
    let slice = str.slice(0, end);
    let split = slice.split(tag);
    let length = split.length;
    return length;
}


配置:

配置和简易版是一样的,只是增加了一个包含和排除掉选项文章来源地址https://www.toymoban.com/news/detail-573373.html

扩展:

  • 除了 transform钩子函数之外,Rollup 还提供了其他一些常用的钩子函数,用于在构建过程中执行特定的逻辑。以下是一些常用的钩子函数:
buildStart:在构建过程开始时调用,可以在其中执行一些初始化操作。
buildEnd:在构建完成后调用。
resolveId:在解析模块标识符时调用,可以自定义模块的解析逻辑。
load:在加载模块时调用,可以自定义模块的加载逻辑。
transform:在转换模块代码时调用,可以修改模块的代码内容。
renderStart:在开始渲染生成输出文件时调用,可以执行一些准备工作。
renderChunk:在渲染每个输出块(chunk)时调用,可以修改输出块的代码内容。
renderDynamicImport:在渲染动态导入语句时调用,可以自定义动态导入的行为。
writeBundle:在生成输出文件完成后调用,可以执行一些清理或后处理的操作。
这些钩子函数可以根据需要选择使用,并根据特定的构建过程进行定制。你可以根据自己的需求在插件配置中添加这些钩子函数,并在相应的钩子函数中编写你想要的逻辑。

到了这里,关于rollup打包js库 占位符替换成文件名和行号输出日志中定位报错位置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • chatGPT问答 之 Webpack 5 多入口打包如何指定打包文件名为规定的文件名

    chatGPT越来越令人惊奇,有一些答案在百度上搜半天却找不到你想要的,但与chatGPT的聊天中就可以非常快的得到你想要的结果,不得不说人工智能很好用下面就是我与chatGPT的聊天内容 在Webpack 5中,可以使用 output.filename 选项来指定多入口打包后的文件名规则。 output.filename 可

    2024年02月02日
    浏览(35)
  • js 通过window.open(url)下载文件,修改文件名

    在页面调用

    2024年02月15日
    浏览(73)
  • js获取文件名或文件后缀名(扩展名)的几种方法

    有时候我们需要通过含有文件名和后缀名的一个字符串中提取出该文件的文件名或文件后缀名(扩展名),可以通过如下几种方式进行截取。 例如文件名为: var fileName=\\\"12345.txt\\\"; 用法参考博文 【js截取字符串subString()方法】 js截取字符串subString()方法_js 如何使用substring()截取字

    2024年04月16日
    浏览(67)
  • js将后端返回的文件流导出为excel,并自定义下载文件名

    一. 需求 后台管理系统,常会出现导出excel表格功能;点击导出按钮,请求后端接口,需要将接口返回的 文件流 导出为excel,实现前端下载excel文件。 但是,返回的数据获取 response 时出现乱码,如图: 二. 实现思路 调用后端下载接口,获取传递过来的二进制数据流 创建 a 标

    2024年02月05日
    浏览(77)
  • Node.js中处理特殊字符的文件名,安全稳妥的方案

    在Node.js中,通过 path 模块提供的 basename 方法,我们可以轻松地从文件路径中提取文件名。然而,这个方法在处理特殊字符时存在一些问题,因为它会对这些字符进行转义,导致在不同操作系统上的兼容性问题。在这篇文章中,我们将介绍一种安全稳妥的方法,结合使用 dir

    2024年02月04日
    浏览(40)
  • WPS的JS宏如何实现全文件路径字符串中截取文件名(excel)

    从全文件路径的字符串中,截取文件名称,例如: 全文件路径字符串为:C:WindowsSystem32driversacpi1.sys 需要截取文件名:acpi1.sys 方法如下: 1、简单的方式:把全文件路径字符串拷贝,放置在Excel表的C列。鼠标点击D列后,输入如下公式: =RIGHT(C2,LEN(C2)-FIND(\\\"@\\\",SUBSTITUTE(C2,\\\"\\\",\\\"

    2024年04月27日
    浏览(42)
  • vue项目中,动态src引入图片,并且js根据文件名后缀,判断文件图片、视频、文档、pdf等类型的方法

    vue根据文件地址,获取后缀,根据后缀判断类型,然后根据类型动态展示不同类型的照片 1、处理后缀,根据后缀判断类型   2、根据返回的结果,直接将文件名命名为返回的结果,比如我有个图片类型的文件,经过上述的方法,返回的是image,那我直接要显示的图片名称就为

    2024年02月06日
    浏览(53)
  • Java下载文件,中文文件名乱码问题解决(文件名包含很多%)

    一般情况下,大家都是这样: 其实乱码就是乱在;filename=\\\" + fileName这里,对文件名的编码设定上。 使用URLEncoder.encode(filepath,\\\"UTF-8\\\")虽然可以解决在提示下载框中正确显示汉字文件名的问题,并且在选择保存,然后打开的情况下,文件名称也可以正确的显示。 但是在提示下载框

    2024年02月12日
    浏览(48)
  • 批量修改文件名-txt_word_ppt批量修改文件名

    word/excel/ppt等等批量修改文件名 批量修改文件名的方法有N多种,我的这种是比较简单的,小白也可以使用 使用windows自带的批处理脚本进行批量重命名 什么类型的文件批量修改原理都一样,这里以txt修改为例 通过py脚本快速创建文件测试,这步是创建100个txt文件,这步不重要,因为我

    2024年01月16日
    浏览(91)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包