คอมพิวเตอร์ Windows อินเทอร์เน็ต

แคชสไตล์ วิธีลบการแคชไฟล์ css และ js การรีเฟรชหน้าบางครั้งช่วยประหยัด

การรวม CSS และ Javascript ภายนอก ทำให้เราต้องการให้มีคำขอ HTTP ที่ไม่จำเป็นเหลือน้อยที่สุด

สำหรับสิ่งนี้ ไฟล์ .js และ .css จะมีส่วนหัวที่ให้การแคชที่เชื่อถือได้

แต่ถ้าไฟล์เหล่านี้มีการเปลี่ยนแปลงระหว่างการพัฒนาล่ะ ผู้ใช้ทุกคนมีเวอร์ชันเก่าในแคช - จนกว่าแคชจะล้าสมัย การร้องเรียนจำนวนมากจะเกิดขึ้นเกี่ยวกับการรวมเซิร์ฟเวอร์และชิ้นส่วนไคลเอ็นต์ที่เสียหาย

วิธีที่ถูกต้องในการแคชและการกำหนดเวอร์ชันช่วยขจัดปัญหานี้ได้อย่างสมบูรณ์ และทำให้แน่ใจได้ว่าการซิงโครไนซ์เวอร์ชันสไตล์ / สคริปต์ที่เชื่อถือได้และโปร่งใส

แคช ETag อย่างง่าย

วิธีที่ง่ายที่สุดในการแคชทรัพยากรแบบคงที่คือการใช้ ETag

เพียงพอที่จะเปิดใช้งานการตั้งค่าเซิร์ฟเวอร์ที่เหมาะสม (สำหรับ Apache จะเปิดใช้งานโดยค่าเริ่มต้น) - และ ETag จะมอบให้กับแต่ละไฟล์ในส่วนหัว - แฮชที่ขึ้นอยู่กับเวลาอัปเดต ขนาดไฟล์และ (บนระบบไฟล์ที่ใช้ไอโหนด ) ไอโหนด

เบราว์เซอร์จะแคชไฟล์ดังกล่าว และระบุส่วนหัว If-None-Match จาก ETag ของเอกสารที่แคชไว้ เมื่อได้รับส่วนหัวดังกล่าว เซิร์ฟเวอร์สามารถตอบกลับด้วยรหัส 304 จากนั้นเอกสารจะถูกนำออกจากแคช

ดูเหมือนว่านี้:

คำขอแรกไปยังเซิร์ฟเวอร์ (ล้างแคช) GET /misc/pack.js HTTP / 1.1 โฮสต์: site

โดยทั่วไป เบราว์เซอร์มักจะเพิ่มส่วนหัว เช่น User-Agent, Accept เป็นต้น พวกเขาถูกตัดให้สั้นลง

การตอบสนองของเซิร์ฟเวอร์ เซิร์ฟเวอร์ส่งในการตอบกลับเอกสารที่มีรหัส 200 และ ETag: HTTP / 1.x 200 ตกลง การเข้ารหัสเนื้อหา: gzip ประเภทเนื้อหา: ข้อความ / javascript; ชุดอักขระ = utf-8 Etag: "3272221997" ช่วงที่ยอมรับ: ไบต์ ความยาวเนื้อหา: 23321 วันที่: วันศุกร์ 02 พฤษภาคม 2551 17:22:46 น. GMT เซิร์ฟเวอร์: lighttpd คำขอเบราว์เซอร์ถัดไป คำขอเบราว์เซอร์ถัดไปในคำขอถัดไป เบราว์เซอร์เพิ่มถ้าไม่มีการจับคู่: (แคช ETag): GET /misc/pack.js HTTP / 1.1 โฮสต์: ไซต์ If-None-Match: "45370005" การตอบสนองของเซิร์ฟเวอร์ เซิร์ฟเวอร์กำลังค้นหา - ใช่ เอกสารไม่มีการเปลี่ยนแปลง ซึ่งหมายความว่าคุณสามารถออกรหัส 304 และไม่ส่งเอกสารอีก HTTP / 1.x 304 ไม่ได้แก้ไขการเข้ารหัสเนื้อหา: gzip Etag: "45370005" ประเภทเนื้อหา: ข้อความ / javascript; charset = utf-8 ยอมรับช่วง: ไบต์ วันที่: อังคาร 15 เมษายน 2008 10:17:11 GMT

อีกทางหนึ่ง หากเอกสารมีการเปลี่ยนแปลง เซิร์ฟเวอร์จะส่ง 200 พร้อม ETag ใหม่

บันเดิล Last-Modified + If-Modified-Since ทำงานในลักษณะเดียวกัน:

  1. เซิร์ฟเวอร์ส่งวันที่แก้ไขล่าสุดในส่วนหัว Last-Modified (แทน ETag)
  2. เบราว์เซอร์แคชเอกสาร และในคำขอถัดไปสำหรับเอกสารเดียวกัน จะส่งวันที่ของเวอร์ชันแคชในส่วนหัว If-Modified-Since (แทนที่จะเป็น If-None-Match)
  3. เซิร์ฟเวอร์ตรวจสอบวันที่ และถ้าเอกสารไม่เปลี่ยนแปลง จะส่งเฉพาะรหัส 304 ไม่มีเนื้อหา

วิธีการเหล่านี้ทำงานได้อย่างเสถียรและดี แต่เบราว์เซอร์ต้องดำเนินการตามต้องการสำหรับแต่ละสคริปต์หรือสไตล์

แคชอัจฉริยะ การกำหนดเวอร์ชัน

แนวทางทั่วไปสำหรับการกำหนดเวอร์ชันนั้นสรุปโดยย่อ:

  1. เพิ่มเวอร์ชัน (หรือวันที่แก้ไข) ให้กับสคริปต์ทั้งหมด ตัวอย่างเช่น http: // เว็บไซต์ / my.jsจะกลายเป็น http: //site / my.v1.2.js
  2. สคริปต์ทั้งหมดถูกฮาร์ดแคชโดยเบราว์เซอร์
  3. เมื่อสคริปต์ถูกอัปเดต เวอร์ชันจะเปลี่ยนเป็นเวอร์ชันใหม่: http: // site / my.v2.0.js
  4. ที่อยู่มีการเปลี่ยนแปลงดังนั้นเบราว์เซอร์จะขอและแคชไฟล์อีกครั้ง
  5. เวอร์ชันเก่า 1.2 จะค่อยๆ หลุดออกจากแคช

