Next.js集成Wasm脚本时遭遇CORS跨域问题求助
问题描述
尝试将已部署的Wasm应用迁移到Next.js路由,测试多种方案均失败,以下是最简复现示例:
Rust后端入口代码
use axum::Router; use tower_http::services::{ServeDir, ServeFile}; use tower_http::cors::{Any, CorsLayer}; #[shuttle_runtime::main] async fn main() -> shuttle_axum::ShuttleAxum { let layer = CorsLayer::new().allow_headers(Any); let router = Router::new().nest_service( "/", ServeDir::new("dist").not_found_service(ServeFile::new("dist/index.html")), ).layer(layer); Ok(router.into()) }
dist/index.html代码
<body> <canvas id="canvas" width="1280" height="720" cursor="auto"></canvas> <script crossorigin="anonymous" type="module"> import init from "https://bevy-game.shuttleapp.rs/game.js" init() </script> </body>
next.config.js配置
const getCorsHeaders = () => { const headers = {}; headers["Access-Control-Allow-Origin"] = "*"; headers["Access-Control-Allow-Credentials"] = "true"; headers["Access-Control-Allow-Methods"] = "GET,OPTIONS,PATCH,DELETE,POST,PUT"; headers["Access-Control-Allow-Headers"] = "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, Authorization"; return Object.entries(headers).map(([key, value]) => ({ key, value })); }; /** @type {import('next').NextConfig} */ const nextConfig = { webpack(config) { config.module.rules.push({ test: /\.svg$/i, use: ['@svgr/webpack'], }) return config }, async rewrites() { return [ { source: '/wasm-test', destination: `https://prismatic-shortbread-d520b8.netlify.app`, }, { source: '/wasm-test/:path*', destination: `https://prismatic-shortbread-d520b8.netlify.app/:path*`, }, { source: '/wasm-shuttle', destination: `https://bevy-game.shuttleapp.rs`, }, { source: '/wasm-shuttle/:path*', destination: `https://bevy-game.shuttleapp.rs/:path*`, } ] }, headers: async () => { return [ { source: "/wasm-test", headers: getCorsHeaders(), }, { source: "/wasm-test/:path*", headers: getCorsHeaders(), }, { source: "/wasm-shuttle", headers: getCorsHeaders(), }, { source: "/wasm-shuttle/:path*", headers: getCorsHeaders(), }, ]; }, ... }
报错信息
wasm-shuttle:1 Access to script at 'https://bevy-game.shuttleapp.rs/game.js' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
解决方案
1. 修复Rust后端的CORS配置
当前Axum的CORS层仅配置了允许任意请求头,但未设置允许的请求源,这是报错的核心原因。修改后端代码补充CORS规则:
use axum::Router; use tower_http::services::{ServeDir, ServeFile}; use tower_http::cors::{Any, CorsLayer}; #[shuttle_runtime::main] async fn main() -> shuttle_axum::ShuttleAxum { let layer = CorsLayer::new() .allow_headers(Any) .allow_origin(Any) // 开发环境允许所有源,生产环境需替换为具体域名 .allow_methods(Any); // 补充允许所有请求方法 let router = Router::new().nest_service( "/", ServeDir::new("dist").not_found_service(ServeFile::new("dist/index.html")), ).layer(layer); Ok(router.into()) }
生产环境建议指定具体允许的域名,示例:
.allow_origin(Origin::exact("http://localhost:3000").or(Origin::exact("你的生产域名")))
2. 调整Next.js中的脚本引入路径
利用已配置的rewrite规则,通过代理路径引入脚本,避免直接跨域请求:
修改dist/index.html中的脚本导入:
<script crossorigin="anonymous" type="module"> import init from "/wasm-shuttle/game.js" init() </script>
该请求会通过Next.js的rewrite转发到目标地址,从根源规避跨域问题。
3. 验证Next.js Headers配置
确保Headers规则正确匹配代理路径,若后端已修复CORS,此步骤可作为强化配置保留。
内容的提问来源于stack exchange,提问作者Wiktor Kujawa
相关产品推荐
相关产品推荐

