三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Vue项目部署IIS全攻略:解决路由404、静态资源与跨域问题

Vue项目部署IIS全攻略:解决路由404、静态资源与跨域问题

1. 项目概述:从开发到上线的最后一公里

做前端开发的朋友,尤其是用Vue框架的,肯定都经历过这个阶段:本地npm run serve跑得飞快,接口调得顺畅,页面渲染完美。但一到要部署到正式的Web服务器,比如Windows Server上最常见的IIS(Internet Information Services),各种“幺蛾子”就全来了。页面白屏、接口404、静态资源加载失败、路由刷新404……这些问题就像通关路上的隐藏Boss,不把它们一个个解决掉,你的应用就永远走不出localhost。

我最近刚把一个中大型的Vue后台管理系统成功部署到了客户的Windows Server 2019的IIS上,整个过程可以说是把能踩的坑几乎都踩了一遍。从IIS的安装、功能启用,到站点的配置、URL重写规则的编写,再到解决因vue.config.js配置、环境变量和跨域引发的各种诡异报错,每一步都需要细致的操作和清晰的理解。网上很多教程要么太旧,要么只讲某一步,缺乏一个从零开始、贯穿始终的实战记录。所以,我想把这次完整的部署过程、遇到的问题以及最终的解决方案系统地梳理出来,希望能帮到正在或即将面临同样挑战的你。这篇文章不会只告诉你“点这里,点那里”,我会重点解释每个配置项背后的逻辑,以及当报错出现时,我们该如何像侦探一样,从浏览器的控制台、IIS的日志里找到线索,最终解决问题。

2. 部署环境整体规划与核心思路

在动手之前,我们必须对部署的“战场”有一个清晰的认识。我们的目标是将一个基于Vue CLI构建的前端SPA(单页应用),部署到Windows Server的IIS上,并确保其能独立运行(不依赖Node.js服务),同时能正确对接后端API。

2.1 为什么选择IIS?

对于许多企业环境,特别是那些历史包袱较重或主要技术栈围绕.NET的团队,Windows Server是标准的服务器操作系统。IIS作为其内置的Web服务器,具有开箱即用、与Windows系统深度集成(如身份验证、性能计数器)、管理界面图形化等优点。虽然对于前端静态资源,Nginx在性能和配置灵活性上可能更胜一筹,但在既定环境下,掌握IIS部署是必要的技能。

2.2 核心挑战与解决思路

部署Vue应用到IIS,不同于部署一个简单的HTML文件集合,主要面临三大挑战,我们的整体思路也围绕它们展开:

  1. 历史路由(History Mode)问题:Vue Router默认使用HTML5 History模式,它利用history.pushStateAPI来实现无#的漂亮URL。但在IIS上,当你直接访问/about这样的子路由,或刷新页面时,IIS会试图在服务器磁盘上寻找名为about的文件或目录,显然找不到,于是返回404。解决思路:我们需要在IIS上配置URL重写规则,将所有非文件、非目录的请求,都重定向到应用的入口文件index.html,由Vue Router在前端接管路由。

  2. 静态资源路径问题:Vue项目打包后,CSS、JS、图片等静态资源会带有哈希值(如app.abc123.js)。如果vue.config.js中配置了错误的publicPath(例如,你的应用部署在子路径/myapp下,但publicPath仍是/),会导致浏览器请求资源的路径错误,从而加载失败。解决思路:根据应用最终访问的URL结构,正确配置vue.config.js中的publicPathoutputDir

  3. 跨域与API代理问题:在开发时,我们常用vue.config.js中的devServer.proxy来代理API请求,解决跨域。但生产构建后,这个配置不再生效。前端打包后的代码是静态的,它发起的API请求会直接从浏览器发送到后端地址。如果前后端域名不同,就会遇到跨域问题。解决思路:生产环境不应依赖前端解决跨域。最佳实践是让前后端部署在同一域名下(不同路径),或者由后端服务配置CORS(跨域资源共享)策略。在IIS层面,我们也可以利用其“应用程序请求路由”和“URL重写”模块,为前端配置一个反向代理,将特定路径的请求转发到后端API服务器,这在某些场景下是有效的过渡方案。

理解了这三点,我们的部署路径就清晰了:准备服务器环境 -> 调整Vue项目构建配置 -> 打包并放置到IIS -> 配置IIS站点与URL重写 -> 处理跨域等进阶问题。

3. 服务器环境准备:IIS安装与必需功能启用

