NextJS中getServerSideProps查询MongoDB时如何解决图片取色CORS报错
问题本质
你遇到的CORS报错和getServerSideProps没有任何关联:
浏览器仅限制客户端JS读取跨域资源的像素数据,img标签渲染图片不受CORS限制,提取图片主色需要读取像素点因此触发了跨域校验。
你之前的逻辑中getServerSideProps仅返回图片URL字符串,客户端运行的JS主动请求第三方图片资源时才触发了跨域拦截。
最优解决方案:服务端预计算主色
直接在getServerSideProps的Node.js环境中完成主色提取,Node环境无CORS限制,还能减少客户端计算开销:
- 安装Node版的fast-average-color依赖:
npm install fast-average-color-node - 修改
getServerSideProps逻辑,计算主色后一同返回给前端:
import FastAverageColor from 'fast-average-color-node' export const getServerSideProps = async () => { const pipeline = [...] const postdata = await db.collection('posts').aggregate(pipeline).toArray(); // 遍历所有帖子预计算主色 for (const post of postdata) { if (post.imgSrc) { try { const color = await FastAverageColor.getColor(post.imgSrc) // 把主色挂载到帖子数据上返回 post.mainColor = color.hex } catch (err) { // 计算失败给默认兜底色 post.mainColor = '#f5f5f5' } } } return { props: { postdata: JSON.parse(JSON.stringify(postdata)), }, }; }
- 前端直接使用返回的
mainColor字段即可,删除客户端提取主色的逻辑。
备选方案1:客户端处理(需要可配置图片存储的CORS规则)
如果一定要在客户端计算主色,按以下步骤操作:
- 到你存储图片的服务商后台(OSS、云存储等)配置CORS规则,允许你的站点域名发起跨域请求,开放GET方法
- 页面中渲染图片的img标签添加
crossOrigin="anonymous"属性 - 修改客户端提取主色的代码,添加跨域配置:
useEffect(() => { fac.getColorAsync(imgSrc, { crossOrigin: 'anonymous' }) .then(color => { console.log('average color: ',color) }) .catch(e => { console.log(e); }); },[])
备选方案2:API路由代理(无法配置图片存储CORS时使用)
新增NextJS API路由做图片代理,客户端请求同域的代理接口转发图片资源,规避跨域限制:
- 新建
pages/api/proxy-image.js文件:
export default async function handler(req, res) { const { url } = req.query try { const response = await fetch(decodeURIComponent(url)) const buffer = await response.arrayBuffer() // 透传图片响应头 res.setHeader('Content-Type', response.headers.get('Content-Type')) res.setHeader('Cache-Control', 'public, max-age=31536000, immutable') res.send(Buffer.from(buffer)) } catch (err) { res.status(404).send('图片加载失败') } }
- 客户端提取主色时使用代理地址:
const proxySrc = `/api/proxy-image?url=${encodeURIComponent(imgSrc)}` fac.getColorAsync(proxySrc)
内容的提问来源于stack exchange,提问作者Ray Purchase
相关产品推荐
相关产品推荐

