终端中打印的五颜六色的彩色文本,你知道是怎么实现的吗,你都知道或用过哪些相关的工具库呢?来一起了解一下吧!
在前端项目开发中,说到控制台终端彩色文本格式化,你可能会想到 chalk
、picocolors
、ansi-colors
甚至是 colors.js
等流行工具库。它们在 npmjs
上的周下载量都分别长期保持在千万到亿级别。彩色文本格式化是 CLI 类前端开发工具中必备的基础功能需求,然而其实现方式其实是非常简单的。
作为前端开发工具链中不可或缺的基础模块,此类工具库的实现原理与性能一直受到开发者社区的高度关注。如早期高度流行的 colors.js
多年来仍一直被广泛应用,但不少人对其扩展 String
原型链的实现方式颇有微词。后来居上的 chalk
库,也会因为其间接依赖稍多、复杂度稍高而时常受到吐槽,于是接着出现了以超轻量、无依赖、跑分高著称的 ansi-colors
、 picocolors
、 kleur
等同类库。以至于 chalk 5
甚至将分离出去的两个功能相对独立的依赖库又进行了内置以实现零依赖、对主要功能实现逻辑重构以取得更高的跑分。
可以看到,作为基础类核心工具库,其在实现方式、执行性能等方面,如同安卓手机界堆硬件一般的内卷。基础工具卷实现与性能,受益的是所有开发者。换个角度来说,实现同样的能力CPU转的少了一些,在普遍应用海量累加的结果下,或许也能间接的节省不少电能消耗呢。
扯远了。铺垫了这么多,只是为了下面要介绍的内容和更高的跑分做个背景预热。
1 字符串拼接实现终端打印彩色文本样式
几年前在开发一个微型 CLI 工具时,希望打印彩色的字符串,但又觉得仅打印一两行信息,不值得多引入一个依赖库(甚至间接依赖近N个库)。
当时这方面流行的开源库主要有 colors.js
和 chalk
。在翻了一下 colors.js
的源码后,发现终端彩色字符的格式化实际上非常简单,简单的按字符串规则拼接即可。参考如下示例:
console.log(`\x1B[31m我有低保,交朋友吗?\x1B[39m`);
console.log(`\x1B[32m绿码,放心通过!\x1B[39m`);
console.log(`\x1B[32m\x1B[4m星星睡不着的时候,是不是也在数人类。\x1B[24m\x1B[39m`);
字符串拼接的方式很简洁的解决了当时的需求,令我很满意。如果你在开发的 CLI 类工具,此类需求简单、且希望拥有较好的启动加载速度,也可以选择这么做。
如果你想了解终端中颜色控制指令相关的内容,可参考阅读:终端中的彩色文本控制指令的格式构成简介
2 clc
: 设计一个极简的自用工具库
后来我又涉及一些其它 CLI 工具的开发,对控制台打印彩色文本的使用逐渐增多。
字符串拼接方式简单、零依赖,可以获得较好的启动加载性能,但当高频重度应用时则显得过于繁琐。于是参考 colors.js
的 styles 列表 写了一个极简单的工具方法,大致如下:
var isDisabled = false;
// 定义 ansi-colors 支持的颜色列表
var colorList = {// colorblack: [30, 39],red: [31, 39],green: [32, 39],yellow: [33, 39],blue: [34, 39],magenta: [35, 39],cyan: [36, 39],white: [37, 39],gray: [90, 39],// more...
};
function enable() { isDisabled = false; }
function disable() { isDisabled = true; }
// 定义一个 color 格式化方法
function color(str, colorType) {if (str === '' || str == null) return '';if (isDisabled) return String(str);var typecfg = colorList[colorType];return typecfg ? '\x1b[' + typecfg[0] + 'm' + str + '\x1b[' + typecfg[1] + 'm' : str;
}
// 使用 color 方法
console.log(color('ERROR', 'red'), `接口[${color('/xxx', 'cyan')}]调用异常!`);
可以看到,其在实现与使用上都是超级简单的。在后续高频使用过程中,发现调用 color
方法的方式也稍显繁琐,于是又继续做了一些扩展:
function log(str, colorType) {console.log(color(str, colorType));
}
Object.keys(colorList).forEach(function (key) {color[key] = function (str) { return color(str, key); };log[key] = function () {var arr = [];for (var i = 0; i < arguments.length; i++) arr.p