很多部署问题,根源在于IIS本身的功能没有安装完整。下面我们一步步来搭建一个适合托管现代前端应用的IIS环境。

3.1 安装IIS服务器角色

在Windows Server上,可以通过“服务器管理器”来添加角色和功能。

  1. 打开服务器管理器
  2. 点击“添加角色和功能”
  3. 在“安装类型”步骤,选择“基于角色或基于功能的安装”
  4. 在“服务器选择”步骤,选择当前服务器。
  5. 在“服务器角色”步骤,勾选“Web 服务器(IIS)”。点击后会弹出窗口,询问是否添加所需功能,点击“添加功能”
  6. 点击下一步,直到进入“角色服务”步骤。这是最关键的一步。

3.2 选择必需的角色服务

默认选中的项目通常不够。为了支持静态文件服务、URL重写、错误页面定制等功能,我们需要手动添加以下角色服务:

  • 常见HTTP功能:默认已选中,确保“静态内容”已勾选。这是基础。
  • 应用程序开发这个必须展开并勾选!
    • .NET Extensibility 3.5 和 4.8:即使我们部署的是纯前端,某些IIS模块可能依赖于此。
    • ASP.NET 3.5 和 4.8:同上,确保运行时支持。
    • ISAPI 扩展:一些旧模块可能需要。
    • ISAPI 过滤器:同上。
  • 运行状况和诊断:建议勾选“HTTP日志记录”和“请求监视器”,便于后续排错。
  • 安全性:根据需求选择,如“请求筛选”、“IP和域限制”。初期可保持默认。
  • 性能:静态内容压缩和动态内容压缩建议都勾选,可以显著减小传输体积,提升加载速度。
  • 管理工具:确保“IIS管理控制台”被勾选。

关键提示:如果你确定后续需要配置URL重写规则(解决路由404问题)或应用程序请求路由(配置反向代理),那么最好在安装时就把这两个模块装上。它们位于“Web服务器(IIS)” -> “管理工具” ->“IIS 可再发行组件”下?不,这里容易找错。实际上,URL重写模块和应用程序请求路由模块通常不是通过服务器管理器安装的,它们需要单独下载安装包。我们可以在IIS安装完成后,再去下载安装。但为了流程连贯,我们先记下这笔。

点击下一步,确认安装。等待安装完成。

3.3 安装URL重写模块与应用程序请求路由

这是解决Vue Router History模式404问题的核心。

  1. 下载URL重写模块:访问微软官方下载页面(搜索“IIS URL Rewrite”),下载与系统位数匹配的安装包(通常是x64)。运行安装程序,按提示完成安装。
  2. 下载应用程序请求路由模块:如果你需要配置反向代理,同样需要搜索“IIS Application Request Routing”进行下载安装。安装ARR时,通常会提示安装其依赖的“Web平台安装程序”,按提示操作即可。

安装完成后,重启IIS管理器(或直接在命令行运行iisreset),你就能在IIS站点的功能视图中看到“URL重写”和“应用程序请求路由”的图标了。

4. Vue项目构建配置要点解析

在打包项目之前,我们需要根据部署目标环境,调整vue.config.js文件。这个文件是Vue CLI项目的核心配置文件。

4.1 关键配置项:publicPath 与 outputDir

// vue.config.js const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ // 部署应用包时的基本 URL。默认是 '/',假设部署在域名的根路径下。 // 如果你打算部署在 https://www.example.com/my-app/,那么 publicPath 应设置为 '/my-app/'。 // 重要:这个值在开发环境下无效,只在生产环境构建时生效。它会影响所有资源(js, css, img, fonts)的引用路径。 publicPath: process.env.NODE_ENV === 'production' ? '/你的子路径/' : '/', // 构建生成的生产环境构建文件的目录。默认是 'dist'。 // 你可以修改为其他名字,比如 'output'。这个目录下的内容就是你要上传到服务器的全部内容。 outputDir: 'dist', // 放置生成的静态资源 (js、css、img、fonts) 的目录 (相对于 outputDir)。 // assetsDir: 'static', // 指定生成的 index.html 的输出路径 (相对于 outputDir)。 // indexPath: 'index.html', // 其他配置... })

publicPath的坑: 这是最容易出错的地方。假设你的服务器IP是192.168.1.100,你希望通过http://192.168.1.100/app来访问应用。

  • 错误配置publicPath: '/'。打包后,资源引用路径会是/js/app.xxx.js。浏览器会去请求http://192.168.1.100/js/app.xxx.js。但你的应用实际在/app目录下,IIS会在http://192.168.1.100/app这个物理路径下找js文件夹,结果就是404。
  • 正确配置publicPath: '/app/'。打包后,资源引用路径变为/app/js/app.xxx.js。浏览器会请求http://192.168.1.100/app/js/app.xxx.js,IIS就能正确映射到物理路径下的文件了。

