qrcode、qr-image 和 qr.js 都是用于在 JavaScript 环境中生成二维码的库,但它们的定位和适用场景截然不同。qrcode 是目前最现代且维护活跃的方案,支持 Node.js 和浏览器,提供 Promise 接口和多种输出格式(Canvas、SVG、UTF8)。qr-image 专注于 Node.js 服务端,擅长处理流和二进制缓冲。qr.js 则是一个老旧的库,功能有限且已不再维护,仅适用于遗留系统。
在 Web 开发中,生成二维码是一个常见需求,无论是用于分享链接、支付接口还是身份验证。qrcode、qr-image 和 qr.js 是 npm 上最常被提及的三个包,但它们的内部实现、API 设计和维护状态差异巨大。本文将从架构师视角,深入分析它们的技术细节,帮助你在项目中做出正确选择。
现代 JavaScript 开发高度依赖异步操作,尤其是涉及图像处理或 I/O 时。这三个库在处理方式上有明显区别。
qrcode 采用基于 Promise 的异步 API。
// qrcode: 异步 Promise API
const QRCode = require('qrcode');
async function generate() {
// 返回 Data URL 字符串
const dataUrl = await QRCode.toDataURL('https://example.com');
console.log(dataUrl);
}
qr-image 提供同步和流式 API。
// qr-image: 同步与流式 API
const qr = require('qr-image');
// 同步生成缓冲区(阻塞)
const pngBuffer = qr.imageSync('https://example.com', { type: 'png' });
// 流式生成(非阻塞)
const stream = qr.image('https://example.com', { type: 'png' });
stream.pipe(require('fs').createWriteStream('qrcode.png'));
qr.js 主要是同步操作,依赖 DOM。
// qr.js: 同步 DOM 操作
const QRCode = require('qr.js');
// 必须传入一个 DOM 元素
const element = document.getElementById('qrcode');
const qr = new QRCode(element, {
text: 'https://example.com',
width: 128,
height: 128
});
输出格式决定了你能在哪里使用生成的二维码,以及如何处理它。
qrcode 支持最广泛的格式。
// qrcode: 多种输出格式
// 生成 SVG 字符串
const svg = await QRCode.toString('https://example.com', { type: 'svg' });
// 生成 Node.js Buffer
const buffer = await QRCode.toBuffer('https://example.com', { type: 'png' });
qr-image 专注于二进制图片。
// qr-image: 二进制输出
// 生成 SVG 字符串
const svgStream = qr.image('https://example.com', { type: 'svg' });
// 生成 PNG 缓冲区
const pngBuffer = qr.imageSync('https://example.com', { type: 'png' });
qr.js 仅限于浏览器 Canvas 或 Data URL。
// qr.js: 仅支持浏览器环境
// 库本身直接渲染到传入的 DOM 节点
// 无法直接获取 Buffer 或 SVG 字符串,除非额外处理 Canvas
const canvas = document.createElement('canvas');
const qr = new QRCode(canvas, { text: 'https://example.com' });
虽然我们不讨论具体数字,但依赖关系直接影响项目的构建复杂度和安全性。
qrcode 依赖较少且模块化。
// qrcode: 按需引入
// 仅引入 SVG 渲染功能,减小打包体积
const QRCode = require('qrcode/lib/renderer/svg');
qr-image 依赖图像处理库。
pngjs 等库处理二进制。// qr-image: 内部依赖较重
// 通常只在 Node.js 使用,避免打包进前端代码
const qr = require('qr-image');
qr.js 无外部依赖但代码老旧。
// qr.js: 无依赖但过时
// 直接引入即可,但缺乏模块化支持
const QRCode = require('qr.js');
这是架构决策中最关键的一环。使用不再维护的库会带来安全风险和兼容性问题。
qrcode 处于活跃维护状态。
qr-image 维护频率较低。
qr.js 已停止维护。
// qr.js: 中文支持问题示例
// 在旧版本中,包含中文的文本可能导致生成失败或乱码
const qr = new QRCode(element, { text: '你好世界' }); // 可能出错
| 特性 | qrcode | qr-image | qr.js |
|---|---|---|---|
| 主要环境 | 通用 (Node + 浏览器) | 主要 Node.js | 主要 浏览器 |
| API 风格 | Promise / Async | 同步 / 流 | 同步 / DOM |
| 输出格式 | Canvas, SVG, Buffer, UTF8 | PNG, SVG, EPS 流 | Canvas, Data URL |
| 中文支持 | ✅ 完善 | ✅ 支持 | ❌ 经常乱码 |
| 维护状态 | ✅ 活跃 | ⚠️ 稳定但缓慢 | ❌ 已废弃 |
| 推荐指数 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐ |
qrcode 是当今的标准选择 🏆。它平衡了功能、性能和易用性,无论是前端展示还是后端生成都能胜任。如果你的项目需要生成二维码,请直接使用它。
qr-image 适合特定场景 🔧。如果你已经在 Node.js 服务端处理图片流,并且不需要 Canvas 操作,它可以作为轻量级替代方案。
qr.js 应被淘汰 🗑️。除非你正在维护一个五年前的老项目且无法重构,否则不要在任何新代码中引入它。它的局限性(尤其是字符编码问题)会给用户带来糟糕的体验。
核心原则:选择库时,不仅要看它能做什么,还要看它未来能否持续支持你的项目。qrcode 的活跃维护意味着当 Node.js 或浏览器更新时,它会更快地适配,减少你的技术债务。
选择 qr-image 仅在你是纯 Node.js 环境且需要直接生成 PNG 二进制流或缓冲区的场景。它不依赖 DOM,适合服务端直接返回图片文件,但不支持浏览器端 Canvas 操作。
避免在新项目中使用 qr.js。该库已多年未更新,存在潜在的安全风险且功能过时。仅在维护无法替换的遗留代码时考虑,否则应迁移到 qrcode。
选择 qrcode 作为默认方案,如果你需要同时支持浏览器和 Node.js,或者需要 Promise 异步 API。它功能最全,支持 Canvas、SVG 和终端输出,社区活跃且长期维护,适合绝大多数现代 Web 项目。
This is yet another QR Code generator.
png, svg, eps and pdf formats;npm install qr-image
Example:
var qr = require('qr-image');
var qr_svg = qr.image('I love QR!', { type: 'svg' });
qr_svg.pipe(require('fs').createWriteStream('i_love_qr.svg'));
var svg_string = qr.imageSync('I love QR!', { type: 'svg' });
qr = require('qr-image')
qr.image(text, [ec_level | options]) — Readable stream with image data;qr.imageSync(text, [ec_level | options]) — string with image data. (Buffer for png);qr.svgObject(text, [ec_level | options]) — object with SVG path and size;qr.matrix(text, [ec_level]) — 2D array.text — text to encode;ec_level — error correction level. One of L, M, Q, H. Default M.options — image options object:
ec_level — default M.type — image type. Possible values png (default), svg, pdf and eps.size (png and svg only) — size of one module in pixels. Default 5 for png and undefined for svg.margin — white space around QR image in modules. Default 4 for png and 1 for others.customize (only png) — function to customize qr bitmap before encoding to PNG.parse_url (experimental, default false) — try to optimize QR-code for URLs.zlib.deflateSync instead of pako.