ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

拆解crypto-hash源码:同构设计如何让Node.js与浏览器共享同一套哈希API

拆解crypto-hash源码:同构设计如何让Node.js与浏览器共享同一套哈希API 拆解crypto-hash源码同构设计如何让Node.js与浏览器共享同一套哈希API【免费下载链接】crypto-hashTiny hashing module that uses the native crypto API in Node.js and the browser项目地址: https://gitcode.com/gh_mirrors/cr/crypto-hashcrypto-hash 是一款体积极小的同构哈希库它让 Node.js 与浏览器共享同一套 sha1 / sha256 / sha384 / sha512 哈希 API底层分别调用node:crypto和浏览器的 Web Crypto代码全部基于原生 crypto 能力浏览器端压缩后仅约 300 字节。如果你曾在项目中同时需要给文件、内容做哈希校验肯定遇到过这样的尴尬Node.js 里写得好好的crypto.createHash(sha256)拿到浏览器里完全跑不起来而浏览器的crypto.subtle.digest又是异步的、算法名还不一样。crypto-hash 用不到 100 行代码就抹平了这些差异。这篇文章带你完整拆解它的同构设计思路。项目作者 Sindre Sorhus 在 readme.md 里有一句自嘲Useful when you want the same hashing API in all environments. My cat calls itisomorphic.在所有环境使用同一套哈希 API我的猫管这叫同构同构哈希为什么是刚需一套 API 打通两端 做内容校验、缓存键生成、文件去重时哈希是绕不开的操作。但两端原生 API 差异不小维度Node.js浏览器入口node:crypto的createHashwindow.crypto.subtle.digest执行方式同步异步Promise算法名sha256SHA-256输入类型Buffer / stringArrayBuffer / ArrayBufferView同构库的价值就在于业务代码只需await sha256(input)完全不关心运行在哪一端。三步上手最快体验 crypto-hash先克隆源码仓库仓库地址https://gitcode.com/gh_mirrors/cr/crypto-hash或在任意项目中安装npm install crypto-hash最小用法如下import {sha256} from crypto-hash; console.log(await sha256()); // 36bf255468003165652fe978eaaa8898e191664028475f83f506dabd95298efc四个函数sha1、sha256、sha384、sha512签名完全一致都接受string、ArrayBuffer或ArrayBufferView返回 Hex 编码字符串传入{outputFormat: buffer}则可拿到ArrayBuffer。项目结构总览5 个源文件讲完全部故事crypto-hash 是一个典型的小即是美项目package.json 的files字段声明了发布的全部内容index.js —— Node.js 端实现含 worker 线程调度browser.js —— 浏览器端实现仅 16 行thread.js —— worker 线程中的哈希执行体仅 9 行utilities.js —— 共用的 Hex 转换工具仅 10 行index.d.ts —— TypeScript 类型定义exports 字段同构分流的第一道开关真正的同构魔术藏在 package.json 的exports里exports: { types: ./index.d.ts, node: ./index.js, default: ./browser.js }Node.js 的模块解析器命中node条件加载 index.jsVite、Webpack 等打包器面向浏览器构建时走default分支加载 browser.js。业务代码里始终是import {sha256} from crypto-hash分流完全由工具链自动完成——这是现代 Node 生态实现同构最优雅的方式不需要任何运行时判断。Node.js 端拆解把哈希丢进 worker 线程 打开 index.js代码分为两层一个兜底实现和一个线程实现。兜底实现第 5–14 行直接用crypto.createHash(algorithm)同步计算。它服务于Worker undefined的极端环境比如某些受限沙箱保证功能永不缺席。线程实现第 16–61 行才是重头戏。为什么要在 Node 端开线程因为同步哈希会阻塞事件循环大文件场景下尤其致命。作者的做法相当精巧懒加载 Workerworker变量初始为undefined第一次调用时才new Worker(threadFilePath)创建线程不哈希就零开销。任务 ID 匹配taskIdCounter自增生成分配 ID存入tasksMapworker 回消息时按id取出对应的resolve完成 Promise。ref/unref 管理生命周期发消息前worker.ref()当tasks.size 0时worker.unref()——线程不会阻止进程退出用完自动离场。零拷贝传输worker.postMessage({id, value}, [buffer])的第二个参数是 transfer listBuffer 的所有权直接移交线程大文件无需复制一份。thread.js 作为线程另一端短到可以整段看接收{id, value}hash.update后把结果连同id发回主线程同样用了 transfer list 避免复制。浏览器端拆解16 行实现 Web Crypto 封装 utilities.js 与 browser.js 加起来不到 30 行。browser.js 的完整逻辑是输入若是字符串用TextEncoder转成字节序列Web Crypto 只收二进制调用globalThis.crypto.subtle.digest(algorithm, buffer)得到摘要按outputFormat返回 Hex 字符串或ArrayBuffer。注意一个细节浏览器端算法名写的是SHA-256而非sha256——Web Crypto 规范要求带连字符的大写格式。这层差异被create(algorithm)工厂函数吸收掉了外部 API 对两端完全一致。⚠️ 使用须知crypto.subtle只在安全上下文HTTPS 或 localhost中可用且该项目面向现代浏览器不支持 IE。共用工具与类型、测试小而完整的工程闭环bufferToHex一个性能导向的小函数utilities.js 里的bufferToHex是两端共用的唯一工具。它没有逐字节拼接而是通过DataView.getUint32每次取 4 个字节转成 16 进制再padStart(8, 0)——循环次数直接降到 1/4是典型的用对 API 就快了的写法。类型与测试的完整覆盖index.d.ts对每个shaXxx函数都写了两个重载——outputFormat: hex返回PromisestringoutputFormat: buffer返回PromiseArrayBuffer类型与运行时行为严格对应。test.jsNode 端用独立实现 hash.js 交叉验证四种算法还专门测试了 ArrayBuffer 输入、buffer 输出格式以及 10 个 sha512 任务并行执行时结果全部正确——这恰好验证了 worker 线程调度的可靠性。test-browser.js 与 index.test-d.ts分别负责浏览器端karma和类型断言tsd测试测试命令直接写在 package.json 的test脚本里。总结从 crypto-hash 学到的 3 个同构设计套路条件 exports 优先于运行时判断靠打包器和 Node 的exports字段分流比typeof window ! undefined更干净还能让 Tree-shaking 真正生效项目也声明了sideEffects: false。为环境差异留兜底worker 不可用时退回同步实现而不是直接抛错——优雅降级是小库的大智慧。异步是统一 API 的最低公分母两端都用Promise返回业务层写法天然一致这是同构能成立的关键一步。整个库源码不足 100 行却完整体现了跨平台库的分流、调度、降级、类型与测试设计。下次你需要在 Node.js 与浏览器间共享哈希逻辑时crypto-hash 就是一个可以直接拿来用、也值得照着学的范例。【免费下载链接】crypto-hashTiny hashing module that uses the native crypto API in Node.js and the browser项目地址: https://gitcode.com/gh_mirrors/cr/crypto-hash创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表