html-docx-js vs html-to-docx
前端 HTML 转 Word 文档方案选型
html-docx-jshtml-to-docx类似的npm包:

前端 HTML 转 Word 文档方案选型

html-docx-jshtml-to-docx 都是用于在浏览器或 Node.js 环境中将 HTML 内容转换为 Microsoft Word (.docx) 文件的 JavaScript 库。它们允许开发者利用熟悉的 HTML/CSS 技术来生成文档,而无需依赖后端服务。html-docx-js 是早期的经典实现,但目前已停止维护;html-to-docx 是其现代化的社区分支,修复了大量已知问题并增强了对图片、表格及复杂样式的支持,是目前更推荐的生产级选择。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
html-docx-js01,149-8310 年前MIT
html-to-docx04824.8 MB1063 年前MIT

html-docx-js vs html-to-docx: 架构、维护性与渲染能力深度对比

在前端生成 Word 文档的场景中,html-docx-jshtml-to-docx 是最常被提及的两个方案。它们的核心目标一致:将 HTML 字符串打包成符合 Office Open XML 标准的 .docx 文件。然而,由于维护状态和底层实现的差异,它们在实际工程中的表现截然不同。本文将从架构维护、样式渲染、资源处理三个维度进行深度剖析。

🛠️ 维护状态与架构健康度

html-docx-js 是早期的开源实现,曾广泛流行。但根据其仓库记录,该库已多年未进行实质性更新。

  • 社区反馈存在多个未修复的严重 Issue(如图片无法显示、表格边框丢失)。
  • 依赖链陈旧,可能与现代构建工具(如 Webpack 5, Vite)存在兼容性问题。
  • 架构上缺乏模块化设计,扩展困难。
// html-docx-js: 引入方式较旧,通常依赖全局变量或 CommonJS
const htmlDocx = require('html-docx-js');
// 缺乏 TypeScript 定义支持,需手动声明

html-to-docx 是社区基于 html-docx-js 源码 Fork 并重构的版本。

  • 保持活跃更新,及时响应社区报告的 Bug。
  • 提供了更好的 TypeScript 类型定义,便于 IDE 智能提示。
  • 优化了内部 Zip 打包逻辑,生成的文件兼容性更强。
// html-to-docx: 支持现代 ES Module 和 TypeScript
import htmlToDocx from 'html-to-docx';
// 或者 Node.js 环境
const htmlToDocx = require('html-to-docx');

🎨 CSS 样式渲染能力

生成 Word 文档最大的痛点在于 CSS 支持。Word 的渲染引擎与浏览器不同,这两个库都需要将 CSS 转换为 WordML。

html-docx-js 对 CSS 的支持较为基础。

  • 仅支持内联样式(Inline Styles),外部类名经常失效。
  • 复杂选择器(如 :nth-child)通常被忽略。
  • 表格边框渲染经常出错,需要大量 hack 代码。
// html-docx-js: 必须将所有样式写在内联 style 属性中
const html = `
  <table style="border: 1px solid black; border-collapse: collapse;">
    <tr>
      <td style="border: 1px solid black;">Data</td>
    </tr>
  </table>
`;
const blob = htmlDocx.asBlob(html);

html-to-docx 增强了样式解析器。

  • 更好地支持 <style> 标签内的类定义。
  • 对表格边框、单元格内边距(padding)的转换更准确。
  • 减少了生成文档后需要手动调整格式的工作量。
// html-to-docx: 支持 <style> 标签,代码更整洁
const html = `
  <style>
    table { border: 1px solid black; border-collapse: collapse; }
    td { border: 1px solid black; padding: 5px; }
  </style>
  <table>
    <tr><td>Data</td></tr>
  </table>
`;
const buffer = await htmlToDocx(html);

🖼️ 图片与资源处理

在文档中嵌入图片是高频需求,两者的处理机制差异显著。

html-docx-js 处理图片时经常出现问题。

  • 对 Base64 格式图片的支持不稳定,容易生成损坏的文件。
  • 外部图片链接(http/https)通常不被支持,必须转为 Base64。
  • 图片尺寸控制不精确,经常溢出页面边界。
