You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一端口部署两个Next.js应用遇中间件冲突错误求助

同一端口运行两个Next.js应用并基于域名路由时的中间件冲突解决

我想在443端口同时运行两个Next.js应用,通过域名区分路由,但访问第二个站点时触发了Cannot redefine property: __import_unsupported错误。已经尝试在中间件里加主机名检查,但问题依旧。

自定义服务器代码(server.js)

require("dotenv").config();
const { createServer } = require("https");
const { parse } = require("url");
const next = require("next");
const fs = require("fs");
const http = require("http");
const path = require("path");

// Define middleware configuration
const middlewareConfig = {
  skipMiddlewareUrlNormalize: true,
  skipTrailingSlashRedirect: true,
};

const dev = process.env.NODE_ENV !== "production";
const gebruikersomgevingApp = next({
  dev,
  dir: path.join(__dirname, "gebruikersomgeving"),
  conf: {
    distDir: ".next-gebruikersomgeving",
    ...middlewareConfig,
  },
});

const prebookingApp = next({
  dev,
  dir: path.join(__dirname, "prebooking"),
  conf: {
    distDir: ".next-prebooking",
    ...middlewareConfig,
  },
});

const gebruikersomgevingHandler = gebruikersomgevingApp.getRequestHandler();
const prebookingHandler = prebookingApp.getRequestHandler();

const httpsOptions = {
  key: fs.readFileSync("C:/Certbot/live/******/privkey.pem"),
  cert: fs.readFileSync("C:/Certbot/live/******/fullchain.pem"),
};

// Initialize apps sequentially to avoid middleware conflicts
async function initializeApps() {
  try {
    await gebruikersomgevingApp.prepare();
    await prebookingApp.prepare();

    // HTTPS server
    createServer(httpsOptions, (req, res) => {
      const parsedUrl = parse(req.url, true);
      const hostname = req.headers.host || "";
      if (hostname.includes("prebooking.net")) {
        prebookingHandler(req, res, parsedUrl);
      } else if (hostname.includes("recreatieportaal.nl")) {
        gebruikersomgevingHandler(req, res, parsedUrl);
      } else {
        gebruikersomgevingHandler(req, res, parsedUrl);
      }
    }).listen(443, (err) => {
      if (err) throw err;
      console.log("> Ready on https://localhost:443");
    });

    // HTTP to HTTPS redirect server
    http
      .createServer((req, res) => {
        const hostname = req.headers.host || "";
        res.writeHead(301, {
          Location: `https://${hostname}${req.url}`,
        });
        res.end();
      })
      .listen(80, (err) => {
        if (err) throw err;
        console.log("> Redirecting HTTP to HTTPS on http://localhost:80");
      });
  } catch (error) {
    console.error("Error initializing apps:", error);
    process.exit(1);
  }
}

initializeApps();

应用中间件代码

Prebooking应用中间件

import { NextResponse, NextRequest } from 'next/server';

function generateUUID() {
  const uuid = crypto.randomUUID();
  return uuid;
}

async function middleware(request: NextRequest) {
  const hostname = request.nextUrl.host;
  if (!hostname.includes('prebooking.net')) {
    return
  }
  const url = request.nextUrl.clone();
  const cookies = request.cookies;
  
  // Check if we already have valid cookies
  if (cookies.get('sessionID') && cookies.get('returnURL')) {
    return NextResponse.next();
  }

  // Check for returnURL parameter
  const returnURL = url.searchParams.get('returnURL');
  
  // If no returnURL and no cookies, redirect to login
  if (!returnURL) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // Generate new session and set cookies
  const sessionID = generateUUID();
  const res = NextResponse.next();
  
  res.cookies.set({
    name: 'sessionID',
    value: sessionID,
    httpOnly: true,
    secure: false,
    maxAge: 60 * 30, // 30 minutes session
  });
  
  res.cookies.set({
    name: 'returnURL',
    value: returnURL,
    httpOnly: true,
    secure: false,
    maxAge: 60 * 30, // 30 minutes session
  });

  return res;
}

// Apply middleware to specific paths (optional)
export const config = {
    matcher: ['/'],
  };

export default middleware;

Gebruikersomgeving应用中间件

import { NextResponse, NextRequest } from 'next/server';
import AuthUser from './app/api/users';

async function middleware(request: NextRequest) {
  const hostname = request.nextUrl.host;
  if (!hostname.includes('recreatieportaal.nl')) {
    return
  }  
  const url = request.nextUrl.clone(); // Clone the URL object
  console.log(new Date().toLocaleTimeString() , 'URL:', url.href);
  // Access query parameters
  const userID = url.searchParams.get('UserID');
  const sessionID = url.searchParams.get('ID');
  const returnURL = url.searchParams.get('returnURL');

  let user = null;
  if(sessionID != null && userID != null && returnURL != null) { // als parameters niet worden meegestuurd
    user = await AuthUser(sessionID, userID, returnURL);
    if (user != null) {
      const res = NextResponse.next();
      res.headers.set("X-sessionID", sessionID);
      res.cookies.set({
        name: 'sessionID',
        value: sessionID,
        httpOnly: true,
        secure: true,
      });
      res.cookies.set({
        name: 'returnURL',
        value: returnURL,
        httpOnly: true,
        secure: true,
      });
      res.headers.set("X-userID", userID);
      res.headers.set("X-returnURL", returnURL);
      return res;
    }
  }

  return NextResponse.next();
}

// Apply middleware to specific paths (optional)
export const config = {
  matcher: ['/'],
};

export default middleware;

错误信息