ฮาร์ดแคช

ฮาร์ดแคช- ค้อนขนาดใหญ่ชนิดหนึ่งที่ตอกย้ำคำขอไปยังเซิร์ฟเวอร์สำหรับเอกสารที่แคชไว้อย่างสมบูรณ์

ในการดำเนินการนี้ เพียงเพิ่มส่วนหัว Expires และ Cache-Control: max-age

ตัวอย่างเช่น ในการแคชเป็นเวลา 365 วันใน PHP:

ส่วนหัว ("หมดอายุ:" .gmdate ("D, d M Y H: i: s", เวลา () + 86400 * 365) "GMT"); ส่วนหัว ("การควบคุมแคช: max-age =" + 86400 * 365);

หรือคุณสามารถแคชเนื้อหาเป็นเวลานานโดยใช้ mod_header ใน Apache:

เมื่อได้รับส่วนหัวดังกล่าว เบราว์เซอร์จะฮาร์ดแคชเอกสารเป็นเวลานาน การเรียกเอกสารเพิ่มเติมทั้งหมดจะให้บริการโดยตรงจากแคชของเบราว์เซอร์ โดยไม่ต้องติดต่อกับเซิร์ฟเวอร์

เบราว์เซอร์ส่วนใหญ่ (Opera, Internet Explorer 6+, Safari) ไม่แคชเอกสารหากมีเครื่องหมายคำถามอยู่ในที่อยู่ เนื่องจากจะถือว่าเป็นไดนามิก

นี่คือเหตุผลที่เราเพิ่มเวอร์ชันลงในชื่อไฟล์ แน่นอน ด้วยที่อยู่ดังกล่าว คุณต้องใช้โซลูชันเช่น mod_rewrite เราจะพิจารณาเรื่องนี้ในบทความต่อไป

ป.ล. แต่ Firefox แคชที่อยู่ด้วยเครื่องหมายคำถาม ..

แปลชื่ออัตโนมัติ

เรามาดูวิธีการเปลี่ยนเวอร์ชันอัตโนมัติและโปร่งใสโดยไม่ต้องเปลี่ยนชื่อไฟล์กัน

ชื่อรุ่น -> ไฟล์

สิ่งที่ง่ายที่สุดคือการเปลี่ยนชื่อเวอร์ชันเป็นชื่อไฟล์ดั้งเดิม

ที่ระดับ Apache สามารถทำได้ด้วย mod_rewrite:

RewriteEngine บน RewriteRule ^ / (. * \.) V + \. (Css | js | gif | png | jpg) $ / $ 1 $ 2 [L]

กฎนี้ประมวลผลไฟล์ css / js / gif / png / jpg ทั้งหมด โดยแยกเวอร์ชันออกจากชื่อ

ตัวอย่างเช่น:

/images/logo.v2.gif -> /images/logo.gif
/css/style.v1.27.css -> /css/style.css
/javascript/script.v6.js -> /javascript/script.js

แต่นอกเหนือจากการตัดเวอร์ชัน คุณต้องเพิ่มส่วนหัวที่ฮาร์ดแคชลงในไฟล์ด้วย สำหรับสิ่งนี้จะใช้คำสั่ง mod_header:

เพิ่มส่วนหัว "หมดอายุ" "จันทร์ 28 ก.ค. 2014 23:30:00 GMT" เพิ่มส่วนหัว "การควบคุมแคช" "อายุสูงสุด = 315360000"

และเมื่อรวมกันแล้วจะใช้การกำหนดค่า apache ดังกล่าว:

RewriteEngine บน # จะลบเวอร์ชันและในขณะเดียวกันก็ตั้งค่าตัวแปรที่ไฟล์เป็นเวอร์ชัน RewriteRule ^ / (. * \.) V + \. (Css | js | gif | png | jpg) $ / $ 1 $ 2 # ไฟล์เวอร์ชันฮาร์ดแคช ส่วนหัวเพิ่ม "หมดอายุ" "จันทร์ 28 ก.ค. 2014 23:30:00 GMT" env = VERSIONED_FILE ส่วนหัวเพิ่ม "Cache-Control" "max-age = 315360000" env = VERSIONED_FILE

เนื่องจากวิธีการทำงานของโมดูล mod_rewrite ต้องวาง RewriteRule ไว้ในไฟล์การกำหนดค่าหลัก httpd.conf หรือในไฟล์ที่เชื่อมต่ออยู่ แต่ไม่ว่าในกรณีใดใน .htaccess มิฉะนั้น คำสั่ง Header จะถูกเรียกใช้ก่อน ติดตั้งตัวแปร VERSIONED_FILE

คำสั่งส่วนหัวสามารถอยู่ที่ใดก็ได้ แม้แต่ใน .htaccess ก็ไม่ต่างกัน

เพิ่มเวอร์ชันให้กับชื่อไฟล์ในหน้า HTML โดยอัตโนมัติ

วิธีใส่เวอร์ชันในชื่อสคริปต์ขึ้นอยู่กับระบบเทมเพลตของคุณและโดยทั่วไปแล้ว วิธีเพิ่มสคริปต์ (สไตล์ ฯลฯ)

ตัวอย่างเช่น เมื่อใช้วันที่แก้ไขเป็นเวอร์ชันและเครื่องมือเทมเพลต Smarty ลิงก์สามารถตั้งค่าได้ดังนี้:

ฟังก์ชันเวอร์ชันเพิ่มเวอร์ชัน:

ฟังก์ชั่น smarty_version ($ args) ($ stat = stat ($ GLOBALS ["config"] ["site_root"]. $ Args ["src"]); $ version = $ stat ["mtime"]; echo preg_replace ("! \. (+?) $! "," .v $ version. \ $ 1 ", $ args [" src "]);)

