PS: 下面方法发现个致命问题,静态资源无法设置成相对路径,待寻求解决方法
NextJS 部署到特定 URL 路径的解决方案探索与实践
在使用 NextJS 进行项目开发时,常常会遇到将项目部署到特定 URL 路径的需求。这在一些复杂的项目架构中,或者需要与其他服务集成的场景下尤为常见。起初,我在解决这个问题时,参考了 DeepSeek-R1 以及相关文章,发现常见的方法是添加一层 Nginx 或者在代码中进行硬编码路径设置。然而,这两种方式都存在一定的局限性,并不理想。经过一番探索和尝试,最终找到了一种较为满意的解决方案,下面将详细介绍这个过程以及具体的实现代码。
常见方案的局限性
- 添加 Nginx 层:使用 Nginx 来处理特定 URL 路径的转发,虽然可以实现功能,但增加了系统的复杂性。这意味着需要额外配置和维护 Nginx 服务器,增加了运维成本。而且,对于一些对部署环境要求简单的项目来说,这种方式显得过于繁琐。
- 硬编码路径:在代码中直接硬编码特定的 URL 路径,虽然实现起来简单直接,但这种方式缺乏灵活性。当项目的部署路径发生变化时,需要修改大量的代码,并且不利于代码的维护和复用。
最终解决方案
为了解决上述问题,我采用了以下两种关键步骤:
- 设置中间件 middleware.tsx:中间件在 NextJS 中起着重要的作用,它可以在请求到达页面之前对请求进行处理。通过设置中间件,我们可以实现对请求路径的重写,使其符合我们的特定 URL 路径需求。
- 静态资源动态获取 basePath:对于静态资源(如链接、图片等),通过 env.mjs 动态获取 basePath,并将其设置到相应的地方。这样可以确保静态资源的路径在不同的部署环境下都能正确加载。
具体实现代码解析
next.config.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const nextConfig = {
basePath: "",
assetPrefix: ".", // TODO: 目前被卡在这里,静态资源文件无法指定相对路径,nextjs只接受 / 和 http 地址
reactStrictMode: true,
images: {
remotePatterns: [
{
protocol: "https",
hostname: "**",
},
{
protocol: "http",
hostname: "**",
},
],
},
};
export default nextConfig;
- middleware.tsx
1 | import { NextRequest, NextResponse } from 'next/server'; |
在这个中间件中,首先获取请求的路径名 pathname
,然后通过 getBasePath
函数获取当前路径的前缀 basePath
。如果没有匹配到前缀,则直接返回原始请求。否则,将路径名中的前缀替换为空字符串,实现路径的重写,并返回重写后的请求。
- env.mjs
1 | /* eslint-disable no-process-env */ |
在 env.mjs
文件中,首先使用 createEnv
创建了一个环境变量对象 env
,定义了客户端和运行时的环境变量。然后,通过 getDynamicEnv
函数实现了动态覆盖环境变量的值。如果在浏览器环境中,从 URL 中获取 apiUrl
、token
和 basePath
,并根据这些值动态更新环境变量。
- lib/utils.tsx
1 | // 判断当前路由是否在白名单中,如果在,则返回当前路由的前缀,否则返回空字符串 |
这个函数用于判断当前路径是否在指定的白名单路径中,如果在,则返回路径的前缀,否则返回空字符串。
- home/page.tsx
1 | "use client"; |
在页面组件中,通过 getDynamicEnv
函数获取 NEXT_PUBLIC_BASE_PATH
,并将其用于图片的 src
属性,确保图片路径的正确性。
总结
通过上述设置中间件和动态获取静态资源路径的方式,成功解决了 NextJS 部署到特定 URL 路径的问题。这种方法既避免了添加 Nginx 层的复杂性,又克服了硬编码路径的不灵活性,提高了项目的可维护性和可扩展性。在实际项目中,根据具体的需求和场景,可以对这些代码进行适当的调整和优化,以满足不同的部署要求。希望这篇文章对正在面临类似问题的开发者有所帮助。
本文链接: http://www.ionluo.cn/blog/posts/9394e4c5.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!