nginx 如何通过反向代理后的nextjs为react应用提供服务?

wydwbb8l  于 5个月前  发布在  Nginx
关注(0)|答案(1)|浏览(78)

我已经构建了一个使用Next.js渲染代码的React应用程序。当通过http://localhost:3000本地服务时,一切都按预期运行。我已经按照说明(或多或少)将整个应用程序容器化,现在有一个按预期运行的容器。然而,像大多数应用程序一样,它需要位于反向代理之后,以便我可以使用一个URL访问它。
我设置反向代理的方式是使用https://secure.example.com的基本URL和/app路径,这些路径指向不同的程序。

location /phpmyadmin/ {
  rewrite       /phpmyadmin/(.*) /$1 break;
  proxy_pass    http://phpmyadmin/;
}

location /roundcube/ {
  rewrite       /roundcube/(.*) /$1 break;
  proxy_pass    http://roundcube/;

  proxy_set_header X-Forwarded-Path "/roundcube";
  proxy_set_header Host $host;
}

location /reactjs/ {
  rewrite        /reactjs/(.*) /$1 break;
  proxy_pass     http://reactjs:3000/;
}

字符串
在设置下一个应用程序时(reactjs位置),我遇到了一点麻烦。当我转到https://secure.example.com/reactjs/时,页面加载,但相关的CSS,JavaScript文件等。不。在加载html检查后,这些文件正在从/_next/请求。我的浏览器试图加载https://secure.example.com/_next/...,但遇到404,这是预期的,因为从该位置没有服务。
我尝试了设置basePath和相应地设置proxy_path指令的组合,但似乎没有帮助。我尝试了编写middleware代码,但似乎没有一个好的方法来重写结果html的内容,以正确引用请求路径。
我找到的唯一解决方案是为/_next/添加第二个location上下文:

location /_next/ {
  proxy_pass     http://reactjs:3000/_next/;
}


虽然这个解决方案可以工作,但它只允许托管下一个应用程序,我更喜欢这样一个解决方案,即渲染的html被正确更新,要么资源路径是相对的(即_next/someResource.js vs /_next/someResource.js),要么至少提供一个添加请求路径的选项。
我对reactjs和nextjs还很陌生,有没有什么我不知道的特性或功能可以让它正常工作?

hgc7kmma

hgc7kmma1#

似乎没有一种明显的方法来处理自定义/动态basePath,或者在呈现的HTML中将URI路径添加到引用的开头。
相反,我采用了我的工作解决方案,并使用basePath将所有内容推送到根斜杠右侧的一个目录,然后编写中间件将发送到/_next的请求重写为${basePath}
我在next.js Github讨论板上写了一个完整的解决方案。
我的nginx配置:

location /reactjs/ {
  rewrite        /reactjs/(.*) /$1 break;
  proxy_pass     http://reactjs:3000/;

  proxy_set_header X-Forwarded-Host $http_host;
}

字符串
next.conf.js:

/** @type {import('next').NextConfig} */

const nextConfig = {
  basePath: '/reactjs',
};

module.exports = nextConfig;


middleware.js:

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

export function middleware(request) {
  // If X-Forwarded-Host is not set, then don't bother with middleware.
  const forwardedHost = request.headers.get('X-Forwarded-Host');
  if (forwardedHost === null) return NextResponse.next();

  // Middleware starts here
  const requestedUrl = request.nextUrl.clone();
  const basePath = '/reactjs';

  // const requestedHost = request.headers.get('X-Forwarded-Host');
  // const forwardedPath = request.headers.get('X-Forwarded-Path');

  console.log('basePath set: ' + basePath);
  console.log('requestedUrl: ' + requestedUrl.toString());
  console.log('basePath index: ' + requestedUrl.toString().indexOf(basePath));

  if (requestedUrl.toString().indexOf(basePath) == -1) {
    console.log('basePath not detected in request.');

    const pathForward = basePath + requestedUrl.toString().split('localhost:3000').pop();
    console.log('Will offer (proxy): ' + pathForward);
    return NextResponse.rewrite(new URL(pathForward, request.url));
  }

  return NextResponse.next();
}


这允许文件在nginx中正确服务,而无需额外的位置上下文。我对此的唯一其他问题是basePath必须匹配nginx使用的位置URI路径。在我的情况下,我不怀疑这是一个问题,但如果我正在创建一个将被广泛使用的应用程序,这可能会带来一点挑战。我更希望这个路径能够通过环境变量设置,但我尝试这样做时遇到了错误,说明basePath必须为空或设置。
希望这种行为将在不久的将来添加到开箱即用。

相关问题