ผลลัพธ์ในหน้า:

การเพิ่มประสิทธิภาพ

เพื่อหลีกเลี่ยงการเรียกสถิติที่ไม่จำเป็น คุณสามารถจัดเก็บอาร์เรย์ที่แสดงรายการเวอร์ชันปัจจุบันในตัวแปรแยกต่างหาก

$ รุ่น ["css"] = อาร์เรย์ ("group.css" => "1.1", "other.css" => "3.0")

ในกรณีนี้ HTML จะถูกแทนที่ด้วยเวอร์ชันปัจจุบันจากอาร์เรย์

คุณสามารถข้ามทั้งสองวิธีและออกเวอร์ชันตามวันที่แก้ไขในระหว่างการพัฒนา - เพื่อความเกี่ยวข้องและในการผลิต - เวอร์ชันจากอาร์เรย์สำหรับประสิทธิภาพ

การบังคับใช้

วิธีการแคชนี้ทำงานได้ทุกที่ รวมถึง Javascript, CSS, รูปภาพ, ภาพยนตร์แฟลช ฯลฯ

เอกสารจะมีประโยชน์เมื่อมีการเปลี่ยนแปลง แต่เบราว์เซอร์ควรมีเวอร์ชันปัจจุบันอยู่เสมอ

การแคชที่กำหนดค่าอย่างเหมาะสมจะมอบประสิทธิภาพที่เพิ่มขึ้นอย่างมาก ช่วยประหยัดแบนด์วิดท์ และลดค่าใช้จ่ายของเซิร์ฟเวอร์ แต่ไซต์จำนวนมากไม่ได้นำการแคชไปใช้อย่างเหมาะสม ทำให้เกิดสภาวะการแย่งชิงที่นำไปสู่การไม่ซิงค์ระหว่างทรัพยากรที่เกี่ยวข้อง

แนวทางปฏิบัติที่ดีที่สุดสำหรับการแคชส่วนใหญ่จัดอยู่ในรูปแบบใดรูปแบบหนึ่งจากสองรูปแบบ:

รูปแบบ # 1: เนื้อหาที่ไม่เปลี่ยนรูปและอายุสูงสุดของแคช

การควบคุมแคช: อายุสูงสุด = 31536000
  • เนื้อหาใน URL จะไม่เปลี่ยนแปลง ดังนั้น ...
  • เบราว์เซอร์หรือ CDN สามารถแคชทรัพยากรเป็นเวลาหนึ่งปีโดยไม่มีปัญหา
  • เนื้อหาแคชที่มีอายุน้อยกว่าอายุสูงสุดที่ระบุสามารถใช้ได้โดยไม่ต้องปรึกษาเซิร์ฟเวอร์

หน้าหนังสือ : ฉันต้องการ "/script-v1.js", "/styles-v1.css" และ "/cats-v1.jpg" 10:24

แคช : ฉันว่าง แล้วเซิร์ฟเวอร์ของคุณล่ะ? 10:24

เซิร์ฟเวอร์ : ตกลง พวกเขาอยู่ที่นั่น อย่างไรก็ตาม เงินสดควรใช้ให้หมดภายในหนึ่งปี ไม่มาก 10:25

แคช : ขอบคุณ! 10:25

หน้าหนังสือ : ไชโย! 10:25

วันถัดไป

หน้าหนังสือ : เฮ้ฉันต้องการ "/ script- v2.js "," / รูปแบบ- v2.css "และ" /cats-v1.jpg "08:14

แคช : มีรูปแมวด้วย ที่เหลือไม่มี เซิร์ฟเวอร์? 08:14

เซิร์ฟเวอร์ : ง่าย - นี่คือ CSS & JS ใหม่ อีกครั้งที่ Cash: อายุการเก็บรักษาไม่เกินหนึ่งปี 08:15

แคช : สุด! 08:15

หน้าหนังสือ : ขอบคุณ! 08:15

แคช : อืม ฉันไม่ได้ใช้ "/script-v1.js" & "/styles-v1.css" มานานพอแล้ว ถึงเวลาที่จะลบพวกเขา 12:32

เมื่อใช้รูปแบบนี้ คุณจะไม่มีวันเปลี่ยนเนื้อหาของ URL ใดโดยเฉพาะ คุณเปลี่ยน URL เอง:

ทุก URL มีบางอย่างที่เปลี่ยนแปลงไปพร้อมกับเนื้อหา ซึ่งอาจเป็นหมายเลขเวอร์ชัน วันที่แก้ไข หรือแฮชของเนื้อหา (นี่คือตัวเลือกที่ฉันเลือกสำหรับบล็อกของฉัน)

เฟรมเวิร์กฝั่งเซิร์ฟเวอร์ส่วนใหญ่มีเครื่องมือในการทำสิ่งนี้ได้อย่างง่ายดาย (ใน Django ฉันใช้ Manifest Static Files Storage); นอกจากนี้ยังมีไลบรารีขนาดเล็กมากใน Node.js ที่ทำสิ่งเดียวกัน เช่น gulp-rev

อย่างไรก็ตาม รูปแบบนี้ไม่เหมาะกับสิ่งต่างๆ เช่น บทความและโพสต์ในบล็อก ไม่สามารถกำหนดเวอร์ชัน URL ของพวกเขาและเนื้อหาสามารถเปลี่ยนแปลงได้ อย่างจริงจัง ฉันมีข้อผิดพลาดด้านไวยากรณ์และเครื่องหมายวรรคตอนจำนวนมาก และจำเป็นต้องสามารถอัปเดตเนื้อหาได้อย่างรวดเร็ว

รูปแบบ # 2: เนื้อหาที่เปลี่ยนแปลงได้ซึ่งตรวจสอบใหม่เสมอบนเซิร์ฟเวอร์

การควบคุมแคช: ไม่มีแคช
  • เนื้อหาของ URL จะเปลี่ยนไป ดังนั้น ...
  • เวอร์ชันแคชในเครื่องไม่สามารถใช้งานได้โดยไม่ต้องระบุเซิร์ฟเวอร์

