IIS服務器下做瀏覽器緩存

你的這個問題問得非常好,很多開發者在同時使用重寫和緩存時都會遇到。簡單來說:你添加的?<staticContent>?和?<clientCache> 配置本身不會影響或干擾?重寫規則的工作。它們各司其職,在 IIS 處理請求的不同階段發揮作用。

但是,根據你提供的配置和搜索結果,存在一個關鍵問題:由于你使用了 URL 重寫,<staticContent><clientCache>?里配置的緩存策略很可能無法對重寫后的請求生效12。

下面我用一個表格幫你快速了解這兩個模塊的工作順序和影響:

階段模塊/動作功能描述對你的配置的影響
1. 接收請求-用戶請求?/product/123IIS 收到對?product/123?的請求
2. URL 重寫 (Rewrite)rewrite?模塊重寫 URL。你的規則將所有非文件/目錄請求重寫到?index.php?s=.../product/123?→?index.php?s=/product/123
3. 處理請求-IIS 開始處理重寫后的新 URL?(index.php)此時請求已被交給 PHP 運行時處理,不再是靜態文件請求
4. 靜態文件緩存staticContent?模塊應用?<clientCache>?策略12此模塊只對靜態文件(如?.css,?.js, 圖片)有效。現在請求的是?index.php因此緩存策略被跳過

?? 為什么緩存會“失效”?

核心原因在于?IIS 處理管道(Pipeline)的順序模塊的職責范圍

  1. 重寫發生在前:你的?rewrite?規則首先執行,將原本像是請求靜態文件(如?/images/photo.jpg)的 URL,重寫到了?index.php?s=...?這個動態處理器。

  2. 靜態緩存檢測在后:隨后,staticContent?模塊會檢查當前被處理的資源(即重寫后的?index.php)是否是一個靜態文件。

  3. 動態資源不緩存:因為它發現當前請求最終是由 PHP 這樣的動態程序處理器處理的,而不是一個直接的靜態文件(如?.jpg?或?.css),所以?staticContent?模塊里配置的?clientCache?策略就不會被應用到這次請求的響應上12。

這意味著,雖然你的規則初衷很好,但對于那些經過重寫規則處理的、看似是靜態文件的 URL,預期的緩存頭(如?Cache-Control: max-age=2592000)并不會被發送到瀏覽器。

🔧 解決方案:使用?outboundRules?設置緩存頭

既然?staticContent?對重寫后的路徑無效,我們需要一個能在請求處理后期階段(即發送響應前)還能起作用的方法。IIS 的?outboundRules?(出站規則)就是完美選擇。

它允許你根據條件(如原始請求的 URL 模式)修改 HTTP 響應頭。

修改后的?web.config?配置示例

<configuration><system.webServer><staticContent><!-- 保留此處,它對直接請求的靜態文件(如CSS, JS)仍然有效 --><clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00" /></staticContent><rewrite><rules><rule name="url入口重寫" stopProcessing="true"><match url="^(.*)$" ignoreCase="false" /><conditions><add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /><add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /></conditions><action type="Rewrite" url="index.php?s={R:1}" /></rule></rules><outboundRules><!-- 添加出站規則:為特定類型的靜態文件添加緩存頭 --><rule name="Add Cache-Control for static files" preCondition="IsStaticFile" stopProcessing="false"><match serverVariable="RESPONSE_Cache_Control" pattern=".*" /><action type="Rewrite" value="public, max-age=2592000" /> <!-- 緩存30天 --></rule><preConditions><!-- 定義條件:判斷響應是否是圖片等靜態文件 --><preCondition name="IsStaticFile"><!-- 通過URL路徑匹配,而非文件物理路徑 --><add input="{REQUEST_URI}" pattern="\.(jpg|jpeg|png|gif|ico|svg|css|js|webp|avif)(\?.*)?$" /></preCondition></preConditions></outboundRules></rewrite><security><requestFiltering><requestLimits maxAllowedContentLength="52428800" /></requestFiltering></security></system.webServer>
</configuration>

特別提醒:如果你的網站做了CDN加速,以上代碼的staticContent不要做,要不會出現靜態文件加載與CDN沖突問題,整個頁面全亂了

📌 配置要點說明

  • 保留原?<staticContent>:它對于直接訪問的真正靜態文件(比如你的?style.css)依然有效。

  • outboundRules?是核心

    • 它在 IIS 輸出響應前工作,可以修改響應頭。

    • {REQUEST_URI}?服務器變量匹配的是用戶瀏覽器中看到的原始請求 URL(即重寫前的 URL,如?/files/image.jpg),而不是重寫后的路徑(index.php?...)。這正好解決了我們的問題。

    • 在?pattern?中,我使用了正則表達式?\.(jpg|jpeg...)(\?.*)?$?來匹配常見的靜態文件擴展名。(\?.*)??部分表示忽略可能存在的查詢字符串(如??v=123)。

    • 將?serverVariable?設置為?RESPONSE_Cache_Control,并通過?action?直接設置其值(public, max-age=2592000)。

