NextJS+Bun环境中间件导出TextDecoderStream空值错误及IP白名单求助
解决Bun+NextJS 13.5.4中Middleware的TextDecoderStream错误并实现IP白名单
一、修复Middleware的TextDecoderStream错误
该错误由Bun 1.0.4与NextJS 13.5.4的Edge Runtime兼容性冲突导致,可尝试以下修复方案:
1. 升级NextJS版本
升级到NextJS 13.5.6及以上稳定版(或直接升级至14.x),官方已修复部分Edge Runtime与Bun的兼容问题:
bun add next@latest
2. 调整Middleware文件位置
将middleware.ts从/src目录移至项目根目录(与src文件夹同级),同时确保tsconfig.json的include配置包含根目录文件:
{ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "middleware.ts"] }
3. 临时切换到Node.js Runtime(实验性)
在next.config.js中配置强制使用Node.js Runtime,绕过Edge环境的兼容性问题:
module.exports = { experimental: { edgeRuntime: 'nodejs', }, }
注意:该配置为实验性功能,可能影响部分Edge专属特性的使用。
二、IP白名单实现方案
方案1:修复后用Middleware实现
当Middleware恢复正常后,编写IP校验逻辑:
import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' // 白名单IP列表 const ALLOWED_IPS = ['192.168.1.1', '127.0.0.1'] export function middleware(request: NextRequest) { // 获取客户端IP(部署到云平台时优先取代理头) const clientIp = request.ip || request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() if (!clientIp || !ALLOWED_IPS.includes(clientIp)) { return new NextResponse('Access Denied', { status: 403 }) } return NextResponse.next() } // 指定需要拦截的路由(匹配所有路由) export const config = { matcher: '/:path*', }
方案2:用根Layout组件替代(无需Middleware)
如果Middleware问题暂时无法解决,可在App Router的根Layout中添加IP校验:
// src/app/layout.tsx import { headers } from 'next/headers' import { redirect } from 'next/navigation' const ALLOWED_IPS = ['192.168.1.1', '127.0.0.1'] export default function RootLayout({ children }: { children: React.ReactNode }) { const headerList = headers() // 获取客户端IP const clientIp = headerList.get('x-forwarded-for')?.split(',')[0]?.trim() || headerList.get('x-real-ip') || 'unknown' if (!ALLOWED_IPS.includes(clientIp)) { redirect('/access-denied') } return ( <html lang="zh-CN"> <body>{children}</body> </html> ) }
创建src/app/access-denied/page.tsx返回403页面:
export default function AccessDenied() { return <h1>403 访问被拒绝</h1> }
注意:该方式仅拦截页面路由,API路由需单独添加校验逻辑。
方案3:自定义Bun服务器实现
如果使用Bun自定义服务器启动NextJS,可在服务器层直接做IP校验:
// server.ts import { createServer } from 'bun' import next from 'next' const dev = process.env.NODE_ENV !== 'production' const app = next({ dev }) const handle = app.getRequestHandler() const ALLOWED_IPS = ['192.168.1.1', '127.0.0.1'] app.prepare().then(() => { createServer({ async fetch(req) { const clientIp = req.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || req.ip || 'unknown' if (!ALLOWED_IPS.includes(clientIp)) { return new Response('Access Denied', { status: 403 }) } return handle(req) }, }).listen({ port: 3000 }, () => { console.log('服务器运行在 http://localhost:3000') }) })
修改package.json的启动脚本:
{ "scripts": { "dev": "bun run server.ts" } }
内容的提问来源于stack exchange,提问作者Forgotten-Storm
相关产品推荐
相关产品推荐

