ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Vue项目部署IIS:web.config重写与404、500.19排查

Vue项目部署IIS:web.config重写与404、500.19排查 前端项目写完之后最后一步往往就卡在“怎么让它在服务器上跑起来”。这两年我经手过不少后台管理系统、数据看板、内部工具打包产物是 Vue 的 dist 目录服务器却是客户机房里那台装着 Windows Server 的物理机运维同事只会 IIS不想也不会给你装 Docker、装 Nginx。这种时候把 Vue 项目部署到 IIS 上就是最现实的选择。这篇内容就是把这套流程完整拆一遍从 IIS 功能勾选、应用程序池配置、web.config 重写规则到刷新页面 404、500.19 配置锁定、应用程序池权限报错 0x80005000 这些坑全部讲透。不管你是刚把第一个 Vue 项目打包完的新手还是被 history 路由折腾过一下午的老手都能从里面找到能直接抄的配置。1. 先把部署链路想清楚Vue 产物和 IIS 的配合逻辑很多人部署失败不是命令敲错了而是压根没搞明白自己在部署什么。把 Vue 项目丢到 IIS 上跟把 PHP 项目丢上去完全是两回事理解这一点能省掉后面一半的排查时间。1.1 Vue 打包后到底生成了哪些东西执行npm run build之后你拿到的 dist 目录本质上就是一包纯静态文件一个index.html、一个带哈希值的assets目录里面是 js、css、字体、图片可能还有 favicon、manifest.json、robots.txt 这些零碎文件。Vue CLI 默认输出到distVite 也是dist可以在配置里改。关键在于这些文件之间是靠相对或绝对路径互相引用的。index.html里会写script src/assets/index-a1b2c3.js这个/开头代表站点根目录。如果你的站点没建在根路径而是挂在http://server.com/admin/下面这个/assets/...就会指向http://server.com/assets/...直接 404页面白屏。这是新手最容易踩的第一个坑后面第二章节会专门讲怎么改。还有一点Vue 是单页应用SPA。整个站点物理上只有一个真实的 HTML 文件就是index.html。用户在页面上点到/user/list、/order/detail/123这些路径都是前端路由vue-router用 JavaScript 在浏览器里动态渲染出来的服务器上并不存在user/list这个目录也没有order/detail/123这个文件。用户在页面内点击跳转没问题因为路由被 JS 拦截了但一旦用户按 F5 刷新或者直接把链接复制给别人打开浏览器就会发一个真实请求给 IISIIS 去磁盘上找D:\site\user\list找不到返回 404。所以 IIS 部署 Vue 的核心矛盾就一句话服务器只认识 index.html但用户会请求任意路由路径。解决它的手段只有一个字重写Rewrite。把“文件不存在的请求”统统交给index.html剩下的交给前端路由自己处理。1.2 为什么有人建议干脆用 Nginx 或者 Node 托管我见过不少人说“Vue 就该用 Nginx 部署”这话有一定道理。Nginx 的try_files $uri $uri/ /index.html;一行配置就解决了重写问题而 IIS 需要额外装 URL Rewrite 模块、还要写 XML 规则确实更绕。Node 方案则是直接跑一个 Express 服务读 dist 目录也一样能解决。但现实情况是很多单位的服务器是 Windows Server 2019/2022上面已经跑着 IIS可能还有 .NET 的老站点、别的部门的系统端口 80/443 已经被 IIS 占了。再装一个 Nginx 监听 8080然后做端口转发反而更乱。更不用说加上 IIS 的 Windows 身份验证、IP 限制、日志审计能力这些东西在内网环境下往往比“配置简单”重要得多。所以我的判断是服务器是 Windows 且已经跑了 IIS那就老老实实配 IIS别为了绕开一个 web.config 去引入新的技术栈。真正要做的是把重写规则、缓存策略、权限这几件事配明白。1.3 部署前你需要确认的几件事动手之前把下面这张清单过一遍能省下大量来回折腾的时间。检查项说明不满足的后果IIS 已安装服务器管理器 → 添加角色和功能 → Web 服务器(IIS)没有 IIS 管理器可用URL Rewrite 模块微软官网下载独立安装包装完需重启 IIS 管理器500.19 配置错误直接打不开站点静态内容功能IIS 功能里勾选“静态内容”403.14 或 404.3静态文件读不了默认文档配置添加 index.html 到默认文档列表访问根路径显示目录列表或 403应用程序池模式建议“无托管代码”无谓地加载 .NET 运行时目录读权限IIS_IUSRS 对站点目录有读取权限401.3 拒绝访问这张表看着简单但我可以负责任地说至少七成的部署失败案例问题都出在这六行里的某一行。尤其是 URL Rewrite 模块很多人以为装了 IIS 就自带实际上它是需要单独下载安装的扩展组件装完之后 IIS 管理器里才会多出“URL 重写”这个图标。2. 环境准备功能组件、模块和打包参数环境这一步做扎实后面基本就是复制粘贴。我习惯把 IIS 配置和前端打包配置分成两条线来看因为它们解决的是不同层面的问题IIS 负责“请求怎么被处理”打包配置负责“资源路径长什么样”。2.1 安装 IIS 并勾选关键功能在 Windows Server 上路径是服务器管理器 → 管理 → 添加角色和功能 → 一路下一步到“服务器角色” → 勾选“Web 服务器(IIS)”。在 Windows 10/11 专业版上则是控制面板 → 程序和功能 → 启用或关闭 Windows 功能 → Internet Information Services。勾选的时候很多人图快直接全勾我不建议这么干。全勾会把 FTP 服务器、WebDAV、各种开发诊断组件都装上去攻击面变大而且某些组件比如 WebDAV还会干扰正常的静态文件请求——WebDAV 模块会拦截 PUT/DELETE 之类的方法某些情况下甚至影响 GET 的处理顺序。我一般只勾这些Web 服务器 → 常见 HTTP 功能静态内容、默认文档、目录浏览可选、HTTP 错误、HTTP 重定向Web 服务器 → 性能静态内容压缩、动态内容压缩Web 服务器 → 安全性请求筛选、Windows 身份验证内网需要域账号登录时勾Web 服务器 → 应用程序开发一般不需要勾 ASP.NET除非同一台机器还有 .NET 站点管理工具 → IIS 管理控制台必须勾否则没有图形界面装完之后浏览器打开http://localhost能看到 IIS 的默认欢迎页说明基础环境没问题。2.2 URL Rewrite 模块一个必须单独装的组件这一步是重灾区。IIS 装好之后IIS 管理器里是没有“URL 重写”图标的必须去微软官网下载URL Rewrite Module 2.1注意是 2.1 版本2.0 在 Server 2022 上有兼容问题安装包很小装完重启 IIS 管理器就能看到。怎么验证装成功了在 IIS 管理器里点开任意一个站点功能视图里能看到“URL 重写”图标就行。或者直接用命令行验证%windir%\system32\inetsrv\appcmd.exe list config -section:system.webServer/rewrite如果提示“找不到请求的节”说明模块没装好如果正常返回配置内容哪怕是空的说明模块已就位。注意URL Rewrite 模块是服务器级别的装一次所有站点都能用。但如果你在 web.config 里写了 rewrite 规则而目标服务器没装这个模块站点会直接抛 500.19连静态文件都打不开报错信息里会写“无法读取配置节 rewrite因为它缺少节声明”。2.3 打包配置publicPath 和 base 到底该填什么这是前端侧唯一需要改的地方但改错了就是白屏。分两种情况情况一站点部署在根路径比如http://192.168.1.10/那资源路径保持默认就行。Vue CLI 3vue.config.js里publicPath: /默认值可不写Vitevite.config.js里base: /默认值可不写情况二站点部署在子目录比如http://192.168.1.10/admin/必须显式指定。Vue CLIpublicPath: /admin/Vitebase: /admin/注意必须以斜杠开头也必须以斜杠结尾。写成admin/会变成相对路径在嵌套路由下解析错乱写成/admin不带尾部斜杠拼接出来的资源地址会变成/adminassets/xxx.js一样 404。这个细节我踩过排查了快一个小时才发现少了个斜杠。配置改完重新npm run build然后打开 dist/index.html 看一眼源码确认里面的引用是/admin/assets/index-xxxx.js这种形式就对了。另外提一句如果你的项目用了 hash 路由模式地址栏带#比如http://site/#/user那 IIS 这边不需要任何重写规则因为#后面的内容根本不会发给服务器。但 hash 模式地址难看SEO 也不友好大部分后台系统还是用 history 模式。下面讲的内容默认都是 history 模式。2.4 关闭 source map 和拆分策略的小建议上线前顺手检查两件事。一是生产构建别带 source map默认productionSourceMap: false或者 Vite 里build.sourcemap: false否则你的源码会原样暴露在生产环境的浏览器里内网项目也建议关掉。二是如果项目比较大dist 里可能出现几十个 chunk 文件。这本身没问题但要留意 IIS 的 MIME 类型.js、.css、.woff2、.svg这些 IIS 默认都认识但有几类扩展名在部分系统上会被漏掉比如.mjs、.wasm、.json在极老版本的 IIS 上可能缺失遇到的时候在 web.config 里补静态内容映射就行第四章节会给出具体写法。3. 建站实操从应用程序池到 web.config 的完整配置这一章是整套流程的核心我把每一步的操作顺序和背后的原因都写清楚你可以照着做。3.1 应用程序池为什么一定要选“无托管代码”打开 IIS 管理器左侧展开服务器节点右键“应用程序池” → 添加应用程序池。名称vue-admin-pool自己起别用中文和空格.NET CLR 版本无托管代码No Managed Code托管管道模式集成Integrated启动模式AlwaysRunning可选减少首次访问的冷启动为什么选“无托管代码”因为 Vue 的 dist 里全是静态文件IIS 只需要把它们原样读出来发给浏览器根本不需要加载 .NET 运行时。如果选了 v4.0IIS 会为每个请求初始化 CLR白白吃掉几十兆内存进程启动也更慢。这个选项不影响任何静态文件服务能力放心选。“托管管道模式”选集成是 IIS 7 之后的推荐模式重写规则和请求筛选都在这个模式下工作得最好。这里还有几个默认参数值得改一下参数默认值建议值原因闲置超时20 分钟0不超时内网系统访问间隔长避免频繁回收固定时间间隔回收1740 分钟保持或按需定期回收可释放内存碎片最大工作进程数11静态站不需要 Web Garden队列长度1000保持静态文件响应快很少堆积改闲置超时这一步我强烈建议做。有一次部署完后用户反馈“每天早上第一次打开特别慢”就是这个 20 分钟闲置回收导致的进程被回收后第一次请求要重新启动工作进程加上磁盘冷读体验很差。3.2 网站绑定与物理路径右键“网站” → 添加网站网站名称vue-admin应用程序池选刚才建的vue-admin-pool物理路径指向你放 dist 内容的目录比如D:\wwwroot\vue-admin绑定类型 httpIP 地址“全部未分配”端口填一个没被占用的比如 8080主机名可以留空关于物理路径的一个重要提醒不要直接把路径指向D:\project\vue-admin\dist而是先把 dist 里的内容复制到D:\wwwroot\vue-admin或者单独建立发布目录。原因有两个一是开发目录里有 node_modules、src、.git权限混乱且体积巨大二是有时候开发机就是服务器本身直接指向 dist 的话下次构建会覆盖但如果构建失败站点就成了半成品状态。如果想让流程更规范可以用符号链接或者直接用 CI 复制但手工部署的场景下一个干净的发布目录是最省心的。绑定端口这里如果 80 端口没被占用可以直接用 80。如果是内网多站点建议用不同端口或者主机名区分别去动默认站点的绑定容易把别人的站点搞挂。3.3 目录权限只给读权限就够了吗网站的物理目录默认继承上级目录的 NTFS 权限大多数情况下 IIS_IUSRS 已经有了读取权限。但如果你是从别的地方 copy 过来的目录或者自己新建的目录结构权限可能没继承好。右键目录 → 属性 → 安全 → 编辑 → 添加 → 输入IIS_IUSRS→ 确定然后只勾读取和执行、列出文件夹内容、读取这三项。注意千万别为了让程序“跑起来”就把 Everyone 加进去给完全控制这是内网安全审计最喜欢抓的问题。Vue 站点是纯静态的读取权限完全够用。只有当日志写入应用目录或者有上传功能时才需要额外给写权限那也应该精确到具体子目录。这里顺便说一下热词里提到的那个经典报错——“应用程序池权限设置失败请手动为其设置 LocalSystem 权限未知错误(0x80005000)”。这个报错通常出现在两种场景一是你尝试在 IIS 管理器里修改应用程序池标识但服务器不在域里或者输入的用户名格式不对比如该写.\username却写了username二是应用程序池标识指向了一个已经被删除或禁用的账户。0x80005000 本质上是 ADSI 层的错误码代表“找不到对象”跟权限本身关系不大是账户解析失败。正确的处理方式是检查应用程序池 → 高级设置 → 进程模型 → 标识如果是自定义账户确认用户名格式为计算机名\用户名或.\用户名如果不需要模拟特定账户直接改回ApplicationPoolIdentity即可如果确实需要 LocalSystem极少见通常是为了访问网络共享注意这是高权限账户等同于服务器管理员能不用就不用我见过有人为了解决一个读文件失败直接把应用程序池标识改成 LocalSystem问题确实没了但这个池如果被攻破攻击者直接拿到系统权限。正确做法是把需要的目录权限授予IIS AppPool\vue-admin-pool这个虚拟账户而不是给整个池提权。3.4 默认文档把 index.html 排到第一位站点 → 双击“默认文档”你会看到Default.htm、Default.asp、index.htm、iisstart.htm等。Vue 的入口是index.html如果列表里没有需要手动添加如果有建议把它移到最上面。为什么强调顺序因为默认文档是按列表顺序逐个尝试的如果目录下同时存在index.htm和index.html某些模板会带IIS 会先命中原生的那个导致你看到的是旧内容或者 404。把index.html置顶最保险。3.5 web.config整套方案里最关键的一个文件在站点根目录也就是放 index.html 的那个目录新建web.config内容如下。这是我在多个项目里验证过的最小可用版本?xml version1.0 encodingUTF-8? configuration system.webServer !-- 1. 默认文档 -- defaultDocument files clear / add valueindex.html / /files /defaultDocument !-- 2. history 路由重写文件/目录不存在时交给 index.html -- rewrite rules rule nameVue Router History Mode stopProcessingtrue match url(.*) / conditions logicalGroupingMatchAll add input{REQUEST_FILENAME} matchTypeIsFile negatetrue / add input{REQUEST_FILENAME} matchTypeIsDirectory negatetrue / add input{REQUEST_URI} pattern^/api/ negatetrue / add input{REQUEST_URI} pattern^/admin/api/ negatetrue / /conditions action typeRewrite url/index.html / /rule /rules /rewrite !-- 3. 缓存策略带哈希的静态资源长缓存index.html 不缓存 -- staticContent clientCache cacheControlModeUseMaxAge cacheControlMaxAge365.00:00:00 / remove fileExtension.json / mimeMap fileExtension.json mimeTypeapplication/json / remove fileExtension.woff / mimeMap fileExtension.woff mimeTypefont/woff / remove fileExtension.woff2 / mimeMap fileExtension.woff2 mimeTypefont/woff2 / /staticContent !-- 4. 压缩 -- httpCompression staticTypes add mimeTypeapplication/javascript enabledtrue / add mimeTypetext/css enabledtrue / add mimeTypeapplication/json enabledtrue / add mimeTypeimage/svgxml enabledtrue / /staticTypes /httpCompression !-- 5. index.html 单独禁止缓存 -- httpProtocol customHeaders add nameX-Content-Type-Options valuenosniff / /customHeaders /httpProtocol /system.webServer /configuration如果你部署在子目录/admin/把规则里的url/index.html改成url/admin/index.html同时在conditions里加一条排除/admin/api/的规则避免接口请求被吞掉。这段配置里有几个点需要展开说。关于{REQUEST_FILENAME}的两个否定条件。IsFile和IsDirectory都要negatetrue意思是“这个路径既不是真实文件也不是真实目录”的时候才重写。为什么不只判断文件因为如果请求的是一个真实存在的目录比如 assets 目录本身重写成 index.html 反而是错的。两个都判断最稳妥。关于排除 API 路径。前后端分离的项目里前端站点经常要代理/api到后端服务。如果不排除后端接口返回 404 的时候请求会被重写成 index.html前端拿到一堆 HTML 内容去 JSON.parse报出莫名其妙的语法错误。这个坑我见过太多次。排除规则用^/api/正则即可注意别写成^/api否则/apixxx也会被排除。关于clientCache。这是个站点级的全局缓存设置配合 Vite 或 Vue CLI 生成的哈希文件名index-a1b2c3.js可以实现“内容变了文件名就变浏览器自动重新下载”。但index.html绝对不能长缓存否则用户永远拿到旧版本。所以更精细的做法是把全局 clientCache 设短一点比如 7 天然后在 assets 子目录里单独放一个 web.config 设长缓存。3.6 assets 子目录的独立缓存配置在dist/assets/目录下再放一个 web.config?xml version1.0 encodingUTF-8? configuration system.webServer staticContent clientCache cacheControlModeUseMaxAge cacheControlMaxAge365.00:00:00 / /staticContent /system.webServer /configuration这样index.html走站点根目录的短缓存assets 里的哈希文件走一年长缓存。每次发版只要 index.html 更新了浏览器就会拿到新的资源引用命名带哈希的新文件会重新下载老文件在缓存里也无所谓。4. 常见报错与排查实录这一章是我最想写的部分因为前面三章的内容文档里都能查到但真正让人崩溃的是那些“看起来一样、原因完全不同”的报错。4.1 页面白屏、刷新 404、资源加载失败这三个现象经常被混为一谈但成因完全不同先看这张速查表现象根本原因定位方法解决方式打开首页就白屏控制台 404资源路径不对看 Network 里 js 请求的 URL修正 publicPath / base首页正常点进子路由刷新后 404缺少重写规则确认 web.config 是否生效加 rewrite 规则首页正常子路由刷新后显示首页内容重写规则写错了把 assets 也重写了看 Network 里 js 返回的 Content-Type 是 text/html加 IsFile/IsDirectory 条件打开是 IIS 欢迎页默认文档没配或顺序不对检查默认文档列表把 index.html 置顶打开显示目录列表目录浏览被启用且没有默认文档站点功能里看目录浏览状态关闭目录浏览配好默认文档第二行和第三行的区别特别关键。刷新后 404说明请求根本没被重写规则没生效刷新后显示首页内容但路由不对说明重写发生了但把不该重写的也重写了。后者更隐蔽因为页面“看起来是好的”但用户一刷新就回到首页体验很差。如果重写规则没生效排查顺序是一确认 URL Rewrite 模块装了二确认 web.config 在站点根目录而不是子目录三确认 web.config 的编码是 UTF-8 无 BOM有 BOM 会导致解析失败四浏览器强刷清缓存IIS 管理器里点“重新启动”站点。我遇到过一次是文件保存成了 UTF-8 with BOMIIS 直接报 500.19报错信息里明确写了“配置错误”但很容易被忽略。4.2 500.19 配置错误三个高频成因500.19 是 IIS 部署里最典型的报错它的含义是“配置文件有非法内容”。三种情况最常见第一种rewrite 节未声明。服务器没装 URL Rewrite 模块而 web.config 里写了rewrite。解决办法就是装模块或者临时把 rewrite 段注释掉验证。第二种节被锁定overrideModeDefault。有些节比如httpCompression、staticContent的部分子节点在 applicationHost.config 里被设置为不允许在站点级别覆盖写进 web.config 就会报 500.19报错信息里会指明具体是哪个节。解决办法有两个一是用 IIS 管理器的“配置编辑器”在服务器级别修改二是在%windir%\system32\inetsrv\config\applicationHost.config里把对应节的overrideModeDefault改成Allowsection namehttpCompression overrideModeDefaultAllow /注意改 applicationHost.config 之前一定要备份这个文件是 IIS 的全局配置改坏了所有站点都起不来。改完执行iisreset或者net stop was /y net start w3svc让它生效。第三种编码问题。web.config 必须是 UTF-8 无 BOM。用记事本另存为的时候注意编码选项推荐用 VS Code 或 Notepad 保存并确认编码格式。4.3 401.3、403.14、404.3 这三个经典错误401.3 未经授权IIS 进程账户没有读取该目录的权限。检查 IIS_IUSRS 权限或者检查目录是否在一个拒绝继承的路径下。还有一种可能是目录在用户桌面上或者 C 盘某些受保护位置建议统一放到D:\wwwroot这类独立盘符下。403.14 目录列表被拒绝说明请求命中了目录但默认文档没找到。检查 index.html 是否在根目录、默认文档列表里是否有它。404.3 MIME 类型被拒绝这是静态文件的扩展名没有对应的 MIME 映射。常见于.woff2、.wasm、.mjs、.json老版本 IIS。在 web.config 的staticContent里加 mimeMap 就行前面给的模板里已经包含了常见项。补一个排查技巧这三个错误如果在浏览器里看到的信息很简略可以打开 IIS 的“错误页”功能把详细错误信息设置为“本地请求显示详细错误、远程请求显示自定义错误”这样在服务器本机用浏览器访问就能看到具体的错误模块和错误码定位效率高很多。4.4 接口跨域和反向代理前后端分离项目部署到同一个 IIS 下最省事的方案就是让 IIS 做反向代理把/api转发到后端服务比如本机的 8080 端口 Node 服务或者 9000 端口的后端。这需要两个东西Application Request RoutingARR模块以及 URL Rewrite。ARR 装完之后在 IIS 管理器根节点上双击“Application Request Routing Cache” → 右侧“Server Proxy Settings” → 勾选 “Enable proxy”然后应用。web.config 里加一条代理规则rule nameAPI Proxy stopProcessingtrue match url^api/(.*) / action typeRewrite urlhttp://127.0.0.1:9000/{R:1} / /rule这条规则要放在 history 重写规则之前因为 rewrite 规则是按顺序匹配的前面的命中后如果stopProcessingtrue就不再往下走。如果不想折腾 ARR另一个方案是后端自己开 CORS前端请求直接打后端地址。内网环境下两者都行但反向代理的好处是前端代码里写/api就行不用区分开发环境和生产环境的域名。注意启用 ARR 代理后如果规则写得过于宽泛比如^.*可能把静态资源的请求也代理出去导致页面彻底打不开。规则的正则一定要写精确。4.5 发版后用户还看到旧页面这是上线之后最常被投诉的问题。原因通常是浏览器缓存了旧的index.html或者中间有 CDN/代理缓存。排查思路先在服务器上用curl -I http://localhost/index.html看响应头确认Cache-Control是不是no-cache或者很短的 max-age。如果是长缓存说明站点级的 clientCache 设置把 index.html 也覆盖了。前面给的方案是站点级设短缓存、assets 设长缓存。更严格的做法是给 index.html 单独加 outboundRules 或者 URL Rewrite 设置响应头但在实际项目里站点级设cacheControlMaxAge7.00:00:00配合 assets 子目录的独立配置实践中已经够用了。另外提醒一句如果前端项目里用了 Service WorkerPWA 插件缓存策略会更复杂SW 会在客户端拦截请求。遇到这类项目发版的时候要在构建配置里处理好 SW 的版本更新否则用户可能要清好几次缓存。这类项目我一般会在发版后主动告诉用户按 CtrlF5 强刷一次比反复解释原理管用。5. 上线之后的优化与运维小技巧站点能打开只是及格线真正体现水平的是后续的稳定性、可维护性和出问题时的恢复速度。5.1 开启静态压缩体积能省一半以上Vue 打包出来的 js 文件动辄几百 KB 到一两兆开启压缩后传输体积通常能降到三分之一。IIS 的静态压缩在“服务器 → 压缩”功能里配置勾选“启用静态内容压缩”然后设置staticCompressionLevel默认 7范围 0-9越高越省带宽但更耗 CPU。httpCompression directory%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files scheme namegzip dll%Windir%\system32\inetsrv\gzip.dll staticCompressionLevel9 / staticTypes add mimeTypetext/* enabledtrue / add mimeTypeapplication/javascript enabledtrue / add mimeTypeapplication/json enabledtrue / add mimeTypeimage/svgxml enabledtrue / /staticTypes /httpCompression要注意的是压缩和缓存配合使用时有个坑IIS 会把压缩后的版本缓存到临时目录如果磁盘满了或者临时目录权限不对压缩会静默失败甚至报 500。所以启用之后务必用浏览器的 Network 面板确认响应头里有Content-Encoding: gzip而不是只看配置文件。5.2 日志、备份与快速回滚日志IIS 默认日志在%SystemDrive%\inetpub\logs\LogFiles\W3SVC{站点ID}是按天分文件的。查问题时用记事本打开太痛苦推荐装一个 Log Parser 或者直接用 PowerShell 过滤Get-Content .\u_ex250315.log | Select-String 404 日志里重点关注sc-status状态码、cs-uri-stem请求路径、time-taken耗时。如果发现大量 404 集中在某个路径模式上基本就能定位到是哪类资源没配好。备份IIS 的配置备份是个容易被忽略但极其重要的环节。有两种粒度一是配置级备份用 appcmd 导出整个 IIS 配置%windir%\system32\inetsrv\appcmd.exe list config /xml D:\backup\iis-config-backup.xml恢复的时候用appcmd.exe add config /in file或者直接替换 applicationHost.config。IIS 管理器里也有图形化的“共享配置”导出功能可以导出为加密文件迁移到另一台服务器时特别方便。二是站点级备份其实就是把发布目录整个打包。我的习惯是在发布目录旁边建一个releases文件夹每次发版把当前版本压缩成vue-admin-20250315.zip保留最近五个版本。线上出问题时解压上一个版本覆盖回去一分钟内完成回滚比重头排查快得多。提示备份文件不要放在站点目录里面否则会被人通过 URL 直接下载。放到站点物理路径之外的目录比如D:\backup\。5.3 一些零碎但实用的经验关于汉字目录名和空格。站点物理路径里不要出现中文、空格、特殊符号。IIS 在某些情况下对含空格路径的处理会有问题特别是配合 URL Rewrite 的时候反代路径拼接容易出错。统一用英文小写加短横线的命名。关于端口和防火墙。建站后如果只能本机访问外部访问不了先检查 Windows 防火墙的入站规则有没有放行对应端口。快速验证方式是netstat -ano | findstr :8080看端口是否在监听如果监听正常但外部不通那基本就是防火墙问题。关于并发和连接数。静态文件站点的性能瓶颈通常不在 IIS而在磁盘 IO 和带宽。如果站点访问量大可以考虑把 dist 目录放到 SSD 上或者前面挂一层缓存。IIS 本身的并发处理能力对内网几百人的规模来说是绰绰有余的。关于部署到子目录时的一个细节。如果你在同一个 IIS 站点下挂多个 Vue 应用比如/admin/和/portal/记得每个子目录都要有独立的 web.config并且重写规则的url要指向各自的index.html。同时publicPath也要分别配置。这三个地方打包配置、目录结构、web.config必须一致缺一个就会出问题。关于 CI 自动化。手工部署一两次还行次数多了必然出错。如果团队有条件可以用 Jenkins 或者 GitLab Runner 在 Windows 上跑构建脚本拉代码、npm install、npm run build、robocopy 到发布目录、调用appcmd recycle apppool回收应用程序池。这套流程跑通之后手工部署的错漏基本就绝迹了。最后说一下我自己的体会。IIS 部署 Vue 这件事难点从来不在技术本身而在于信息不对称——前端开发者不熟悉 IIS 的配置层级运维同学不理解 history 路由为什么需要重写。把这层窗户纸捅破之后整套流程其实非常稳定一台 Server 2019 的机器配好之后连续跑一年多不出问题是很正常的。真正需要花心思的是第一次配的时候把 web.config 写扎实把权限收干净把缓存分层理清楚。这三件事做完了后面就只剩下发版和回滚两个动作轻松得很。
返回列表