Next.js配置cookie类型has条件rewrites致Image组件加载异常
相关配置
next.config.js
/** @type {import('next').NextConfig} */ const has = { type: 'cookie', key: 'mobile', value: 'true', }; module.exports = { publicRuntimeConfig: { API_URL: [process.env.API_URL] }, trailingSlash: true, images: { domains: [process.env.API_URL], deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], }, webpack: (config, { isServer }) => { if (!isServer) { config.resolve.fallback = { fs: false, }; } return config; }, async rewrites() { return { beforeFiles: [ { source: '/path/', destination: '/mobile/path', has: [has], }, { source: '/path/:league/', destination: '/mobile/path/:league/', has: [has], }, { source: '/:url*/', destination: '/mobile/:url*/', has: [has], }, ], }; }, };
注:原配置存在两处语法笔误,已在上述代码中修正:一是images.domains数组缺少闭合括号,二是第一条重写规则的source字段缺少字符串闭合引号与结尾斜杠。
问题表现
配置中通过rewrites实现路径重写,期望当请求携带mobile=true的cookie时,将对应页面请求转发到移动端路径下。实际测试出现以下现象:
Image组件加载异常,图片显示为破损状态- 异常仅在
has判断条件类型为cookie时出现,将类型改为query后图片加载完全正常 - 排查确认图片请求URL未被修改,格式为
http://localhost:3000/_next/image/?url=https://external-url.com - 直接访问重写后的目标路径
/mobile/path(不触发重写规则)时,图片可以正常加载

问题原因
该问题不属于Next.js框架bug,是重写规则匹配范围过大导致的:
配置的第三条重写规则使用了通配符/:url*/,会匹配所有路径的请求。而cookie会在同域下的所有请求中自动携带,包括Next.js内部的资源请求——比如图片优化接口/_next/image、静态资源请求/_next/static/*,这些请求都会命中通配重写规则,被转发到/mobile/_next/*路径下。但/mobile/_next/*没有对应的处理逻辑,会直接返回404或者错误响应,最终导致图片加载失败。
当判断条件改为query类型时,Next.js内部发起的/_next/image请求不会自动携带自定义query参数,因此不会命中重写规则,图片加载自然正常。
修复方案
在重写规则中排除Next.js内部路径,避免/_next开头的内部请求被重写即可,修改后的rewrites配置如下:
async rewrites() { return { beforeFiles: [ { source: '/path/', destination: '/mobile/path', has: [has], }, { source: '/path/:league/', destination: '/mobile/path/:league/', has: [has], }, { source: '/:url*/', destination: '/mobile/:url*/', has: [has], missing: [ { type: 'pathname', value: '^/_next(.*)$' } ] }, ], }; },
通过添加missing条件,所有/_next开头的内部路径都不会命中这条通配重写规则,图片组件、静态资源的加载就会恢复正常。
内容的提问来源于stack exchange,提问作者Andrii Radkevych
相关产品推荐
相关产品推荐

