การจัดการกับแคชเบราว์เซอร์ในแอพหน้าเดียว


27

ฉันกำลังพยายามหาวิธีจัดการแคชของเว็บเบราว์เซอร์สำหรับแอปหน้าเดียวอย่างถูกต้อง

ฉันมีการออกแบบที่ค่อนข้างธรรมดา: ไฟล์ HTML, JS และ CSS หลายตัวที่ใช้งานสปาและมีข้อมูล JSON มากมายที่สปาใช้ ปัญหาเกิดขึ้นเมื่อฉันต้องการผลักดันการอัปเดต: ฉันอัปเดตส่วนคงที่ของเว็บไซต์และรหัสที่สร้าง JSON ในเวลาเดียวกัน แต่เบราว์เซอร์ไคลเอนต์มักจะมีส่วนคงที่แคชดังนั้นรหัสเก่าพยายามประมวลผลข้อมูลใหม่และ อาจ (ขึ้นอยู่กับการเปลี่ยนแปลงที่ทำ) อาจมีปัญหา (โดยเฉพาะอย่างยิ่งดูเหมือนว่า IE จะก้าวร้าวมากกว่า Chrome หรือ Firefox เกี่ยวกับการใช้แคช JS โดยไม่ต้องทำการตรวจสอบซ้ำ)

วิธีที่ดีที่สุดในการจัดการกับสิ่งนี้คืออะไร?

  1. ตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลง JSON ของฉันเข้ากันได้ย้อนหลังและถือว่าแคชของเบราว์เซอร์จะหมดอายุในระยะเวลาที่เหมาะสม
  2. ฝังหมายเลขรุ่นบางส่วนในทั้ง JS แบบคงที่และ JSON จากนั้นเรียกใช้งานwindow.location.reload(true);หากไม่ตรงกัน
  3. ค้นหาชุดค่าผสมที่เหมาะสมของส่วนหัว ( must-revalidateหรือno-cacheอะไรก็ตามแหล่งที่มา แตกต่างกันไปตามวิธีการทำ) เพื่อให้แน่ใจว่าเบราว์เซอร์จะตรวจสอบความถูกต้องของทรัพยากรทั้งหมดในทุก ๆ ครั้งที่โหลดซ้ำแม้ว่ามันจะหมายถึง
  4. จัดการการควบคุมแคชของฉันและหมดอายุส่วนหัวเพื่อให้เนื้อหาแบบคงที่หมดอายุเมื่อฉันต้องการผลักดันการอัปเดต
  5. อื่น ๆ อีก?

1
เคยได้ยิน # 3 และ # 4 ล้มเหลวโดยไม่คาดคิดในการควบคุมเว็บเบราว์เซอร์ในตัวหากสภาพแวดล้อมของคุณเป็นสิ่งชั่วร้าย ( ไอ iOS) จากเพื่อนร่วมงาน # 1 และ # 2 สามารถเป็นตัวเลือกระดับแอป แต่ยังอาจ (?) ทำให้เกิดปัญหาแคชสำหรับทรัพยากรอื่น ๆ หรือสำหรับการโหลดทรัพยากรบางส่วน สิ่งเดียวที่ฉันเห็นได้อย่างน่าเชื่อถือทำงานในรหัสพร้อมการผลิตคือการดึง yoururl.html? <SomeTimeStamp> เพราะจะปลอมกลไกการแคชส่วนใหญ่ โบนัส: นำเว็บแอปทั้งหมดของคุณไปไว้ในไฟล์เพื่อให้โหลดได้สำเร็จหรือล้มเหลวแบบอะตอม ข้อเสีย: ทำงานได้ดีที่สุดบนลิงก์ในเครื่อง ไมล์สะสมของคุณอาจแตกต่างกันไป โชคดี!
J Trana

2
+1 เพื่อใช้หมายเลขรุ่นหรือการประทับเวลาเป็นพารามิเตอร์ URL สำหรับทรัพยากร
9000

คำตอบ:


14

คุณต้องมีโซลูชันป้องกันการแคช บทบาทของการใช้แคชคือ:

  1. เปลี่ยนชื่อทรัพยากรเป็นชื่อที่ไม่ซ้ำกันขึ้นอยู่กับเนื้อหาของพวกเขา
  2. อัปเดตการอ้างอิงทั้งหมดไปยังแหล่งข้อมูลเหล่านั้น