หน้าหนังสือ : สวัสดี ฉันต้องการเนื้อหาของ "/ about /" และ "/sw.js" 11:32

แคช : ช่วยไม่ได้ เซิร์ฟเวอร์? 11:32

เซิร์ฟเวอร์ : มีดังกล่าว เงินสด เก็บไว้กับตัว แต่ถามก่อนใช้ 11:33

แคช : ครับผม! 11:33

หน้าหนังสือ : ขอบคุณ! 11:33

วันถัดไป

หน้าหนังสือ : เฮ้ ฉันต้องการเนื้อหาของ "/ about /" และ "/sw.js" อีกครั้ง 09:46

แคช : รอสักครู่. เซิร์ฟเวอร์ สำเนาของฉันโอเคไหม สำเนาของ "/ about /" มาจากวันจันทร์ และ "/sw.js" มาจากเมื่อวาน 09:46

เซิร์ฟเวอร์ : "/sw.js" ไม่เปลี่ยนแปลง ... 09:47

แคช : เย็น. หน้า กด "/sw.js" ค้างไว้ 09:47

เซิร์ฟเวอร์ : ... แต่ "/ เกี่ยวกับ /" ฉันมีเวอร์ชันใหม่แล้ว เงินสด อุ้มเธอ แต่เหมือนครั้งที่แล้ว อย่าลืมถามฉันก่อน 09:47

แคช : เข้าใจแล้ว! 09:47

หน้าหนังสือ : ดี! 09:47

หมายเหตุ: ไม่มีแคชไม่ได้หมายความว่า "ไม่แคช" แต่หมายถึง "ตรวจสอบ" (หรือตรวจสอบอีกครั้ง) ทรัพยากรที่แคชจากเซิร์ฟเวอร์ ไม่มีร้านค้าสั่งไม่ให้เบราว์เซอร์แคชเลย นอกจากนี้ ต้องตรวจสอบอีกครั้งไม่ได้หมายถึงการตรวจสอบความถูกต้องอีกครั้ง แต่ความจริงที่ว่าทรัพยากรที่แคชถูกใช้ก็ต่อเมื่ออายุน้อยกว่าอายุสูงสุดที่ระบุ มิฉะนั้นจะมีการตรวจสอบอีกครั้งเท่านั้น นั่นเป็นวิธีที่เริ่มต้นด้วยการแคชคำหลัก

ในรูปแบบนี้ คุณสามารถเพิ่ม ETag (ID เวอร์ชันที่คุณเลือก) หรือส่วนหัว Last-Modified ในการตอบกลับ ในการขอเนื้อหาจากไคลเอนต์ครั้งต่อไป มันจะแสดงผล If-None-Match หรือ If-Modified-Since ตามลำดับ ทำให้เซิร์ฟเวอร์สามารถพูดว่า “ใช้สิ่งที่คุณมี แคชของคุณเป็นปัจจุบัน” ซึ่งก็คือการส่งคืน HTTP 304.

หากไม่สามารถส่ง ETag / Last-Modified เซิร์ฟเวอร์จะส่งเนื้อหาทั้งหมดเสมอ

รูปแบบนี้ต้องมีการร้องขอเครือข่ายเสมอ ดังนั้นจึงไม่ดีเท่ากับรูปแบบแรกที่สามารถทำได้โดยไม่ต้องร้องขอเครือข่าย

ไม่ใช่เรื่องแปลกเมื่อเราไม่มีโครงสร้างพื้นฐานสำหรับรูปแบบแรกแต่ปัญหากับคำขอเครือข่ายในรูปแบบที่ 2 อาจเกิดขึ้นได้เช่นกัน ด้วยเหตุนี้ จึงใช้ตัวเลือกระดับกลาง: อายุสูงสุดสั้นและเนื้อหาที่ไม่แน่นอน นี่เป็นการประนีประนอมที่ไม่ดี

การใช้อายุสูงสุดกับเนื้อหาที่เปลี่ยนแปลงได้มักเป็นทางเลือกที่ผิด

และน่าเสียดายที่มันแพร่หลาย หน้า Github สามารถนำมาเป็นตัวอย่างได้

จินตนาการ:

  • / บทความ /
  • /styles.css
  • /script.js

ด้วยส่วนหัวฝั่งเซิร์ฟเวอร์:

การควบคุมแคช: ต้องตรวจสอบใหม่ อายุสูงสุด = 600

  • การเปลี่ยนแปลงเนื้อหา URL
  • หากเบราว์เซอร์มีแคชเวอร์ชันใหม่ 10 นาที จะใช้โดยไม่ปรึกษาเซิร์ฟเวอร์
  • หากไม่มีแคชดังกล่าว คำขอเครือข่ายจะถูกใช้ อาจใช้ If-Modified-Since หรือ If-None-Match

หน้าหนังสือ : ฉันต้องการ "/ article /", "/script.js" และ "/styles.css" 10:21

แคช : ฉันไม่มีอะไรเหมือนคุณ เซิร์ฟเวอร์? 10:21

เซิร์ฟเวอร์ : ไม่มีปัญหา พวกเขาอยู่ที่นี่ แต่จำไว้ว่าเงินสด: สามารถใช้ได้ภายใน 10 นาทีข้างหน้า 10:22

แคช : มี! 10:22

หน้าหนังสือ : ขอบคุณ! 10:22

หน้าหนังสือ : สวัสดี ฉันต้องการ "/ article /", "/script.js" และ "/styles.css" อีกครั้ง 10:28

แคช : อ๊ะ ขออภัย ฉันทำ "/styles.css" หาย แต่ฉันมีอย่างอื่นอีก เอาไปเถอะ เซิร์ฟเวอร์ คุณปรับแต่ง "/styles.css" ให้ฉันได้ไหม 10:28

เซิร์ฟเวอร์ : ง่าย ๆ มันเปลี่ยนไปแล้วตั้งแต่ครั้งสุดท้ายที่คุณหยิบมันขึ้นมา คุณสามารถใช้ได้อย่างปลอดภัยในอีก 10 นาทีข้างหน้า 10:29