TypeError: Cannot redefine property: __import_unsupported

    at <unknown> (webpack-internal:///(middleware)/../node_modules/next/dist/esm/server/web/globals.js:81)
    at Proxy.defineProperty (<anonymous>)
    at enhanceGlobals (webpack-internal:///(middleware)/../node_modules/next/dist/esm/server/web/globals.js:81:12)
    at eval (webpack-internal:///(middleware)/../node_modules/next/dist/esm/server/web/globals.js:89:1)
    at (middleware)/../node_modules/next/dist/esm/server/web/globals.js (file://D:\htdocs\multiapp\prebooking\.next-prebooking\server\middleware.js:399:1)
    at __webpack_require__ (file://D:\htdocs\multiapp\gebruikersomgeving\.next-gebruikersomgeving\server\edge-runtime-webpack.js:37:33)
    at fn (file://D:\htdocs\multiapp\gebruikersomgeving\.next-gebruikersomgeving\server\edge-runtime-webpack.js:273:21)
    at eval (webpack-internal:///(middleware)/../node_modules/next/dist/build/webpack/loaders/next-middleware-loader.js?absolutePagePath=D%3A%5Chtdocs%5Cmultiapp%5Cprebooking%5Cmiddleware.ts&page=%2Fmiddleware&rootDir=D%3A%5Chtdocs%5Cmultiapp%5Cprebooking&matchers=&preferredRegion=&middlewareConfig=e30%3D!:5:86)
    at (middleware)/../node_modules/next/dist/build/webpack/loaders/next-middleware-loader.js?absolutePagePath=D%3A%5Chtdocs%5Cmultiapp%5Cprebooking%5Cmiddleware.ts&page=%2Fmiddleware&rootDir=D%3A%5Chtdocs%5Cmultiapp%5Cprebooking&matchers=&preferredRegion=&middlewareConfig=e30%3D! (file://D:\htdocs\multiapp\prebooking\.next-prebooking\server\middleware.js:817:1)
    at __webpack_require__ (file://D:\htdocs\multiapp\gebruikersomgeving\.next-gebruikersomgeving\server\edge-runtime-webpack.js:37:33)
    at __webpack_exec__ (file://D:\htdocs\multiapp\prebooking\.next-prebooking\server\middleware.js:856:48)

解决方法

1. 核心原因

错误本质是两个Next.js应用的中间件在同一个Node.js进程中加载时,尝试重复定义全局变量(如__import_unsupported),导致运行时冲突。自定义Node.js服务器无法完全隔离两个应用的运行上下文,这是主要问题。

2. 推荐方案:改用Nginx反向代理

这是最稳定的解决方案,无需修改应用代码,通过Nginx直接做域名路由:

  • 分别启动两个Next.js应用在不同端口(比如3000和3001)
  • Nginx配置示例:
server {
    listen 443 ssl;
    server_name prebooking.net;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

server {
    listen 443 ssl;
    server_name recreatieportaal.nl;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    location / {
        proxy_pass http://localhost:3001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

# HTTP跳转HTTPS
server {
    listen 80;
    server_name prebooking.net recreatieportaal.nl;
    return 301 https://$host$request_uri;
}

3. 坚持用Node.js服务器:进程隔离

通过child_process将两个应用放在独立子进程运行,主进程仅做反向代理:

  • 主server.js修改为:
require("dotenv").config();
const { createServer } = require("https");
const http = require("http");
const fs = require("fs");
const { spawn } = require("child_process");
const httpProxy = require("http-proxy");

const proxy = httpProxy.createProxyServer({});
const httpsOptions = {
  key: fs.readFileSync("C:/Certbot/live/******/privkey.pem"),
  cert: fs.readFileSync("C:/Certbot/live/******/fullchain.pem"),
};

// 启动两个子进程运行各自的Next.js应用
const prebookingProcess = spawn("npm", ["run", "start"], { cwd: "./prebooking" });
const gebruikersomgevingProcess = spawn("npm", ["run", "start"], { cwd: "./gebruikersomgeving" });

// HTTPS代理服务器
createServer(httpsOptions, (req, res) => {
  const hostname = req.headers.host || "";
  if (hostname.includes("prebooking.net")) {
    proxy.web(req, res, { target: "http://localhost:3000" });
  } else {
    proxy.web(req, res, { target: "http://localhost:3001" });
  }
}).listen(443, () => {
  console.log("> Ready on https://localhost:443");
});

// HTTP跳转HTTPS
http.createServer((req, res) => {
  const hostname = req.headers.host || "";
  res.writeHead(301, { Location: `https://${hostname}${req.url}` });
  res.end();
}).listen(80, () => {
  console.log("> Redirecting HTTP to HTTPS on http://localhost:80");
});

// 监听子进程输出
prebookingProcess.stdout.on("data", (data) => console.log(`prebooking: ${data}`));
prebookingProcess.stderr.on("data", (data) => console.error(`prebooking error: ${data}`));
gebruikersomgevingProcess.stdout.on("data", (data) => console.log(`gebruikersomgeving: ${data}`));
gebruikersomgevingProcess.stderr.on("data", (data) => console.error(`gebruikersomgeving error: ${data}`));
  • 安装依赖:npm install http-proxy
  • 修改两个应用的package.json启动命令,指定端口:
// prebooking/package.json
"scripts": {
  "start": "next start -p 3000"
},
// gebruikersomgeving/package.json
"scripts": {
  "start": "next start -p 3001"
}

4. 中间件优化(辅助措施)

虽然无法解决核心冲突,但可以减少不必要的执行:

  • 将主机名检查改为if (!hostname.endsWith('prebooking.net')) return;,避免子域名误匹配
  • 调整config.matcher,仅匹配需要中间件处理的路径,减少执行频次

内容的提问来源于stack exchange,提问作者Jarno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 00:02:34