💡 其他注意事項

  1. 性能與調試:出站規則會對匹配的所有響應生效,包括動態請求。規則條件要盡可能精確,避免不必要的性能開銷。配置后務必在瀏覽器開發者工具的“網絡”面板中檢查響應頭是否按預期添加。

  2. 文件存在性檢查(可選):如果你希望只為實際存在的靜態文件添加緩存頭,可以在?preCondition?中添加基于?{REQUEST_FILENAME}?和?IsFile?的條件。但這在重寫場景下可能較復雜,多數情況下匹配 URL 模式已足夠。

  3. 服務器級緩存:搜索結果567提到URL 重寫模塊可能會影響 IIS 服務器內核級別的輸出緩存。這意味著即使瀏覽器緩存正常工作,IIS 服務器自身對靜態文件的緩存(旨在提升性能)可能會因為重寫規則而被禁用。這是為了確保緩存邏輯正確。這一點通常無需普通開發者處理,但值得了解。


總而言之,你的配置不會“影響”重寫,但?staticContent?無法作用于重寫后的請求。最佳實踐是使用?outboundRules?來為經過重寫的靜態資源請求添加緩存頭

希望這些說明能幫你解決問題。如果還有其他疑問,歡迎隨時提出。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97988.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97988.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97988.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Flutter 3.35.2 以上版本中 數字轉字符串的方法指南

在 Flutter 3.35.2 (對應 Dart 2.19 及以上版本) 中&#xff0c;將數字轉換為字符串主要依賴于 Dart 語言本身提供的原生方法。這些方法穩定且向后兼容。下面我為你介紹幾種主要的方法和案例。 &#x1f522; 數字轉字符串的基本方法方法名適用類型描述常用場景toString()int, …

C#基礎(⑤ProcessStartInfo類和Process類)

1. 它是什么&#xff1f;ProcessStartInfo 是 C# 里的一個類&#xff08;屬于 System.Diagnostics 命名空間&#xff09;&#xff0c;作用是&#xff1a;定義要啟動的程序路徑&#xff08;比如 notepad.exe&#xff09;設置啟動時的參數&#xff08;比如打開哪個文件&#xff0…

《設計模式之禪》筆記摘錄 - 19.備忘錄模式

備忘錄模式的定義備忘錄模式(Memento Pattern)提供了一種彌補真實世界缺陷的方法&#xff0c;讓“后悔藥”在程界序的世界中真實可行&#xff0c;其定義如下&#xff1a;Without violating encapsulation, capture and externalize an objects internal state so that the obje…

22、Jenkins容器化部署Java應用

22、Jenkins容器化部署Java應用 1、準備Dockerfile 將Dockerfile文件放入項目目錄下 FROM registry.cn-hangzhou.aliyuncs.com/xx_blog/openjdk:21-jdk LABEL maintainer"xxqq.com" #復制打好的jar包 COPY target/*.jar /app.jar RUN apk add -U tzdata; \ ln -sf /…

基于單片機智能水龍頭/智能洗漱臺設計

傳送門 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目速選一覽表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目功能速覽 概述 該設計采用單片機作為核心控制器&#xff0c;結合紅外傳感器、水流傳感器和電磁閥等模塊&#xf…

GD32入門到實戰30--產品配置參數存儲方案 (EEPROM)

我們之前已經實現eeprom的驅動了&#xff0c;我們在應用層實現產品配置參數存儲方案我們要實現&#xff1a;原本設定的modebus從機&#xff08;單片機&#xff09;地址是01&#xff0c;存儲在eeprom里&#xff0c;按下按鍵后修改地址為03&#xff0c;重新上電modebus從機&#…

find_code 插件 react_vite