แคช : ไม่มีปัญหา. 10:29

หน้าหนังสือ : ขอบคุณ! แต่ดูเหมือนว่ามีบางอย่างผิดพลาด! ทุกอย่างพังทลาย! เกิดอะไรขึ้น? 10:29

รูปแบบนี้มีสิทธิ์ที่จะมีชีวิตอยู่ในการทดสอบ แต่จะทำลายทุกอย่างในโครงการจริงและติดตามยากมาก ในตัวอย่างข้างต้น เซิร์ฟเวอร์ได้อัปเดต HTML, CSS และ JS แล้ว แต่หน้านั้นแสดงด้วย HTML และ JS แบบเก่าจากแคช ซึ่งได้เพิ่ม CSS ที่อัปเดตจากเซิร์ฟเวอร์แล้ว เวอร์ชั่นไม่ตรงกันทำให้เสียทุกอย่าง

บ่อยครั้งเมื่อทำการเปลี่ยนแปลงที่สำคัญใน HTML เราเปลี่ยนทั้ง CSS เพื่อสะท้อนโครงสร้างใหม่อย่างถูกต้อง และ JavaScript เพื่อให้ทันกับเนื้อหาและสไตล์ ทรัพยากรเหล่านี้เป็นอิสระทั้งหมด แต่ส่วนหัวของแคชไม่สามารถแสดงสิ่งนี้ได้ ด้วยเหตุนี้ ผู้ใช้อาจมีทรัพยากรหนึ่ง / สองเวอร์ชันล่าสุดและส่วนที่เหลือเป็นเวอร์ชันเก่า

max-age ถูกกำหนดให้สัมพันธ์กับเวลาตอบสนอง ดังนั้นหากทรัพยากรทั้งหมดถูกโอนเป็นส่วนหนึ่งของที่อยู่เดียวกัน ทรัพยากรเหล่านั้นจะหมดอายุพร้อมกัน แต่ก็ยังมีโอกาสเล็กน้อยที่จะยกเลิกการซิงค์ หากคุณมีเพจที่ไม่มี JavaScript หรือมีรูปแบบอื่นๆ วันที่หมดอายุของแคชจะไม่ซิงค์กัน และที่แย่กว่านั้น เบราว์เซอร์ดึงเนื้อหาจากแคชอย่างต่อเนื่อง โดยไม่ทราบว่า HTML, CSS และ JS นั้นต้องพึ่งพาซึ่งกันและกัน ดังนั้นจึงสามารถดึงเนื้อหาออกจากรายการและลืมเรื่องอื่นๆ ไปได้เลย เมื่อพิจารณาปัจจัยเหล่านี้ทั้งหมดแล้ว คุณควรเข้าใจว่าโอกาสที่เวอร์ชันที่ไม่ตรงกันนั้นค่อนข้างสูง

สำหรับผู้ใช้ ผลลัพธ์อาจเป็นรูปแบบหน้าที่ใช้งานไม่ได้หรือปัญหาอื่นๆ ตั้งแต่ข้อบกพร่องเล็กๆ น้อยๆ ไปจนถึงเนื้อหาที่ใช้ไม่ได้โดยสิ้นเชิง

โชคดีที่ผู้ใช้มีทางออกฉุกเฉิน ...

การรีเฟรชหน้าบางครั้งช่วยประหยัด

หากหน้าเว็บโหลดโดยการรีเฟรช เบราว์เซอร์จะทำการตรวจสอบซ้ำที่ฝั่งเซิร์ฟเวอร์เสมอ โดยไม่สนใจอายุสูงสุด ดังนั้น หากผู้ใช้มีปัญหาเนื่องจากอายุสูงสุด การรีเฟรชหน้าอย่างง่ายสามารถแก้ไขทุกอย่างได้ แต่แน่นอนว่าหลังจากพบช้อนแล้ว ตะกอนจะยังคงหลงเหลืออยู่และทัศนคติที่มีต่อไซต์ของคุณจะค่อนข้างแตกต่างออกไปบ้าง

พนักงานบริการสามารถยืดอายุของจุดบกพร่องเหล่านี้ได้

ตัวอย่างเช่น คุณมีพนักงานบริการในลักษณะนี้:

รุ่น Const = "2"; self.addEventListener ("ติดตั้ง", เหตุการณ์ => (event.waitUntil (caches.open (`สแตติก - $ (เวอร์ชัน)`) .then (แคช => cache.addAll (["/styles.css", "/ สคริปต์ .js "])));)); self.addEventListener ("เปิดใช้งาน", เหตุการณ์ => (//… ลบแคชเก่า…)); self.addEventListener ("ดึงข้อมูล", เหตุการณ์ => (event.respondWith (caches.match (event.request) .then (response => response || fetch (event.request)));));

พนักงานบริการนี้:

  • สคริปต์แคชและสไตล์
  • ใช้แคชในการแข่งขัน ไม่เช่นนั้นจะเข้าถึงเครือข่าย

หากเราเปลี่ยน CSS / JS เราจะเพิ่มหมายเลขเวอร์ชันด้วย ซึ่งทำให้เกิดการอัปเดต อย่างไรก็ตาม เนื่องจาก addAll เข้าถึงแคชก่อน เราจึงอาจลงเอยด้วยสภาวะการแข่งขันอันเนื่องมาจากเวอร์ชัน CSS & JS ที่มีอายุสูงสุดและไม่ตรงกัน

หลังจากที่แคชแล้ว เราจะมี CSS & JS ที่เข้ากันไม่ได้จนกว่าจะมีการอัปเดตพนักงานบริการในครั้งต่อไป และนี่คือกรณีที่เราไม่เข้าสู่สภาวะการแข่งขันระหว่างการอัปเดตอีกครั้ง

คุณสามารถข้ามการแคชในพนักงานบริการได้:

Self.addEventListener ("ติดตั้ง", เหตุการณ์ => (event.waitUntil (caches.open (`สแตติก - $ (เวอร์ชัน)`) .then (แคช => cache.addAll ([คำขอใหม่ ("/ styles.css", (แคช: "ไม่มีแคช")), คำขอใหม่ ("/ script.js", (แคช: "ไม่มีแคช")])));));

ขออภัย ตัวเลือกสำหรับการแคชไม่ได้รับการสนับสนุนใน Chrome / Opera และเพิ่งถูกเพิ่มใน Firefox nightly build แต่คุณสามารถทำเองได้:

Self.addEventListener ("ติดตั้ง", เหตุการณ์ => (event.waitUntil (caches.open (`สแตติก - $ (เวอร์ชัน)`) .then (แคช => Promise.all (["/styles.css", "/ script .js "] .map (url => (// cache-bust โดยใช้การดึงสตริงการสืบค้นแบบสุ่มกลับ (` $ (url)? $ (Math.random ()) `) .then (การตอบสนอง => (// ล้มเหลว บน 404, 500 ฯลฯ ถ้า (! response.ok) โยนข้อผิดพลาด ("ไม่เป็นไร"); ส่งคืน cache.put (url, ตอบกลับ);)))))));));

ในตัวอย่างนี้ ฉันกำลังล้างแคชโดยใช้ตัวเลขสุ่ม แต่คุณสามารถเพิ่มแฮชของเนื้อหาในบิลด์ได้ (ซึ่งคล้ายกับที่ sw-precache ทำ) นี่เป็นการนำ JavaScript ไปใช้ในรูปแบบแรก แต่ใช้งานได้กับพนักงานบริการเท่านั้น ไม่ใช่เบราว์เซอร์และ CDN

Service Workers และ HTTP Cache ทำงานร่วมกันได้ดี อย่าให้พวกเขาทะเลาะกัน!

อย่างที่คุณเห็น คุณสามารถแก้ไขข้อผิดพลาดในการแคชในพนักงานบริการได้ แต่ควรแก้ไขปัญหาที่ต้นทาง การตั้งค่าแคชอย่างถูกต้องไม่เพียงแต่ทำให้งานของพนักงานบริการง่ายขึ้น แต่ยังช่วยเบราว์เซอร์ที่ไม่สนับสนุนพนักงานบริการ (Safari, IE / Edge) และยังช่วยให้คุณได้รับประโยชน์สูงสุดจาก CDN ของคุณอีกด้วย

ส่วนหัวการแคชที่ถูกต้องยังช่วยให้อัปเดตพนักงานบริการได้ง่ายขึ้นอีกด้วย

รุ่น Const = "23"; self.addEventListener ("ติดตั้ง", เหตุการณ์ => (event.waitUntil (caches.open (`สแตติก - $ (เวอร์ชัน)`) .then (แคช => cache.addAll (["/", "/ script-f93bca2c. js "," /styles-a837cb1e.css "," /cats-0e9a2ef4.jpg "])));));

ที่นี่ฉันได้แคชหน้ารูทด้วยรูปแบบ # 2 (การตรวจสอบความถูกต้องทางฝั่งเซิร์ฟเวอร์) และทรัพยากรอื่น ๆ ทั้งหมดที่มีรูปแบบ # 1 (เนื้อหาที่ไม่เปลี่ยนรูป) การอัปเดตของพนักงานบริการแต่ละครั้งจะทำให้เกิดคำขอไปยังหน้าราก และทรัพยากรอื่นๆ ทั้งหมดจะถูกโหลดก็ต่อเมื่อ URL ของพวกเขามีการเปลี่ยนแปลง ข่าวดีก็คือมันช่วยประหยัดทราฟฟิกและปรับปรุงประสิทธิภาพ ไม่ว่าคุณจะอัปเกรดจากเวอร์ชันก่อนหน้าหรือเวอร์ชันที่เก่ามาก

มีข้อได้เปรียบที่สำคัญกว่าการใช้งานแบบเนทีฟที่นี่ โดยที่ไบนารีทั้งหมดจะถูกดาวน์โหลดแม้ว่าจะมีการเปลี่ยนแปลงเล็กน้อย หรือเรียกใช้การเปรียบเทียบไบนารีที่ซับซ้อน วิธีนี้ทำให้เราสามารถอัปเดตเว็บแอปพลิเคชันขนาดใหญ่ที่มีโหลดค่อนข้างน้อย

พนักงานบริการทำงานได้ดีกว่าเป็นการเพิ่มประสิทธิภาพมากกว่าการใช้ไม้ค้ำยันชั่วคราว ดังนั้นให้ทำงานกับแคชแทนการต่อสู้

เมื่อใช้อย่างระมัดระวัง เนื้อหาที่มีอายุสูงสุดและเปลี่ยนแปลงได้จะดีมาก

max-age มักเป็นตัวเลือกที่ไม่ถูกต้องสำหรับเนื้อหาที่เปลี่ยนแปลงได้ แต่ก็ไม่เสมอไป ตัวอย่างเช่น บทความต้นฉบับมีอายุสูงสุดสามนาที เงื่อนไขการแข่งขันไม่ใช่ปัญหา เนื่องจากไม่มีการขึ้นต่อกันบนหน้าที่ใช้รูปแบบแคชเดียวกัน (CSS, JS & รูปภาพใช้รูปแบบ # 1 - เนื้อหาที่ไม่เปลี่ยนรูป) อย่างอื่นไม่ได้ใช้รูปแบบนี้

รูปแบบนี้หมายความว่าฉันกำลังเขียนบทความยอดนิยมอย่างใจเย็น และ CDN (Cloudflare) ของฉันสามารถลดภาระจากเซิร์ฟเวอร์ได้ ถ้าแน่นอน ฉันยินดีที่จะรอสามนาทีเพื่อให้บทความที่อัปเดตพร้อมใช้งานสำหรับผู้ใช้

ควรใช้รูปแบบนี้โดยไม่มีความคลั่งไคล้ ถ้าฉันเพิ่มส่วนใหม่ลงในบทความ และเชื่อมโยงกับส่วนนั้นจากบทความอื่น ฉันได้สร้างการขึ้นต่อกันที่ต้องแก้ไข ผู้ใช้สามารถคลิกที่ลิงค์และรับสำเนาของบทความโดยไม่ต้องมีส่วนที่เขากำลังมองหา หากฉันต้องการหลีกเลี่ยงสิ่งนี้ ฉันต้องอัปเดตบทความ ลบเวอร์ชันแคชของบทความออกจาก Cloudflare รอสามนาที แล้วจึงเพิ่มลิงก์ไปยังบทความอื่น ใช่ รูปแบบนี้ต้องใช้ความระมัดระวัง

เมื่อใช้อย่างถูกต้อง การแคชจะช่วยเพิ่มประสิทธิภาพและประหยัดแบนด์วิดท์ได้อย่างมาก ส่งผ่านเนื้อหาที่ไม่เปลี่ยนรูปหากคุณสามารถเปลี่ยน URL ได้อย่างง่ายดาย หรือใช้การตรวจสอบความถูกต้องทางฝั่งเซิร์ฟเวอร์อีกครั้ง ผสมผสานเนื้อหาที่มีอายุสูงสุดและเนื้อหาที่เปลี่ยนแปลงได้หากคุณกล้าพอที่จะแน่ใจว่าเนื้อหาของคุณไม่มีการขึ้นต่อกันที่อาจเกิดจากการซิงค์

หลายคนคิดว่าโดยค่าเริ่มต้นไฟล์ CSS ที่เชื่อมต่อผ่านลิงก์หรือ @import จะไม่ถูกแคช ฉันต้องทำให้คุณผิดหวัง มันคือ css ที่แม่นยำซึ่งถูกแคชไว้ในไฟล์แยกต่างหาก และมันดีมาก ฉันจะบอกว่ายอดเยี่ยมมาก ข้อมูลนี้ได้รับการยืนยันอย่างน่าเชื่อถือในทั้ง 6 ตัวขึ้นไปและเบราว์เซอร์อื่นๆ เป็นที่น่าสังเกตว่าผู้เป็นที่รักจำนวนมากแคชไฟล์ดังกล่าวด้วยความเร็วที่บ้าคลั่งดังนั้นจึงเป็นที่หนึ่งสำหรับกรณีนี้ อย่างไรก็ตาม มันเป็นกลไกนี้เองที่ Opera มีความเร็วที่สำคัญในหลายกรณีเมื่อเปรียบเทียบกับเบราว์เซอร์อื่นๆ แต่ฉันจะทำการจองทันทีว่าการแคช "สุดยอด" ใน Opera นี้เป็นเรื่องตลกที่โหดร้ายเมื่อใช้เทคโนโลยี AJAX ในขณะที่คนอื่น ๆ ปรับแต่งพวงเจี๊ยบเมื่อใช้ AJAX แต่ Opera ก็ใช้อันเก่า แต่นี่เป็นเพลงของหัวข้อแยกต่างหาก

การแคช CSS

แต่! ยังมีปัญหาด้านความเศร้าโศกอยู่บ้างในทิศทางนี้ ตามกฎแล้วเกิดจากเซิร์ฟเวอร์ Apache ที่กำหนดค่าไม่ถูกต้องซึ่งสร้างส่วนหัวที่ไม่ถูกต้อง และด้วยความช่วยเหลือของส่วนหัว คุณสามารถควบคุมการแคชของไฟล์ได้ ตามค่าเริ่มต้น แคชจะเปิดใช้งานอยู่เสมอ แต่มีบางครั้งที่คุณไม่จำเป็นต้องแคชไฟล์ ด้วยเหตุนี้ ผู้เชี่ยวชาญจึงเริ่มเต้นรำกับแทมบูรีนเกี่ยวกับส่วนหัว HTTP แต่ถ้าคุณกำลังอ่านบทความนี้ทั้งหมด แสดงว่าคุณยังห่างไกลจากการจัดการส่วนหัว HTTP ฉันรับรองกับคุณว่าในอนาคตอันใกล้คุณจะไม่ต้องเผชิญกับงานดังกล่าว และหากคุณอยากรู้ถึงแก่นแท้ ฉันจะบอกคุณสั้น ๆ ว่าสิ่งนี้เกิดขึ้นได้อย่างไร

  1. ส่งส่วนหัว HTTP ไปยังเว็บเซิร์ฟเวอร์ - พวกเขาพูดว่า เฮ้ พริกหวาน ส่งไฟล์ CSS ให้ฉัน มิฉะนั้น ฉันมี CSS แต่ครั้งสุดท้ายที่มีการเปลี่ยนแปลงดังกล่าว
  2. และเซิร์ฟเวอร์ก็ตอบกลับมา น่ารักมาก ไม่มีการเปลี่ยนแปลงตั้งแต่นั้นมา ใช้ CSS เก่าของคุณอย่างกล้าหาญ
  3. หาก CSS เปลี่ยนไป แสดงว่าเบราว์เซอร์อัปเดต CSS ในแคชอย่างโง่เขลา

ทีนี้ ถ้าไม่เหนื่อย ก็แค่ขยะทางวิทยาศาสตร์เล็กๆ น้อยๆ จากการทดลองบางอย่าง

ฉันจะบอกคุณทันทีว่าข้อความด้านล่างจะเข้าใจได้ไม่ดีสำหรับผู้เริ่มต้นในเว็บ โดยพื้นฐานแล้วสิ่งนี้จะมีประโยชน์สำหรับผู้ที่ยังต้องเผชิญกับงานปิดการใช้งานและเปิดใช้งานแคช

การทดลองทั้งหมดดำเนินการตามจริงและจ่ายเงิน พูดตามตรงว่าโฮสต์ที่ดีที่ให้คุณเปลี่ยนโครงสร้างของส่วนหัว HTTP ได้โดยไม่ต้องหวาดระแวงว่าจะถูกแฮ็กโดยส่วนหัว HTTP :)

โหมดเบราว์เซอร์

ดังนั้นเบราว์เซอร์ใด ๆ ก็มี 2 โหมด:

1. โหมดเริ่มต้น, ชื่อเรื่องที่ส่งคืนคือ:

Cache-Control: no-store, no-cache, must-revalidate, post-check = 0, เช็คล่วงหน้า = 0

2. โหมดเปิดใช้งานแคช, ชื่อเรื่องที่ส่งคืนคือ:

การควบคุมแคช: ส่วนตัว อายุสูงสุด = 10800 ตรวจสอบล่วงหน้า = 10800

ต่อไป ฉันจะอธิบายพฤติกรรมของเบราว์เซอร์

FireFox 3.5 และสูงกว่า

ในครั้งแรกโหมดแคชไฟล์ JavaScript ภายนอกอย่างแน่นหนาและไม่ได้ตรวจสอบการอัปเดต เว้นแต่คุณจะบังคับให้หน้ารีเฟรช CSS ได้รับการตรวจสอบโดยคำขอส่วนหัว

If-Modified-Since: "วันที่ปัจจุบัน" GMT If-None-Match: " own hash code"

กล่าวคือ CSS จะโหลดซ้ำก็ต่อเมื่อได้รับการอัปเดตจริงเท่านั้น

ประการที่สองโหมดหยุดรีเฟรชหน้าโดยสิ้นเชิง นั่นคือ แม้ว่าเราจะเปลี่ยนแปลงเนื้อหาที่แสดงบนเพจในฐานข้อมูล เนื้อหาจะไม่แสดงสิ่งนี้ แม้ว่าจะถูกบังคับให้รีเฟรช เนื่องจากมันส่งคำขอ:

GET / HTTP / 1.1 โฮสต์: xxx.com หาก-แก้ไข-ตั้งแต่: วันที่ GMT ปัจจุบัน

และได้รับคำตอบว่า

HTTP / 1.1 304 ไม่ถูกแก้ไข

Internet Explorer 8 (IE8)

ในครั้งแรกโหมด Internet Explorer จะส่งคำขอ If-Modified-Since & If-None-Match สำหรับทั้ง JavaScript และ css นั่นคือจะโหลด JavaScript และ CSS เฉพาะเมื่อมีการอัปเดตจริงเท่านั้น เช่นเดียวกับถ้าเพจถูกบังคับให้รีเฟรช

ประการที่สองโหมด Internet Explorer ยังส่งคำขอ If-Modified-Since & If-None-Match สำหรับทั้ง JavaScript และ css แต่ในขณะเดียวกัน มันก็ไม่ได้พยายามโหลด / อัปเดตหน้าด้วยซ้ำ กล่าวคือ มันไม่ได้ส่งคำขอด้วยซ้ำ นั่นคือ js / css ของคุณจะได้รับการอัปเดต แต่เนื้อหาเทมเพลตและหน้าจะไม่ทำ แม้แต่การบังคับให้รีเฟรชหน้าก็ไม่ช่วยในการอัปเดตเนื้อหา

Opera 10 และเก่ากว่า

ในครั้งแรกโหมด Opera ในโหมดแรก การอัปเดต js & CSS จะขึ้นอยู่กับค่าของตัวเลือกตรวจสอบรูปภาพในการตั้งค่า หากตั้งค่าตัวเลือกเป็น เสมอ โอเปร่าจะส่งคำขอด้วย If-Modified-Since & If-None-Match เพื่อตรวจสอบการอัปเดต js & css หากมีการตั้งค่า เช่น 5 ชั่วโมง ค่านั้นจะถูกตรวจสอบทุกๆ 5 ชั่วโมง หรือโดยการบังคับให้รีเฟรชหน้า

ประการที่สองโหมด Opera จะไม่ตรวจสอบการอัปเดต js & CSS (ไม่ส่งคำขอ GET) และไม่ได้ส่งคำขอ GET สำหรับหน้านั้นด้วย นั่นคือ เราจะไม่เห็นการอัปเดต js & css หรือการอัปเดตเนื้อหาดังเช่นใน สิ่งอื่นๆ และในเบราว์เซอร์อื่นๆ แต่ด้วยการอัปเดตแบบบังคับ Opera จะดีกว่า ต่างจาก IE & FF ตรงที่ Opera ร้องขอเนื้อหาของหน้าอย่างชัดเจนโดยไม่มี If-Modified-Since & If-None-Match คำขออัปเดต Js & CSS สำหรับการบังคับให้อัปเดตมาพร้อมกับ If-Modified-Since & If-None-Match

ข้อสรุป

  1. การแคช หากคุณไม่เข้าใจว่ามันทำงานอย่างไรในเบราว์เซอร์ต่างๆ และผลที่ตามมา เป็นสิ่งที่ค่อนข้างอันตราย
  2. การแคชสามารถเปิดใช้งานได้ก็ต่อเมื่อเพจไม่ค่อยอัปเดต (นั่นคือ หากไซต์ไม่มีเพจที่อัปเดตตามเวลาจริง) และแม้ในกรณีนี้ จำเป็นต้องกำหนดขีดจำกัดในช่วงเวลาจำกัดการแคช (เช่น สองสามชั่วโมงหรือหนึ่งวัน)
  3. ในความคิดของฉัน FireFox มีพฤติกรรมที่ฉลาดกว่า IE เล็กน้อย เพราะถึงแม้จะปิดการใช้งานแคช มันก็ไม่ได้ตรวจสอบการอัปเดต JavaScript อย่างต่อเนื่อง ซึ่งดูสมเหตุสมผลเพราะ JavaScript มีการอัปเดตน้อยมาก
  4. Opera ช่วยให้คุณควบคุมการอัปเดตรูปภาพ JavaScript และ CSS ได้อย่างยืดหยุ่นโดยใช้การตั้งค่าตรวจสอบรูปภาพ ซึ่งเป็นข้อดี Opera ยังทำงานได้ดีกว่า IE & FF ด้วยการเปิดใช้งานแคชและบังคับให้รีเฟรช เนื่องจากฉันขอเตือนคุณว่า Opera จะรีเฟรชเนื้อหาของหน้าอย่างสมบูรณ์ในกรณีนี้ และ IE & FF จะทำให้คุณมีความสุข

ขอให้โชคดีและไซต์ที่ให้ผลกำไร