惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
P
Palo Alto Networks Blog
C
Cisco Blogs
The Hacker News
The Hacker News
T
Threatpost
S
Schneier on Security
K
Kaspersky official blog
Spread Privacy
Spread Privacy
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
NISL@THU
NISL@THU
量子位
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
Security Latest
Security Latest
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
博客园 - 叶小钗
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
News and Events Feed by Topic
爱范儿
爱范儿
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
Project Zero
Project Zero
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
GbyAI
GbyAI
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
T
Tenable Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Vulnerabilities – Threatpost
Forbes - Security
Forbes - Security
博客园 - 三生石上(FineUI控件)
C
Cyber Attacks, Cyber Crime and Cyber Security
N
News and Events Feed by Topic
V
V2EX
Webroot Blog
Webroot Blog
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Blog — PlanetScale
Blog — PlanetScale
M
MIT News - Artificial intelligence
Scott Helme
Scott Helme
Simon Willison's Weblog
Simon Willison's Weblog
L
LangChain Blog
W
WeLiveSecurity
Cloudbric
Cloudbric

博客园 - 冯叶青

OpenAI vs Anthropic API 对比:响应体、请求体、消息格式与工具调用 GitHub Actions 自动部署流程 Git分支自动合并脚本:基于时间戳的冲突解决方案 Next.js lingui.js 多语言自动提取翻译键 - ats-node React实现短信验证码输入组件 Next.js 中优雅地使用 Lottie 动画 Next.js 路由参数更新最佳实践:从 replaceState 到 nextReplaceState Jenkins构建时SWR模块导入报错解决方案 git 提交 实现大图自动压缩功能 React lingui.js 多语言自动提取翻译键 - ast node html2canvas 解决截图空白问题 react 实现前端发版监测 JS根据文件名获取文件类型 JS获取本机IP地址 适用于react、vue菜单格式化工具函数 git 内容提交 实现大图拦截功能 JS实现视频截图 next.js 利用中间件(middleware.ts)实现PC与移动路由无缝切换 Android生成签名文件及对apk进行签名 JS-SDK 配置,实现微信分享功能
解决 Jenkins 环境下 Lingui 构建报错 "btoa is not defined"
冯叶青 · 2025-01-21 · via 博客园 - 冯叶青

问题描述

在 Jenkins CI 环境中构建 React 项目时,遇到了以下错误:

Error: btoa is not defined
  11 | };
  12 | const QkImagePreview = (props: QkImagePreviewType) => {
> 13 |   const { i18n, t } = useLingui();
     |                       ^^^^^^^^^^^
  14 |   const [visible, setVisible] = useState(false);

这个错误发生在使用 @lingui/macro 进行国际化构建时。有趣的是,这个错误只在 Jenkins 环境中出现,在本地 Windows 环境中构建是正常的。

原因分析

  • btoa 函数是浏览器原生提供的 API,用于将二进制字符串转换为 Base64 编码
  • 在 Node.js 环境中,btoa 函数默认是不存在的
  • Lingui 在构建过程中需要使用 btoa 来生成消息 ID
  • Jenkins 使用 Node.js 环境进行构建,所以缺少这个函数

解决方案

1. 创建 Polyfill 文件

创建 src/utils/btoa-polyfill.ts:

// btoa polyfill for Node.js
if (typeof btoa === 'undefined') {
  global.btoa = function (str: string) {
    return Buffer.from(str, 'binary').toString('base64');
  };
}

export {};

2. 在 Vite 配置中引入 Polyfill

修改 vite.config.ts:

import { defineConfig, loadEnv } from 'vite';
// ... 其他导入
import './src/utils/btoa-polyfill';

export default defineConfig(({ mode }) => {
  // ... 配置内容
});

技术要点

  • 这是一个典型的环境差异导致的问题 - 浏览器环境 vs Node.js 环境
  • Polyfill 的实现利用了 Node.js 的 Buffer API 来模拟浏览器的 btoa 功能
  • 在 Vite 配置文件中导入 polyfill 确保它在构建过程的早期被加载

注意事项

1. 这个 polyfill 只在构建时需要,不会影响到生产环境的代码

2. 该解决方案适用于所有使用 Lingui + Vite 的项目在 Node.js 环境下的构建

3. 如果使用其他构建工具(如 webpack),可能需要调整 polyfill 的引入方式

相关依赖版本

{
  "@lingui/core": "^5.1.0",
  "@lingui/macro": "^5.1.0",
  "@lingui/react": "^5.1.0",
  "vite": "^4.3.9"
}