find_code 插件 react_vite const fs require("fs"); const path require("path"); const parser require("babel/parser"); const traverse require("babel/traverse").default; const generate require("babel/generator&…

手機秒變全棧IDE:Claude Code UI的深度體驗

還在為只能在命令行中使用Claude Code而苦惱嗎&#xff1f;想在移動設備上繼續你的AI編程對話嗎&#xff1f;Claude Code UI的出現徹底改變了這一切。這個開源項目為Anthropic官方的Claude Code CLI工具提供了現代化的Web界面&#xff0c;讓你能夠在任何設備、任何地方與AI編程…

F5發布后量子API安全解決方案,以AI驅動全面防護應對量子計算威脅

量子計算的飛速演進&#xff0c;正對傳統加密體系構成日益嚴峻的安全威脅。Gartner預測顯示&#xff0c;到2029年&#xff0c;量子計算機有望攻破目前普遍采用的公鑰加密算法&#xff0c;這一風險正倒逼全球企業加速密碼體系的更迭與升級。面對這一挑戰&#xff0c;F5公司——應…

深度剖析 DC - DC 轉換器在新能源汽車中的關鍵應用

在新能源汽車的發展進程中&#xff0c;DC - DC 轉換器扮演著至關重要的角色。以下將詳細介紹其在新能源汽車上的應用&#xff0c;包括作用、電路組成以及工作原理等方面。DC - DC 轉換器的作用簡單來說&#xff0c;新能源汽車上的 DC - DC 轉換器是一個 “降壓型電壓變換器”。…

【標準項目】在線五子棋對決(下)

在線五子棋對決一. 項目介紹及鏈接二. 項目結構設計項目模塊劃分業務處理模塊的子模塊劃分項目流程圖玩家流程圖服務器流程圖三. 數據管理模塊數據庫設計創建 user_table 類四. 在線用戶管理模塊五. 游戲房間管理模塊游戲房間類實現游戲房間管理類實現六. Session 管理模塊Sess…

重構導航之核:高德地圖的深度學習架構解析 導論:從數字化世界到可計算世界

導論&#xff1a;從數字化世界到可計算世界 數字地圖的演進&#xff0c;本質上是一場關于“世界可計算性”的持續探索。第一代地圖的核心任務是數字化轉錄&#xff08;Digital Transcription&#xff09;&#xff0c;它成功地將物理世界的靜態元素——道路、建筑、興趣點&#…

邏輯回歸(sigmoid函數、混淆矩陣、精確率召回率F1)

目錄 一、概述 1、邏輯回歸 2、激活函數 sigmoid函數 3、最大似然估計 二、邏輯回歸 1、原理 2、損失函數 3、代碼 三、混淆矩陣 1、定義 2、舉例 3、代碼 四、分類評估方法 1、精確率&#xff08;Precision&#xff09; 2、召回率&#xff08;Recall&#xff09; 3、F1&#…

Redis底層實現原理之五大基礎結構

文章目錄1. 基礎結構和編碼類型2. 編碼類型和數據結構實現2.1 字符串&#xff08;String&#xff09;2.2 壓縮列表&#xff08;listpack&#xff09;2.3 哈希表&#xff08;hashtable&#xff09;2.4 快速列表&#xff08;quicklist&#xff09;2.5 整數集合&#xff08;intset…

火山引擎數據智能體DataAgent總結分享

數據的冰山:看得見的資產與看不見的鴻溝 這張圖片用“冰山”類比的方式展示了數據資產管理中的可見與不可見問題,并突出了數據利用的核心挑戰與潛在陷阱。 1. 冰山之上的“看得見的資產” 內容:數據庫、報表、指標等結構化、顯性的數據資源。 核心挑戰: 需要從“采集存儲”…

100種高級數據結構 (速查表)

一、 基礎結構的擴展與組合 (Advanced Linear Structures) 這些結構在數組、鏈表、隊列、棧等基礎結構上增加了特定功能或約束。雙端隊列 (Deque - Double-Ended Queue) 介紹&#xff1a;允許在隊列的前后兩端都進行插入和刪除操作的線性結構。應用場景&#xff1a;工作竊取算法…

一個開源的企業官網簡介

簡介一個完美的企業官網系統,支持手機端和電腦端展示企業風采,還可以展示企業產品/企業新聞資訊等等.普通用戶PC端展示普通用戶手機端展示管理后臺

TCP實現線程池競爭任務

服務端&#xff1a;#include<stdio.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<netinet/ip.h> #include<strings.h> #include<unistd.h> #include<ctype.h> #include<arpa/inet.h&…

Redis C++ 實現筆記(F篇)

Implementing Redis in C : F Redis C 實現筆記&#xff08;F篇&#xff09; 前言 本章代碼及思路均來自Build Your Own Redis with C/C 本文章只闡述我的理解想法&#xff0c;以及需要注意的地方。 本文章為續<<Implementing Redis in C : E>>所以本文章不再…

finally 與 return的執行順序

一、第一次試驗public static void main(String[] args) throws InterruptedException {System.out.println(aaa(null));}private static StringBuilder aaa(Integer i) throws InterruptedException {StringBuilder sb new StringBuilder();try {i.toString();return sb;} ca…