// html-docx-js: 图片容易丢失或损坏,需手动确保 Base64 格式
const html = `
  <img src="data:image/png;base64,iVBORw0KG..." width="200" />
`;
// 风险:生成的 docx 在某些 Word 版本中无法打开图片
const blob = htmlDocx.asBlob(html);

html-to-docx 优化了资源打包流程。

  • 稳定支持 Base64 图片嵌入,自动处理 MIME 类型。
  • 对图片尺寸属性的解析更符合 Word 标准(像素到 Twips 的转换)。
  • 减少了因资源路径问题导致的文档损坏风险。
// html-to-docx: 图片嵌入更可靠,尺寸控制更准
const html = `
  <img src="data:image/png;base64,iVBORw0KG..." style="width:200px;" />
`;
// 生成的文档图片显示正常,且不易损坏
const buffer = await htmlToDocx(html);

📦 输出格式与环境兼容

根据运行环境(浏览器 vs Node.js),返回的数据类型有所不同。

html-docx-js 主要针对浏览器环境设计。

  • 默认返回 Blob 对象,配合 FileSaver.js 下载。
  • 在 Node.js 环境中使用较为繁琐,需额外转换 Buffer。
  • 缺乏对输出选项的精细控制(如页面方向、页边距)。
// html-docx-js: 浏览器端返回 Blob
const blob = htmlDocx.asBlob(htmlContent, {
  orientation: 'landscape' // 支持有限
});
// 需配合 file-saver 使用
saveAs(blob, 'document.docx');

html-to-docx 兼顾了浏览器与 Node.js 环境。

  • Node.js 返回 Buffer,浏览器可配置返回 Blob
  • 支持更丰富的配置项,如页边距、页眉页脚设置。
  • 更适合服务端生成文档后直接存储或发送。
// html-to-docx: Node.js 返回 Buffer,便于直接存储
const buffer = await htmlToDocx(htmlContent, {
  orientation: 'landscape',
  margins: { top: 1440, bottom: 1440 } // 更精细的控制
});
// 可直接写入文件系统
fs.writeFileSync('document.docx', buffer);

🤝 共同点:核心原理

尽管存在差异,两者在底层原理上是相似的:

1. 📄 基于 Office Open XML 标准

  • 两者都不是简单地将 HTML 转为 PDF 再转 Word,而是直接构建 .docx 的 XML 结构。
  • 这意味着生成的文件是真正的 Word 文档,可再次编辑。
// 两者生成的都是标准的 .docx 压缩包结构
// 包含 [Content_Types].xml, word/document.xml 等文件

2. 🔗 依赖 JSZip 进行打包

  • 内部都使用 jszip 库来将 XML 文件和资源打包成最终的二进制文件。
  • 性能瓶颈通常出现在 Zip 压缩阶段,尤其是大图片。
// 内部实现伪代码
const zip = new JSZip();
zip.file('word/document.xml', xmlContent);
const content = await zip.generateAsync({ type: 'blob' });

3. ⚠️ 样式支持均有局限

  • 受限于 Word 对 CSS 的支持程度,两者都无法完美还原复杂的 Web 布局(如 Flexbox, Grid)。
  • 建议使用传统的 Table 布局来确保文档结构稳定。
// 推荐做法:使用 Table 布局而非 Div + Flex
// ❌ 不推荐
<div style="display:flex">...</div>
// ✅ 推荐
<table><tr><td>...</td></tr></table>

📊 核心差异总结

特性html-docx-jshtml-to-docx
维护状态🔴 已停止维护 (Legacy)🟢 活跃维护 (Active)
图片支持⚠️ 不稳定,易损坏✅ 稳定,Base64 支持好
CSS 解析🔴 仅支持内联样式🟡 支持
TypeScript❌ 无官方定义✅ 提供类型定义
Node.js 支持⚠️ 需额外转换✅ 原生支持 Buffer
表格渲染🔴 边框经常丢失🟡 边框支持较好

💡 架构师建议

