在IIS应用中部署Next.js时node_modules更新问题咨询
Next.js + IIS + Azure DevOps CI/CD 部署问题解决思路
当前部署方式
已成功在IIS根/子应用中部署Next.js应用,手动部署流程为:执行next build后,将构建输出的.next文件夹、node_modules、自定义web.config、server.js复制到IIS指向的构建目录,IISNode运行后会自动生成iisnode文件夹,最终目录结构如下:
next-build ├── .next ├── node_modules ├── web.config ├── server.js └── iisnode
核心问题
引入Azure DevOps CI/CD流水线后,生成的工件部署到IIS构建目录时,node_modules无法自动更新。尝试过Next.js的standalone输出模式(该模式会在构建产物中包含依赖),但存在兼容性问题无法正常运行。希望找到自动部署时添加node_modules的方案,考虑过在部署阶段执行yarn install,但对Azure DevOps不熟悉,不确定如何实现(此方案需要同时部署package.json)。
相关代码
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) => { const parsedUrl = parse(req.url, true); const { pathname, query } = parsedUrl; console.log(parsedUrl); console.log(req.headers); if (pathname.startsWith('/next-build')) { const page = pathname === '/next-build' ? '/' : pathname.substring('/next-build/'.length); return app.render(req, res, page, query); } else { return app.render(req, res, '/next-build', query); } }).listen(port, (err) => { if (err) throw err; console.log(`> Ready on http://localhost:${port}`); }); });
Azure DevOps 流水线YAML配置
trigger: - main pool: name: BuildServer steps: - task: NodeTool@0 inputs: versionSpec: '18.x' displayName: '安装 Node.js' - script: | npm install -g yarn displayName: '全局安装 yarn' - script: | yarn install displayName: '安装项目依赖' - script: | npm run build displayName: '执行 Next.js 构建' - task: PublishBuildArtifacts@1 inputs: PathtoPublish: $(build.SourcesDirectory)/.next ArtifactName: deploy publishLocation: 'Container'
错误信息

复现步骤
- 执行
npx create-next-app@latest创建基于Pages路由的Next.js应用 - 在
next.config.js中添加对应IIS应用名称的basePath,例如:basePath: "/next-build" - 将代码推送至Azure DevOps仓库
- 创建新流水线并关联代码仓库
- 使用上述YAML配置运行流水线,下载生成的工件
- 解压工件并放入IIS构建文件夹
- 在IIS中创建应用池并配置正确权限
- 在Default Web Site下创建名为
next-build的子应用,关联上述应用池,物理路径指向构建文件夹 - 确保站点/应用的访问用户拥有读写权限
- 安装iisnode和URL Rewrite模块
- 添加适配IIS的
web.config文件 - 添加上述自定义
server.js文件 - 访问应用即可触发错误
解决方案建议
方案1:调整流水线工件,部署时安装生产依赖
- 修改流水线的工件发布范围:
不要只发布.next文件夹,需要将package.json、yarn.lock(或package-lock.json)、server.js、web.config都纳入发布范围。可以添加CopyFiles任务将这些文件复制到统一输出目录,再发布该目录:# 在build步骤后添加 - task: CopyFiles@2 inputs: SourceFolder: '$(build.SourcesDirectory)' Contents: | package.json yarn.lock server.js web.config TargetFolder: '$(build.ArtifactStagingDirectory)/deploy' OverWrite: true - task: CopyFiles@2 inputs: SourceFolder: '$(build.SourcesDirectory)/.next' Contents: '**' TargetFolder: '$(build.ArtifactStagingDirectory)/deploy/.next' OverWrite: true - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(build.ArtifactStagingDirectory)/deploy' ArtifactName: deploy publishLocation: 'Container' - 在部署阶段添加依赖安装步骤:
使用Azure DevOps的部署任务或自定义脚本,在将工件部署到IIS服务器后,执行yarn install --production(仅安装生产依赖,减少体积)。确保部署用户拥有服务器构建目录的读写权限。
方案2:构建阶段打包生产依赖(不推荐,依赖体积大)
如果必须在构建阶段完成依赖打包,可以在流水线中添加ArchiveFiles任务,将.next、node_modules、必要配置文件一起打包成压缩包发布。但此方案会增大工件体积,且依赖更新时需要重新构建整个工件,灵活性较差。
额外检查点
- 确认IIS应用池的身份用户拥有构建目录的读写权限,确保
yarn install能正常写入文件 - 检查
web.config中的iisnode配置,确保指向正确的server.js路径 - 确认服务器上安装了对应版本的Node.js和yarn,避免版本不兼容问题
内容的提问来源于stack exchange,提问作者Tim van Dam
相关产品推荐
相关产品推荐

