在IIS上部署Next.js遭遇404错误,寻求解决方案
在IIS部署Next.js项目遇到404问题的排查与解决
问题背景
刚接触IIS部署Next.js,为验证部署策略创建了小型测试项目,按步骤操作后仍遇到404错误。
已执行操作
- 执行
next build构建项目,将.next、node_modules文件夹,以及web.config和server.js复制到部署目录 - 安装iisnode和URLRewrite模块
- 在IIS「默认网站」下创建名为
iis-test-project的应用程序,关联应用程序池,配置好物理路径及权限
遇到的问题
- 访问
http://localhost/iis-test-project时显示Next.js的「404 | This page could not be found.」页面 - 静态资源如
http://localhost/_next/static/chunks/main-app-9fe887c4b47d5643.js返回404 - 尝试设置
next.config.js的output: "export"并替换部署文件,问题未解决
当前配置文件
web.config
<configuration> <system.webServer> <rewrite> <rules> <rule name="myapp"> <match url="/*" /> <action type="Rewrite" url="server.js" /> </rule> </rules> </rewrite> <iisnode node_env="production" nodeProcessCommandLine=""C:\Program Files\nodejs\node.exe"" interceptor=""%programfiles%\iisnode\interceptor.js"" /> </system.webServer> <location path="" overrideMode="Deny"> <system.webServer> <handlers> <add name="iisnode" path="server.js" verb="*" modules="iisnode" /> </handlers> </system.webServer> </location> </configuration>
server.js
const { createServer } = require('http') const { parse } = require('url') const next = require('next') const dev = process.env.NODE_ENV !== 'production' const port = process.env.PORT || 3000; const app = next({ dev }) const handle = app.getRequestHandler() app.prepare().then(() => { createServer((req, res) => { handle(req, res, parsedUrl) }).listen(port, (err) => { if (err) throw err console.log(`> Ready on http://localhost:${port}`) }) })
解决方案
1. 修复server.js的代码错误
原代码未定义parsedUrl变量,且未配置子应用的basePath,导致Next.js无法正确解析请求路径。修改后的代码:
const { createServer } = require('http') const { parse } = require('url') const next = require('next') const dev = process.env.NODE_ENV !== 'production' // 优先使用IIS分配的端口,不要硬编码3000 const port = process.env.PORT || 3000; // 配置basePath为子应用名称 const app = next({ dev, basePath: '/iis-test-project' }) const handle = app.getRequestHandler() app.prepare().then(() => { createServer((req, res) => { // 补上解析URL的代码 const parsedUrl = parse(req.url, true) handle(req, res, parsedUrl) }).listen(port, (err) => { if (err) throw err console.log(`> Ready on http://localhost:${port}`) }) })
2. 调整web.config的重写规则
原规则会将所有请求转发到server.js,包括静态资源,导致静态文件无法被正确访问。修改后优先处理静态资源,再转发其他请求:
<configuration> <system.webServer> <rewrite> <rules> <!-- 优先处理Next.js静态资源,直接返回文件 --> <rule name="Next.js Static Files" stopProcessing="true"> <match url="^_next/static/.*" /> <action type="Rewrite" url="{R:0}" /> </rule> <!-- 将其他请求转发到server.js,保留完整路径 --> <rule name="myapp"> <match url=".*" /> <action type="Rewrite" url="server.js/{R:0}" /> </rule> </rules> </rewrite> <iisnode node_env="production" nodeProcessCommandLine=""C:\Program Files\nodejs\node.exe"" /> <handlers> <add name="iisnode" path="server.js" verb="*" modules="iisnode" /> </handlers> </system.webServer> </configuration>
3. 配置next.config.js的basePath
在项目根目录的next.config.js中添加子应用路径,确保Next.js生成的资源路径正确:
/** @type {import('next').NextConfig} */ const nextConfig = { basePath: '/iis-test-project', // 如果使用静态导出模式(output: "export"),需额外配置assetPrefix // assetPrefix: '/iis-test-project', } module.exports = nextConfig
4. 验证权限与应用程序池设置
- 确认应用程序池的标识(如
IIS AppPool\iis-test-project)对部署目录拥有读取和执行权限 - 将应用程序池的
.NET CLR版本设置为无托管代码,适配Node.js应用
问题原因总结
- server.js缺失
parsedUrl变量定义,导致请求路径解析失败 - 未配置
basePath,Next.js无法识别自身运行在子应用路径下,生成的静态资源路径错误 - web.config重写规则未优先处理静态资源,导致静态请求被转发到server.js返回404
内容的提问来源于stack exchange,提问作者Tim van Dam
相关产品推荐
相关产品推荐

