tesseract.js 本地部署指南:workerPath、langPath、corePath 三路径加载机制详解
tesseract.js 在浏览器端采用"API 层 + Web Worker + 远程 WASM 核心"的分层加载架构,语言数据与 tesseract.js-core 默认从 CDN 拉取。对于有内网隔离、离线运行或资源统一管控需求的团队,必须通过 workerPath、langPath、corePath 三个参数把全部资源切换到本地。本文基于官方文档 local-installation.md 并结合当前仓库源码(v7.0.0),完整讲清每个参数的默认值、取值规则、URL 拼接公式以及源码中的实际加载逻辑,帮助你把 tesseract.js 完整落地到本地环境。
浏览器端的资源加载架构:为什么需要"本地化"
官方文档对浏览器环境下的架构描述是:tesseract.js 本体只提供 API 层,内部会打开一个 WebWorker 处理请求;这个 worker 再从 CDN 加载由 Emscripten 编译的 tesseract.js-core(WASM 运行时),随后动态加载托管在另一个 CDN 上的语言数据文件。
从源码结构可以印证这一调用链:
- src/worker/browser/index.js 是浏览器端
createWorker的入口,它读取 src/worker/browser/defaultOptions.js 中的默认配置,其中workerPath默认值为`https://cdn.jsdelivr.net/npm/tesseract.js@v${version}/dist/worker.min.js`(version取自 package.json 的version字段,当前仓库为7.0.0)。 - src/worker/browser/spawnWorker.js 负责实际创建 Worker:默认
workerBlobURL为true(见 src/constants/defaultOptions.js),它会构造一个包含importScripts("<workerPath>")的 Blob 脚本,再通过new Worker(URL.createObjectURL(blob))启动。这意味着 worker 脚本的实际下载地址由workerPath决定,Blob URL 只是一种同域规避手段——这也是"本地化"必须替换workerPath的原因。 - Worker 内部逻辑位于 src/worker-script/browser/index.js,它向通用调度器注册了
getCore(加载 WASM 核心)、gunzip(解压语言包)和基于 IndexedDB 的缓存适配器(src/worker-script/browser/cache.js 使用idb-keyval读写缓存)。
理解了这条链路,就能明白官方文档给出的建议:如果不需要完全离线,直接让 tesseract.js 走 CDN 最省心;但如果你必须把所有文件放在本地,就需要向 createWorker 传入自定义的 workerPath、langPath、corePath。
三个本地化参数与完整调用示例
官方文档给出的标准调用方式是(示例 URL 为 v5.0.0,实际使用时请替换为你当前安装的版本,本仓库为 v7.0.0):
const worker = await createWorker('eng', 1, {
workerPath: 'https://cdn.jsdelivr.net/npm/tesseract.js@v5.0.0/dist/worker.min.js',
langPath: 'https://tessdata.projectnaptha.com/4.0.0',
corePath: 'https://cdn.jsdelivr.net/npm/tesseract.js-core@v5.0.0',
});
三个参数的语义(继承自 local-installation.md):
| 参数 | 语义 | 典型本地取值 |
|---|---|---|
workerPath |
worker.js 文件的位置 |
你本地静态服务器上的 worker 脚本 URL |
langPath |
tesseract 语言文件(traineddata)的位置 | 本地托管的语言数据目录 URL |
corePath |
tesseract.js-core(WASM 核心)文件的位置 | 本地托管的核心文件目录 URL |
需要说明的是,这三个参数在 worker 真正读取之前会先经过 src/utils/resolvePaths.js 的统一处理:浏览器环境下会用 new URL(s, window.location.href) 把相对路径解析为基于当前页面地址的绝对 URL;Node.js 环境下则原样透传(允许本地文件路径)。这解释了为什么浏览器端本地部署时,workerPath/corePath/langPath 既可以写绝对 URL,也可以写相对当前页面的相对路径,而 Node.js 端还能直接写文件系统路径。
更完整的用法示例可参考 examples/node/recognize.js、examples/browser/basic-efficient.html 以及 docs/examples.md。
workerPath:worker 脚本从哪里加载
workerPath 指定 worker 脚本的位置。浏览器端的默认值来自 src/worker/browser/defaultOptions.js:
const defaultOptions = {
...defaultOptions,
workerPath: `https://cdn.jsdelivr.net/npm/tesseract.js@v${version}/dist/worker.min.js`,
};
即默认加载 jsDelivr 上与主包同版本的 dist/worker.min.js。本地部署时,把 workerPath 指向你自己服务器上的 worker 脚本即可。结合 spawnWorker 的 Blob 包装逻辑(默认 workerBlobURL: true),你不需要自己构造 Blob——库会自动对 workerPath 生成 importScripts 包装脚本。
langPath:语言文件的 URL 计算公式
langPath 指定 tesseract 语言文件的位置,语言文件 URL 按如下公式计算:
langPath + langCode + '.traineddata.gz'
如果用户没有指定 langPath,语言数据会自动从 jsDelivr CDN 下载。源码 src/worker-script/index.js(约 L122-L150)中可以看到这条加载逻辑的实际实现:
// If `langPath` if not explicitly set by the user, the jsdelivr CDN is used.
const langPathDownload = langPath || (lstmOnly
? `https://cdn.jsdelivr.net/npm/@tesseract.js-data/${lang}/4.0.0_best_int`
: `https://cdn.jsdelivr.net/npm/@tesseract.js-data/${lang}/4.0.0`);
从这段代码可以补充两点官方文档未展开的实现细节:
- 默认 CDN 的实际形态:未设置
langPath时,默认语言数据来自 jsDelivr 上的@tesseract.js-data/<lang>/4.0.0npm 包目录,lstmOnly模式(createWorker第二个参数为 1 以上时)则使用4.0.0_best_int变体; - Node.js 支持本地目录路径:源码中
langPath既可以是 URL,也可以是 Node.js 下的本地文件路径(通过isURL判断后分别走网络请求或本地文件系统读取),加载顺序为langPath/<lang>.traineddata(.gz),并支持先查缓存(readCache)。这意味着 Node.js 环境下的"全本地化"可以直接把langPath指向一个放好.traineddata.gz文件的本地目录,无需起静态服务器;而浏览器端则必须提供可访问的 URL。
本地部署实践上,langPath 目录里应包含你所用每种语言的 <langCode>.traineddata.gz 文件(如 eng.traineddata.gz),语言代码列表见 src/constants/languages.js 与 docs/tesseract_lang_list.md。
corePath:WASM 核心目录与 4 个必备文件
corePath 指定 tesseract.js-core 文件的位置,官方文档给出的默认值为 https://cdn.jsdelivr.net/npm/tesseract.js-core@v5.0.0(当前仓库源码中该默认值由 src/worker-script/browser/getCore.js 动态构造:https://cdn.jsdelivr.net/npm/tesseract.js-core@v${coreVersion},其中 coreVersion 取自 package.json 的 dependencies['tesseract.js-core'],当前为 ^7.0.0,即默认加载 v7.0.0)。
官方文档要求:设置 corePath 时,必须指向一个包含全部 4 个以下文件的目录:
tesseract-core.wasm.jstesseract-core-simd.wasm.jstesseract-core-lstm.wasm.jstesseract-core-simd-lstm.wasm.js
tesseract.js 会根据用户设备的硬件能力与 createWorker 的选项自动挑选正确的文件。从源码 src/worker-script/browser/getCore.js 可以看到完整的挑选逻辑:先通过 wasm-feature-detect 探测 simd 与 relaxedSimd 支持,再结合 lstmOnly 标志,在 4 种组合中取交集命名(relaxedsimd / simd / 空 前缀 × lstm / 空 后缀)。需要指出的是,文档中列出的"4 个文件"是 v5 时代的清单;从当前源码看,corePath 目录若同时提供 tesseract-core-relaxedsimd.wasm.js 与 tesseract-core-relaxedsimd-lstm.wasm.js 两个 relaxedSimd 变体,在支持该指令集的浏览器上会被优先选用,因此本地部署时建议把核心包目录内的文件完整拷贝,不要只挑 4 个。
指向单个 .js 文件的兼容性行为
getCore.js 中还有一段重要的向后兼容逻辑:
// If a user specifies a specific JavaScript file, load that file.
if (corePathImport.slice(-2) === 'js') {
corePathImportFile = corePathImport;
}
即当 corePath 被设置为一个具体的 .js 文件(而非目录)时,库会无条件加载该文件,不再根据设备是否支持 SIMD 做选择。官方文档明确说明:这一行为仅为不破坏旧代码而保留,强烈不建议这样使用——指定 tesseract-core.wasm.js 会导致在支持 SIMD 的设备上性能大幅下降;指定 tesseract-core-simd.wasm.js 则可能在不支持 SIMD 的设备上直接运行失败。
此外,源码还保留了对 tesseract.js-core 4.0.3 及更早版本的兼容:若加载后全局变量挂在 TesseractCoreWASM 而非 TesseractCore 上,会自动做别名映射,否则抛出 Failed to load TesseractCore 错误。本地部署时若核心文件加载 404,通常表现为这一错误,优先检查 corePath 指向的目录是否 4 个文件齐全。
Node.js 环境:为什么只需要关心 langPath
官方文档指出:在 Node.js 环境中,你可能唯一需要自定义的路径是 languages/langPath。从源码看这一结论有明确依据:
- src/worker/node/defaultOptions.js 中 Node 端的默认
workerPath为path.join(__dirname, '..', '..', 'worker-script', 'node', 'index.js'),即直接指向 npm 包内的本地 worker 脚本,不经过任何网络请求; - WASM 核心在 Node 端由 src/worker-script/node/getCore.js 处理,同样从本地
tesseract.js-core依赖中加载; - src/worker/node/spawnWorker.js 使用 Node 原生
worker_threads的new Worker(workerPath)启动,workerPath是文件系统路径。
因此在 Node.js 端做本地化时,只需把 langPath 指向你本地的语言数据目录(文件或目录均可,见上文 src/worker-script/index.js 的加载逻辑),workerPath 与 corePath 一般保持默认即可。语言文件下载与缓存行为可结合 tests/ 下的 recognize.test.mjs、detect.test.mjs 了解测试中如何验证识别链路。
本地部署检查清单
综合官方文档与源码实现,把 tesseract.js 全量切到本地资源时,可按以下清单逐项核对:
- workerPath:指向你的静态服务器上与主包同版本的 worker 脚本(浏览器端默认走 jsDelivr,见 src/worker/browser/defaultOptions.js);
- langPath:目录内含各语言的
<lang>.traineddata.gz,URL 按langPath + langCode + '.traineddata.gz'拼接;Node.js 端可直接使用本地目录路径,且未设置时默认回落到 jsDelivr 的@tesseract.js-data包; - corePath:指向目录(而非单个
.js文件),目录内 4 个核心文件齐全(源码还支持 2 个 relaxedSimd 变体,建议一并拷贝);版本与主包保持一致(当前仓库为 v7.0.0,文档示例中的 v5.0.0 仅示意); - 版本一致性:三个资源都带版本号,替换 URL 时务必与 package.json 中声明的
tesseract.js-core依赖版本对齐,避免 WASM 接口不匹配。
按照以上方式配置后,tesseract.js 在浏览器与 Node.js 中都可以完全脱离公共 CDN 运行,语言数据、WASM 核心与 worker 脚本均由你自己的服务器提供,满足内网部署与离线场景的要求。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00