作为警告,我首先要说的是,我不相信 NextJS 可以很好地处理代理,尤其是在子路径上。
话虽如此,以下应该可行,但有限制:
const express = require('express')
const proxy = require('http-proxy-middleware')
const options = {
target:'http://localhost:3000/',
pathRewrite: {
'^/example': ''
}
}
const exampleProxy = proxy(options)
const app = express()
app.use(['/example', '/_next', '/static'], exampleProxy)
app.listen(8000)
pathRewrite 选项确保代理上的 /example/xyz 重定向到 NextJS 服务器上的 /xyz。
您需要代理/_next(或任何您将构建目录重命名为),以便您的页面找到所有构建的资产(脚本、样式表、webpack 块等)。如果您检查 Next 的任何项目页面,您会发现这些资产链接是绝对的,因此也需要代理该目录。
出于同样的原因,您需要代理 /static,除了该目录用于保存您的静态 NextJS 资产(图像等)。
您还会注意到 Next 中的页面链接通常也是绝对链接(我知道我的所有项目中都包含我的链接)。
以上都是我认为 NextJS 并不真正适合子路径代理使用的原因。
更新:
您可以在 NextJS 项目根目录的 next.config.js 文件中添加以下配置:
module.exports = {
assetPrefix: '/example'
}
这会将/example 添加到所有已构建资产的前面,因此您将链接到/example/_next/pages/xyz 而不是/_next/pages/xyz。通过此更新,您可以删除代理端的 /_next 代理,并且您的 可构建 资产(脚本、样式表等)仍应加载。
关于 NextJS 应用程序中的导航(即“页面”)链接,如我的评论中所述,您可以设置自己的 Link 版本并添加子路径:
import Link from 'next/link'
// for proxied server
const PROXY_PATH= '/example'
// for non-proxied server
// const PROXY_PATH= ''
export default MyLink = ({ as, children, ...props }) => <Link {...props} as={`${PROXY_PATH}${as}`}>{children}</Link>
您必须确保您的所有 MyLink 组件都定义了一个 as 属性。您不想想要更改 href 道具本身(链接 是),只更改 as 道具(链接 出现)。
最后,对于 /static 资产,您只需在 NextJS 应用程序中重写静态链接,即转
<img src='/static/mylogo.svg' />
到
<img src=`${PROXY_PATH}/static/mylogo.svg` />
并且代理端的路径重写应该正确处理它。
有了这个,您可以在单独的配置文件中的项目范围内定义PROXY_PATH,或者从环境变量中加载它。