html-docx-js 属于“历史遗留技术” 🏛️。除非你正在维护一个 5 年前的老项目且无法承担重构成本,否则不应在新代码库中引入它。它的停止维护状态意味着任何新发现的 Bug 都将无法修复,这在生产环境中是不可接受的风险。

html-to-docx 是目前事实上的“标准替代方案” 🛡️。它在保持 API 简洁的同时,解决了原库最致命的稳定性问题。对于需要生成合同、报告或导出功能的 SaaS 应用,它是更安全可靠的选择。

最终建议

  1. 新项目:直接使用 html-to-docx
  2. 老项目迁移:制定计划逐步替换 html-docx-js,重点测试图片渲染和表格样式。
  3. 复杂需求:如果需要对文档格式有像素级控制(如精确打印),建议考虑服务端方案(如 Puppeteer 转 PDF 或 专用 Word 生成库 docx),而非 HTML 转换方案。

如何选择: html-docx-js vs html-to-docx

  • html-docx-js:

    仅建议在维护遗留系统且无法升级依赖时使用。由于该库已多年未更新,存在已知 bug 且不支持现代 CSS 特性,在新项目中引入会导致后续维护成本极高。如果必须使用,请确保测试所有边界情况,并准备好应对图片丢失或样式错乱的风险。

  • html-to-docx:

    强烈推荐用于所有新项目。它 actively 维护,修复了原库的许多核心缺陷,特别是对 Base64 图片和复杂表格边框的支持更好。如果你需要可靠的文档生成能力且希望减少样式调试时间,这是目前的最佳实践选择。

html-docx-js的README

html-docx-js

This is a very small library that is capable of converting HTML documents to DOCX format that is used by Microsoft Word 2007 and onward. It manages to perform the conversion in the browser by using a feature called 'altchunks'. In a nutshell, it allows embedding content in a different markup language. We are using MHT document to ship the embedded content to Word as it allows to handle images. After Word opens such file, it converts the external content to Word Processing ML (this is how the markup language of DOCX files is called) and replaces the reference.

Altchunks were not supported by Microsoft Word for Mac 2008 and are not supported by LibreOffice and Google Docs.

Compatibility

This library should work on any modern browser that supports Blobs (either natively or via Blob.js). It was tested on Google Chrome 36, Safari 7 and Internet Explorer 10.

It also works on Node.js (tested on v0.10.12) using Buffer instead of Blob.

Images Support

This library supports only inlined base64 images (sourced via DATA URI). But it is easy to convert a regular image (sourced from static folder) on the fly. If you need an example of such conversion you can checkout a demo page source (see function convertImagesToBase64).

Usage and demo

Very minimal demo is available as test/sample.html in the repository and online. Please note that saving files on Safari is a little bit convoluted and the only reliable method seems to be falling back to a Flash-based approach (such as Downloadify). Our demo does not include this workaround to keep things simple, so it will not work on Safari at this point of time.

You can also find a sample for using it in Node.js environment here.

To generate DOCX, simply pass a HTML document (as string) to asBlob method to receive Blob (or Buffer) containing the output file.

var converted = htmlDocx.asBlob(content);
saveAs(converted, 'test.docx');

asBlob can take additional options for controlling page setup for the document:

  • orientation: landscape or portrait (default)
  • margins: map of margin sizes (expressed in twentieths of point, see WordprocessingML documentation for details):
    • top: number (default: 1440, i.e. 2.54 cm)
    • right: number (default: 1440)
    • bottom: number (default: 1440)
    • left: number (default: 1440)
    • header: number (default: 720)
    • footer: number (default: 720)
    • gutter: number (default: 0)

For example:

var converted = htmlDocx.asBlob(content, {orientation: 'landscape', margins: {top: 720}});
saveAs(converted, 'test.docx');

IMPORTANT: please pass a complete, valid HTML (including DOCTYPE, html and body tags). This may be less convenient, but gives you possibility of including CSS rules in style tags.

html-docx-js is distributed as 'standalone' Browserify module (UMD). You can require it as html-docx. If no module loader is available, it will register itself as window.htmlDocx. See test/sample.html for details.

License

Copyright (c) 2015 Evidence Prime, Inc. See the LICENSE file for license rights and limitations (MIT).