基于React JS PWA集成Google Cloud Vision时遇类型错误求助
解决React PWA集成Google Cloud Vision时的"Class extends value undefined"错误
问题描述
在构建集成Google Cloud Vision的React PWA时,出现以下错误:
get @ @google-cloud_vision.js?t=1718885447253&v=dfd5bd38:24811 Show 1 more frame Show less @google-cloud_vision.js?t=1718885447253&v=dfd5bd38:24910 Uncaught TypeError: Class extends value undefined is not a constructor or null at node_modules/google-auth-library/build/src/auth/authclient.js (@google-cloud_vision.js?t=1718885447253&v=dfd5bd38:24910:45) at __require2 (chunk-WGAPYIUP.js?v=dfd5bd38:19:50) at node_modules/google-auth-library/build/src/auth/oauth2client.js (@google-cloud_vision.js?t=1718885447253&v=dfd5bd38:25051:24) at __require2 (chunk-WGAPYIUP.js?v=dfd5bd38:19:50) at node_modules/google-auth-library/build/src/auth/computeclient.js (@google-cloud_vision.js?t=1718885447253&v=dfd5bd38:25700:26) at __require2 (chunk-WGAPYIUP.js?v=dfd5bd38:19:50) at node_modules/google-auth-library/build/src/auth/googleauth.js (@google-cloud_vision.js?t=1718885447253&v=dfd5bd38:29193:27) at __require2 (chunk-WGAPYIUP.js?v=dfd5bd38:19:50) at node_modules/google-auth-library/build/src/index.js (@google-cloud_vision.js?t=1718885447253&v=dfd5bd38:30145:24)
对应的代码如下:
import React, { useState } from 'react'; import vision from '@google-cloud/vision' const Scan = () => { const [imageFile, setImageFile] = useState(null); const [text, setText] = useState(''); const keyFilename = '../../../../CloudVision.json'; const handleImageChange = (event) => { const newImageFile = event.target.files[0]; setImageFile(newImageFile); }; const detectText = async () => { if (!imageFile) { return; } try { const client = new vision.ImageAnnotatorClient({ keyFilename, }); const [result] = await client.textDetection(imageFile); const fullTextAnnotation = result.fullTextAnnotation; setText(fullTextAnnotation.text); } catch (error) { console.error('Error:', error); // Handle errors appropriately (e.g., display an error message) } }; return ( <div id='Scan'> <input type="file" accept="image/*" onChange={handleImageChange} /> <button onClick={detectText}>Detect Text</button> {text && <p>Extracted Text: {text}</p>} </div> ); }; export default Scan;
错误原因
@google-cloud/vision是服务器端SDK,依赖Node.js核心模块(如fs、path),无法直接在浏览器环境(React PWA属于前端环境)中运行。此外,直接在前端暴露服务账号密钥(keyFilename)会导致密钥泄露,存在严重安全风险。前端环境缺少SDK依赖的Node.js模块,导致类继承时找不到对应的构造函数,从而抛出Class extends value undefined错误。
解决方案
方案1:搭建后端代理服务(推荐)
通过后端服务调用Google Cloud Vision API,前端仅负责上传图片和接收结果,避免密钥暴露和环境不兼容问题。
后端代码(Node.js + Express)
const express = require('express'); const multer = require('multer'); const vision = require('@google-cloud/vision'); const app = express(); const upload = multer({ storage: multer.memoryStorage() }); // 后端安全存放服务账号密钥 const client = new vision.ImageAnnotatorClient({ keyFilename: './CloudVision.json' }); // 定义文本检测接口 app.post('/detect-text', upload.single('image'), async (req, res) => { try { const [result] = await client.textDetection(req.file.buffer); const text = result.fullTextAnnotation?.text || ''; res.json({ text }); } catch (err) { res.status(500).json({ error: err.message }); } }); app.listen(3001, () => console.log('Server running on port 3001'));
前端修改后的代码
import React, { useState } from 'react'; const Scan = () => { const [imageFile, setImageFile] = useState(null); const [text, setText] = useState(''); const handleImageChange = (event) => { const newImageFile = event.target.files[0]; setImageFile(newImageFile); }; const detectText = async () => { if (!imageFile) return; const formData = new FormData(); formData.append('image', imageFile); try { const response = await fetch('http://localhost:3001/detect-text', { method: 'POST', body: formData }); const data = await response.json(); setText(data.text); } catch (error) { console.error('Error:', error); } }; return ( <div id='Scan'> <input type="file" accept="image/*" onChange={handleImageChange} /> <button onClick={detectText}>Detect Text</button> {text && <p>Extracted Text: {text}</p>} </div> ); }; export default Scan;
方案2:直接调用Google Cloud Vision REST API
如果不想搭建后端,可以使用API密钥调用官方REST接口,但需注意限制API密钥的使用范围,避免被滥用。
前端修改后的代码
import React, { useState } from 'react'; const Scan = () => { const [imageFile, setImageFile] = useState(null); const [text, setText] = useState(''); // 在Google Cloud控制台创建API密钥,并限制调用来源(如指定你的域名) const API_KEY = '你的API密钥'; const handleImageChange = (event) => { const newImageFile = event.target.files[0]; setImageFile(newImageFile); }; const detectText = async () => { if (!imageFile) return; const reader = new FileReader(); reader.onload = async (e) => { const base64Image = e.target.result.split(',')[1]; // 提取图片的base64编码部分 try { const response = await fetch(`https://vision.googleapis.com/v1/images:annotate?key=${API_KEY}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ requests: [ { image: { content: base64Image }, features: [{ type: 'TEXT_DETECTION' }] } ] }) }); const data = await response.json(); const fullTextAnnotation = data.responses[0]?.fullTextAnnotation; setText(fullTextAnnotation?.text || ''); } catch (error) { console.error('Error:', error); } }; reader.readAsDataURL(imageFile); }; return ( <div id='Scan'> <input type="file" accept="image/*" onChange={handleImageChange} /> <button onClick={detectText}>Detect Text</button> {text && <p>Extracted Text: {text}</p>} </div> ); }; export default Scan;
内容的提问来源于stack exchange,提问作者Darryl Mbae
相关产品推荐
相关产品推荐