ในโครงการแบบอิงตาม Grunt เป็นเรื่องปกติที่จะใช้grunt-revเพื่อให้แน่ใจว่าไฟล์ทั้งหมดที่จำเป็นต้องรีเฟรชจะได้รับชื่อเฉพาะตามเนื้อหาของพวกเขา

หากคุณแน่ใจว่าไฟล์ JSON ของคุณได้รับชื่อไฟล์แคชตามการอ้างอิงใน Javascript ของคุณไคลเอนต์จะโหลดไฟล์ JSON ที่ Javascript คาดหวังเสมอ

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

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


2
+1 สำหรับบิต "แคชป้องกัน" ที่เอียงซึ่งเปิดประตูไปสู่ ​​google สิ่งนี้ได้ผลดี
Zak Kus

@Ted Percival - กรอบ yeoman ทำสิ่งนี้ซึ่งฉันใช้ แต่ฉันเห็นปัญหา เมื่อฉันปล่อยบิลด์ใหม่เบราว์เซอร์อาจมี index.html แคชซึ่งอ้างอิงถึงไฟล์เก่า ... และเบราว์เซอร์ได้รับข้อผิดพลาด ฉันจะแก้ไขได้อย่างไร (A. ) symlink ชื่อไฟล์เก่าทั้งหมดไปยังชื่อใหม่ (ใช้งานได้) (B. ) เพิ่มส่วนหัวที่ไม่แคชใน index.html (แต่จะเป็นที่เคารพเสมอ) (C. ) เพิ่ม. htaccess เพื่อรับรู้ไฟล์ที่มีการแก้ไข และค้นหาฐานหนึ่ง (เช่น 12345.main.js -> main.js)
timh

5

คุณสามารถใช้if-modified-since + last-modifiedหรือif-none-match + etagส่วนหัวพร้อมกับcache-controlส่วนหัวที่เหมาะสม (อาจมีข้อบกพร่องของเบราว์เซอร์แต่ไม่มีสิ่งใดที่คุณไม่สามารถจัดการได้ในเบราว์เซอร์ล่าสุด)

หากไฟล์เป็นแบบคงที่ฉันขอแนะนำให้คุณใช้if-modified-sinceเพราะมันสามารถทำได้โดยอัตโนมัติด้วยเซิร์ฟเวอร์ HTTP ที่กำหนดค่าไว้อย่างดี ควรส่งคืน 304 หากไฟล์ไม่ได้ถูกแก้ไขตั้งแต่การดาวน์โหลดครั้งล่าสุด

ฉันไม่คิดว่า # 1 และ # 2 ของคุณจะทำงานในระยะยาว # 3 หรือ # 4 สามารถทำงานได้ # 3 นั้นง่ายกว่า แต่คุณต้องเรียนรู้วิธีจัดการกับปัญหานี้เพียงครั้งเดียว ดังนั้นฉันจะลอง # 4 ถ้าฉันเป็นคุณ แต่วิธีแก้ปัญหาอาจขึ้นอยู่กับว่าเบราว์เซอร์ที่ลูกค้าของคุณใช้ ... ตัวอย่างเช่น IE8 มีปัญหาด้วยการอัปเดตแคช ajax ฯลฯ ...


2

หากคุณสามารถรวมตัวกรอง Java Servlet ใน SPA ของคุณนี่เป็นวิธีแก้ปัญหาในการทำงาน: CorrectBrowserCacheHandlerFilter.java

โดยทั่วไปเมื่อเบราว์เซอร์ของคุณร้องขอไฟล์คงที่เซิร์ฟเวอร์จะเปลี่ยนเส้นทางทุกคำขอไปยังสิ่งเดียวกัน แต่ใช้พารามิเตอร์แบบสอบถามแบบแฮช ( ?v=azErTตัวอย่าง) ซึ่งขึ้นอยู่กับเนื้อหาของไฟล์คงที่เป้าหมาย

การทำเช่นนี้เบราว์เซอร์จะไม่แคชไฟล์แบบคงที่ที่ประกาศในindex.htmlตัวอย่างของคุณ(เพราะจะได้รับเสมอ302 Moved Temporarily) แต่จะแคชเฉพาะไฟล์ที่มีรุ่นแฮชเท่านั้น (เซิร์ฟเวอร์จะตอบคำถาม200เหล่านั้น) ดังนั้นแคชเบราว์เซอร์จะถูกใช้อย่างมีประสิทธิภาพสำหรับไฟล์คงที่ที่มีรุ่นแฮช

Disclaimer: CorrectBrowserCacheHandlerFilter.javaผมผู้เขียน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.