如何确定publicPath?问你自己:用户最终通过哪个完整的URL来访问我的应用首页?把这个URL中域名之后的部分,作为publicPath(必须以斜杠开头和结尾)。如果直接是根域名,那就是/

4.2 环境变量与模式配置

生产环境和开发环境的API地址通常不同。我们可以在项目根目录创建环境文件来管理。

  1. 创建环境文件

    • .env.development:开发环境变量。
    VUE_APP_API_BASE_URL=/api
    • .env.production:生产环境变量。
    VUE_APP_API_BASE_URL=/prod-api

    注意:只有以VUE_APP_开头的变量才会被静态嵌入到客户端代码中。

  2. 在代码中使用:在你的API请求封装文件中(如src/utils/request.js),可以这样使用:

    const service = axios.create({ baseURL: process.env.VUE_APP_API_BASE_URL, timeout: 10000 });

    这样,在开发时,请求会发往/api(由devServer.proxy代理);在生产构建后,请求会发往/prod-api

  3. 在vue.config.js中配置代理(仅开发有效)

    module.exports = defineConfig({ // ... 其他配置 devServer: { proxy: { '/api': { // 匹配所有以 /api 开头的请求 target: 'http://your-backend-server.com', // 后端API地址 changeOrigin: true, // 改变请求头中的Origin为目标地址,解决CORS pathRewrite: { '^/api': '' // 重写路径,去掉 /api 前缀 } } } } })

    再次强调:这个devServer.proxy配置只在npm run serve时生效,对生产包毫无影响。不要指望用它来解决生产环境的跨域问题。

4.3 执行构建

配置好vue.config.js和环境变量后,运行构建命令:

npm run build

或者如果你使用了自定义模式:

npm run build:production

构建成功后,你会在项目根目录下看到dist文件夹(或你指定的outputDir),里面就是需要部署到IIS的全部静态文件。

5. IIS站点配置与部署实操

现在,我们将dist文件夹里的内容放到服务器上,并通过IIS建立站点。

5.1 文件上传与目录权限

  1. 在服务器上选择一个目录存放你的应用,例如C:\WebSites\MyVueApp
  2. dist文件夹内的所有文件(注意是文件夹内的内容,不是dist文件夹本身),复制到C:\WebSites\MyVueApp
  3. 设置目录权限(非常重要!):右键点击MyVueApp文件夹 -> “属性” -> “安全”选项卡。
    • 点击“编辑”,然后“添加”。
    • 输入对象名称:IIS_IUSRS,点击“检查名称”后确定。
    • 在权限列表中,给IIS_IUSRS组赋予“读取和执行”、“列出文件夹内容”、“读取”的权限。点击确定。

实操心得:权限问题是导致“HTTP 错误 500.19 - Internal Server Error”或“无法访问请求的页面”的常见原因。确保IIS的工作进程账户(默认是IIS_IUSRS组或特定的应用程序池标识)对你的网站根目录有读取权限。

5.2 创建IIS站点

  1. 打开IIS管理器
  2. 在左侧“连接”面板,展开服务器节点,右键点击“网站”,选择“添加网站”。
  3. 网站名称:填写一个易于识别的名字,如MyVueApp
  4. 物理路径:点击浏览,选择刚才的文件夹C:\WebSites\MyVueApp
  5. 绑定
    • 类型httphttps(如果你有SSL证书)。
    • IP地址:可以选择“全部未分配”或指定一个服务器IP。
    • 端口80(http)或443(https)。如果80端口已被占用,可以用其他端口,如8080
    • 主机名:如果有域名,可以填写。测试阶段可以留空。
  6. 点击“确定”。现在,在浏览器访问http://服务器IP:端口,你应该能看到Vue应用的界面了。但是,如果你点击了路由跳转,然后刷新页面,大概率会遇到404错误

6. 核心难题破解:配置URL重写解决路由404

现在我们来解决Vue Router History模式在IIS下的核心问题。我们将使用之前安装的“URL重写”模块。

6.1 图形界面配置法(推荐)

  1. 在IIS管理器中,选中你刚刚创建的站点(MyVueApp)。
  2. 双击功能视图中的“URL重写”图标。
  3. 在右侧“操作”面板,点击“添加规则...”
  4. 选择规则模板:“入站规则” ->“空白规则”
  5. 编辑入站规则:
    • 名称Vue Router History Mode(自定义)。
    • 匹配URL
      • 请求的URL:选择“与模式匹配”。
      • 使用:选择“正则表达式”。
      • 模式:(.*)(匹配所有请求)。
    • 条件
      • 点击“添加”条件。
      • 条件输入:{REQUEST_FILENAME}
      • 检查输入字符串是否:选择“不是文件”。
      • 点击“确定”。
      • 再次点击“添加”条件。
      • 条件输入:{REQUEST_FILENAME}
      • 检查输入字符串是否:选择“不是目录”。
      • 点击“确定”。
      • 逻辑分组:选择“全部匹配”。
    • 操作
      • 操作类型:选择“重写”。
      • 重写URL:/index.html
      • 其他默认。
  6. 点击右侧“应用”。规则就创建好了。

这个规则的含义是:对于所有进入的请求,如果请求的URL既不对应服务器上的一个物理文件,也不对应一个物理目录,那么就将请求重写到/index.html。这样,Vue应用就能被加载,并由Vue Router来解析URL,展示对应的组件。

6.2 web.config文件配置法(便于迁移)

图形界面配置最终会生成一个web.config文件放在你的网站根目录。你也可以直接创建或修改这个文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="Vue Router History Mode" stopProcessing="true"> <match url="(.*)" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <action type="Rewrite" url="/index.html" /> </rule> </rules> </rewrite> <!-- 可选:配置静态文件缓存、MIME类型等 --> <staticContent> <!-- 解决某些字体文件或特殊文件类型无法识别的问题 --> <remove fileExtension=".json" /> <mimeMap fileExtension=".json" mimeType="application/json" /> <remove fileExtension=".woff2" /> <mimeMap fileExtension=".woff2" mimeType="font/woff2" /> </staticContent> </system.webServer> </configuration>

将上述web.config文件放到你的网站根目录(和index.html同级)。IIS会自动读取并应用其中的重写规则。

注意事项:如果你的应用部署在子路径(如/app),那么重写URL应该是/app/index.html。同时,确保vue.config.js中的publicPath也配置正确,两者必须匹配。

配置完成后,再次访问你的应用,尝试刷新子路由页面,404错误应该就消失了。

7. 生产环境跨域问题与反向代理配置

如前所述,生产环境跨域应由后端解决(CORS)。但如果后端暂时无法修改,或者你希望将所有请求统一通过前端域名发出,可以在IIS上为前端站点配置一个反向代理,将API请求转发到后端服务器。

前提:确保已安装“应用程序请求路由”模块。

7.1 启用代理功能

  1. 在IIS管理器中,点击服务器节点(不是站点),找到“应用程序请求路由缓存”功能。
  2. 双击打开,在右侧“操作”面板,点击“服务器代理设置...”。
  3. 勾选“启用代理”,然后点击“应用”。

7.2 配置URL重写规则进行代理

我们的目标是:将前端对/prod-api/的请求,转发到真正的后端服务器http://api-backend.com

  1. 再次进入你的站点(MyVueApp)的“URL重写”功能。
  2. 点击“添加规则”,选择“空白规则”。
  3. 编辑规则:
    • 名称Reverse Proxy to API
    • 匹配URL
      • 模式:^prod-api/(.*)(正则表达式,匹配以prod-api/开头的请求)。
      • 这个模式需要和你在生产环境变量VUE_APP_API_BASE_URL中设置的值匹配。
    • 条件:此规则通常不需要额外条件。
    • 操作
      • 操作类型:选择“重写”。
      • 重写URL:http://api-backend.com/{R:1}{R:1}捕获了正则中(.*)的内容)。
      • 重要:勾选“停止处理后续规则”。
  4. 点击“应用”。

配置后的效果:前端代码请求/prod-api/user/login,IIS的URL重写模块会截获这个请求,并将其重写为http://api-backend.com/user/login,然后由ARR模块代理转发出去,并将响应返回给前端。对于浏览器而言,请求始终是发给自己的域名,因此没有跨域问题。

踩坑记录:反向代理配置后,如果后端API响应头中包含了Location重定向信息,这个重定向地址可能是后端服务器的内网地址,导致前端跳转失败。需要在重写规则的操作中,勾选“重写所有请求头”或在后端避免返回此类重定向。

8. 部署常见问题与错误排查实录

即使按照步骤操作,依然可能遇到各种报错。下面是我遇到的一些典型问题及解决方法。

8.1 HTTP 错误 500.19 - Internal Server Error

这是IIS配置错误中最常见的一个。

  • 错误详情:通常伴随一个配置错误代码,如0x8007000d
  • 可能原因及解决
    1. IIS功能未安装:错误代码0x8007000doften indicates a malformed XML inweb.config. 但更常见的是因为web.config中引用了未安装的IIS模块。确保已安装“URL重写”模块。可以尝试暂时删除或重命名web.config文件,看错误是否消失来确认。
    2. 权限不足:应用程序池对网站目录没有读取权限。按照5.1节所述,为IIS_IUSRS组添加目录读取权限。
    3. web.config格式错误:XML标签未闭合或属性值格式错误。可以使用在线XML验证器检查。

8.2 静态资源(JS、CSS、图片)加载失败(404)

  • 症状:页面可以打开,但样式错乱,控制台报错找不到.js.css或字体文件。
  • 排查步骤
    1. 检查浏览器开发者工具的“网络”选项卡,看具体是哪个资源404,以及它请求的完整URL是什么。
    2. 对比这个请求URL和服务器上该资源的实际物理路径。
    3. 首要怀疑publicPath:99%的问题源于此。确认vue.config.js中的publicPath是否与你的实际访问路径匹配。如果应用通过http://server/app访问,publicPath必须是/app/
    4. 检查IIS的“MIME类型”。对于.woff2.woff.ttf等字体文件,IIS可能没有默认的MIME类型。可以按照6.2节在web.config中添加,或者在IIS的站点级或服务器级的“MIME类型”功能中添加。

8.3 路由刷新后页面空白或404

  • 症状:首页正常,点击内部链接跳转正常,但刷新页面或直接输入子路由URL后白屏或404。
  • 排查
    1. 确认URL重写规则已生效:访问一个不存在的路径(如/some-unknown-path),如果返回的是你的Vue应用首页(而不是IIS的404页面),说明规则生效。如果还是IIS的404,说明规则没起作用。
    2. 检查规则条件:确保重写规则的条件是“不是文件”且“不是目录”。如果条件设置反了,会导致所有请求(包括对静态资源的请求)都被重写到index.html,造成资源加载循环错误。
    3. 检查规则顺序:如果有多个重写规则(比如还有反向代理规则),确保Vue路由规则放在最后,或者设置了“停止处理后续规则”。规则是从上到下执行的。

8.4 控制台报错:Loading chunk xxx failed.

  • 症状:应用使用路由懒加载,在跳转某些页面时,控制台报错加载某个js块失败。
  • 原因:这通常是因为publicPath配置错误,或者资源文件在部署后发生了变更(如重新构建部署了),但用户浏览器还缓存着旧的index.html,它引用的chunk文件路径或哈希值已经不对了。
  • 解决
    1. 确保publicPath绝对正确。
    2. 检查服务器是否对index.html文件设置了正确的缓存策略。index.html应该设置为不缓存或极短时间缓存,而静态资源(js/css)可以设置长期缓存。可以在IIS的“HTTP响应头”里为index.html设置Cache-Control: no-cache

8.5 反向代理后API请求失败

  • 症状:配置了反向代理规则,但前端发起的API请求依然报错(404、500等)。
  • 排查
    1. 在IIS管理器中,进入“失败请求跟踪”功能(需先安装),启用对站点的跟踪,设置状态代码为400-999,然后重现错误。查看跟踪日志,可以看到请求在IIS内部流转的详细过程,判断是重写规则没匹配到,还是代理转发失败。
    2. 检查反向代理规则的模式(Pattern)是否正确。确保它匹配了你前端代码中实际请求的路径。
    3. 检查重写URL是否正确,后端服务器地址是否可达。
    4. 检查后端服务器防火墙是否放行了IIS服务器IP的入站请求。

部署是一个系统工程,尤其是将现代前端框架部署到传统Web服务器上,需要打通开发、构建、服务器配置多个环节。最关键的是理解每个配置项的意义:publicPath决定了资源怎么找,URL重写决定了请求怎么导,反向代理决定了API怎么转。当出现问题时,善用浏览器开发者工具、IIS的日志和失败请求追踪,从错误信息出发,逆向排查,总能找到问题的根源。希望这份结合了原理和实战踩坑经验的记录,能让你在部署Vue应用到IIS的路上少走些弯路。

← 返回列表