Clear the cache in JavaScript ลง Code JS แล้ว Code ไม่เปลี่ยน

cacheJS
cacheJS

เพื่อนๆ เคยเจอปัญหาการติดตั้ง Code Js ไฟล์รูป ไฟล์ html ไฟล์  style sheet  หรือไฟล์อื่นๆ ที่ไม่ได้เป็นภาษา Server Script  ตัวใหม่ไปติดตั้งแล้วไฟล์เหล่านั้นไม่เปลี่ยนบ้างไหมครับ ถ้าเคยเราแก้ปัญหานี้อย่างไรเราอาจจะแก้ปัญหาโดยการกด Ctrl F5 แล้วมันก็จะใช้ได้ วันนี้เราจะมาหาคำตอบพร้อมแนวทางการแก้ไขกันครับ

สาเหตุ ของมันก็เกิดจากการทำ Cache ของ browser แล้วมันคืออะไรเอ่ย cache browser ก็คือการจัดเก็บไฟล์พวก รูป html  JS หรือไฟล์อื่นๆ เอาไว้ที่เครื่อง Client(เครื่อง Com หรือ laptop ที่เราใช้อยู่นั่นแหละครับ) เพื่อให้ browser ไม่ต้องไปทำการ load ไฟล์ซ้ำทุกครั้งที่มีการเรียก Page ไปที่ Server ข้อดีของมันก็คือจะช่วยให้ Page ทำงานได้เร็วขึ้นเพราะไม่ต้องเรียกไฟล์ต่างๆ ข้าม Network ทุกครั้งที่มีการเรียกใช้งาน Page แต่ข้อเสียของมันก็คือหากมีไฟล์ใหม่ที่ใช้ชื่อเดียวกัน แล้วเราทำการเรียกไฟล์ชื่อเดิมทั้งที่ Copy replace  ที่ Server แล้วลองเปิดที่ Server ก็เป็นไฟล์ใหม่แล้ว แต่ที่เครื่อง client  ยังคงได้ไฟล์เดิมอันนี้แหละคือปัญหา  (ถ้าหากเราไม่ได้ซีเรียสอะไรเราก็สามารถแก้ปัญหาโดยการกด ctrl F5 ก็ได้ครับ) การกด ctrl F5 มันก็น่าจะเพียงพอแล้วที่จะแก้ปัญหาได้ (ถ้าเพียงพอก็ไม่ต้องอ่านต่อและ ล้อเล่น ^_^)

ก่อนอื่นเราต้องมองออกก่อนว่าไฟล์ไหนเป็นไฟล์ที่อยู่ใน Cache ของ Browser วิธีการดูก็สามารถดูได้ง่ายๆ และก็คล้ายๆ กันในแต่ละ browser ซึ่งในที่นี้ผมขอยกตัวอย่างการดูว่าไฟล์ที่ถูก Cache จาก google chrome นะครับเพราะมันมี Tool มาให้เลยไม่ต้องติดตั้งเพิ่มแต่อย่างไร (ถ้าทำใน firefox ต้องติดตั่ง fire bugs เพิ่มครับ ส่วน IE ไม่ต้องไปพูดถึงอิอิ)

วิธีการ

ให้เปิด web site ด้วย google chrome จากนั้นให้คลิกขวาแล้วเลือกตรวจสอบหรือกด Key ลัด Ctrl+shift+I

chomeinsect
จากนั้นให้เลือกที่ Network แล้วกด F5 จากภาพด้านล่างให้สังเกตุที่ column status จะแสดง HTTP Status Codes ซึ่งมันมีความหมายครับผมได้สรุปออกมาให้สามารถเข้าใจง่ายๆ ตามตารางด้านล่างครับผม
cachefile304

HTTP Status Codes ที่สำคัญ

Status Code ตัวอย่าง คำอธิบาย
2xx Successful 200 – OK เป็น Code แจ้งการเรีกรับส่ง Request ระหว่าง Client และ Server สำเร็จถูกต้อง
3xx Redirection 304 – Not Modified  เป็น Code ที่แจ้งในส่วนของ Client เป็นคนจัดการ
4xx Client Error 404 – Not Found เป็น Code แจ้ง Client Error
5xx Server Error 500 – Internal Server Error< เป็น Code ที่แจ้ง Server Error
Unreachable 0,Unreachable เป็น Code ไม่ได้ระบุไว้ในข้อกำหนดแต่เกิดจาก third-party services ตัวอื่นๆ ยกตัวอย่างเช่น  RESTful error responses:

HTTP Status Codes เพิ่มเติม

จริงๆมันมีอีกหลายตัวให้ดูตาม link ด้านบนแต่ให้เอา Concept ไปครับ ตัวที่เราสนใจก็คือ Code 304

304 – Not Modified : แล้วอันนี้มันหมายถึงอะไร มันก็แปลตรงตัวเลยนั่นและครับว่าไม่ได้ถูกแก้ไข หรือพูดง่ายว่ามันก็คือ Cache นั่นเอง เรามาดูหลักการของมันแบบสั้นๆ ก็แล้วกันนะครับเพราะรู้เยอะเราก็อาจไม่ได้ใช้มันขนาดนั้น เอาละเราลงลึกเข้าไปอีกหน่อยเราจำเป็นที่จะต้องรู้ HTTP  Headers อีกสักสองสามตัว

Request Header

-If-Modified-Since

-If-None-Match

Response Header

-Last-Modified

-ETag 

วิธีการดูก็ให้เลือกไฟล์ JavaScript หรือไฟล์อะไรก็ตามที่ Code เป็น 304 และก็ดูในส่วนของ Section Request Header ตามรูปโดยในส่วนนี้จะเป็นการ Request จาก browserchomecache304
ถ้าไฟล์ใหนที่ถูกทำ Cache หรือ Status เป็น 304  Browser จะเป็นตัวจัดการ Request  Header โดยจะแปะ If-Modified-Since และ If-None-Match ส่งไปให้ Server Check ว่าเป็นไฟล์ใหม่หรือไม่ทุกครั้งๆ ที่มีการเรียกใช้ (ถ้าแบบไม่ต้องถามทุกครั้งจะใช้  Expires และ Cache-Control: max-age สามารถกำหนดได้ใน Server คือเมื่อหมดอายุตามที่กำหนดก็ค่อยให้เรียกทีนึง)

If-Modified-Since:Thu, 31 Mar 2016 03:05:59 GMT (ส่งเวลาของไฟล์ที่ถูกแก้ไขครั้งล่าสุดของ Cache ไปเทียบกับ Server เป็นเวลาเดียวกันไหม)

If-None-Match:”66a3640fa8ad11:0″   (ส่งค่าจากการ Hashes เนื้อหาของไฟล์ไปเทียบกับ Server ว่าเป็นไฟล์เดียวกันไหม)

สาเหตุ ที่ต้อง Check สองอย่างก็เพราะบางครั้งไฟล์นั้นถูก Save ใหม่แต่เนื้อหาเป็นไฟล์เดิม Etag ก็จะเท่าเดิมมันก็ถือว่าไม่มีการเปลี่ยนแปลงใดๆ

If-None-Match ส่งค่า ETag   :คือค่าที่ได้จากการ Hashes เนื้อหาของไฟล์ (Hashes จะเป็นการคำนวณ binary ของไฟล์แล้วจะได้ค่าๆ retun กับมาเสมอแล้วถ้าเป็นไฟล์เดียวกันมันจะมีค่าเท่ากันเสมอ)   เช่น ABBBFG  ทำ Hashes  สมุมติว่าได้ 11 แล้ว GABBBF ทำ Hashes แล้วยังไงก็ไม่มีมีทางได้ค่า 11 แน่นอนซึ่งอาจเป็น 10 หรืออะไรก็ตามจากนั้น Browser จะส่งสองค่านี้ให้ Server Check ว่าจะต้องทำการโหลดไฟล์นี้ใหม่หรือว่าจะให้ใช้ไฟล์ที่อยู่ใน Cache ของ ฺBrowser

ถ้า ETag และ LAST-Modified ไม่ตรงกันกับ Server   Server จะส่งไฟล์มาให้ Client ใหม่ผลถือว่าเป็นคนละไฟล์กับที่อยู่ใน Cache ของ Browser และจะ return Code Status 200 และจะเก็บไฟล์นี้ไว้ใน Cache และก็ Stamp สองค่า ETag และ LAST-Modified นี้เพื่อส่ง check ทุกครั้งที่มีการเรียกใช้

แต่ถ้าสองค่านี้ระหว่าง Client กับ Server มีค่าเท่ากัน Server จะ Return Code 304 โดยไม่มีการส่งไฟล์ใหม่ให้กับ Client และ Client จะใช้ File ที่เครื่องแทน เพื่อเพิ่มความเร็วและเป็นการช่วยลดโหลดเพราะ Message ของ Status Code เมื่อเทียบกับการส่งไฟล์ใหม่นั้นถือว่าน้อยมาก

รูปแสดงการทำงานร่วมกันของ Client (Request Header) และ Server (Response Header)

Cache

แล้วการกด Key ลัดด้านล่างมันทำงานอย่างไร

Force Refresh
OS Short Key
Windows ctrl + F5
Mac/Apple Apple + R or command + R
Linux F5

จาก Short Key ด้านบนก็คือการบังคับให้ Browser ไม่สนใจ Cache ในเครื่องและทำการส่ง Request Header โดยที่ไม่ส่ง Parameter ไปถาม Server นั่นเองเท่านี้ก็จะได้ไฟล์ไหมหมด

อธิบายมาตั้งนานก็มาถึงสิ่งที่ผมอยากที่จะนำเสนอสักทีสักทีครับผม ^_^ (รอมาตั้งนาน)

สมุมติว่าเพื่อนๆ เป็นผู้ Develop App ที่มี User ใช้เป็นจำนวนมากและค่อนข้าง serious ยกตัวอย่างเช่น App อัตราแลกเปลี่ยนอย่างรูปด้านล่าง

exchange
โดย User จะต้องเขามาใช้ทุกวันเพื่อใช้ในการแจ้งลูกค้าหรือคำนวณการแลกปลี่ยนเงินตราต่างประเทศ เผอิญดันมีการแก้ไข code JS และเปลี่ยน stylesheet ตามความต้องการของ User สมุมติว่าเราได้แก้โปรแกรมและเราลง Code JS และ stylesheet ไปพร้อมกันแล้วเราตรวจสอบหน้าเครื่อง Server แล้วว่าทุกอย่างถูกต้องดูเครื่องไหนๆ ก็ถูกต้องไปหมด แต่พอเช้าวันรุ่งขึ้น สมุมติว่าเป็น 10 โมง (ตอนกำลังพีคเลย -_-) Mail ก็เข้ามาเป็น 100 mail เลยว่า Rate ไม่ Show บ้าง โชว์เพี้ยนๆ บ้างอ้าวไงละทีนี้ (มีทั้งถามสุภาพ มีทั้งถามแบบเหน็บแนบ ถามแบบขู่กลุ้มวุ้ย เอาชีวิตจริงมาเล่าเลย 55555)  เอาไงละถ้าจริง User มีความรู้อยู่บ้างก็คงต้องลองกด ctrl + F5 แต่ทำไงได้ครับก็เขาไม่ได้เข้าใจการทำงานของเทคโนโลยี ไม่มีทางออกเอาละผมก็งัดไม่ตายมาใช้คือแจ้งให้ User กด ctrl + F5 แต่พอมีถามมามากๆ ขึ้นชักไม่ไหวครับเลยต้องหา Solution จึงเป็นที่มาของบทความอันยาวยืดอันนี้ค้นไปค้นมาก็เข้าใจว่า ปัญหาก็คือในบางครั้งเครื่อง Client มันก็ไม่ได้เป็นไปตามที่อธิบายข้างต้นเสมอไปบางครั้งเครื่อง Client  ต้องเรียกผ่าน ISP ผ่าน third party ต่างๆ ถ้ามียกตัว เช่น Akamai (cache) ซึ่งหลายๆ ครั้งไฟล์มันก็มาไม่ถูกอย่างที่ครวเป็นเพราะมันต้องผ่านหลาย Hop ซึ่งส่งผลให้โปรแกรมของเราทำงานไม่ถูกต้อง เลยต้องวิธี พอพบก็อยากที่จะเอามาแชร์ให้เพื่อนๆ ครับอาจจะไม่ใช่วิธีที่ถูกต้องเพราะสถาปัตยกรรมเขาสร้างมาแบบนี้ (แต่จำเป็นครับผม) ขอ highlight กว้างๆ เลยว่าแก้ปัญหาได้จริงๆๆๆๆๆๆๆๆๆๆๆๆๆ

    <script src="Module/jquery-2.1.4.min.js?Ver=0001"></script>
    <script src="Module/Materialize/js/materialize.js?Ver=0001"></script>
    <script src="Module/Materialize/js/init.js?Ver=0001"></script>

เน้นเลยว่ามีประโยชน์

จากด้านบนก็เพียงแต่แปะ QueryString ต่อท้ายไฟล์ที่เราต้องการที่จะให้ Clear Cache เท่านั้นมันเหมือนเป็นการหลอก Browser ว่าเป็นไฟล์ใหม่เพียงครั้งแรกให้เรียกไฟล์ใหม่เท่านั้น ครั้งต่อไปก็เขา Cache เหมือนเดิม (ถ้ามีวิธีที่ดีกว่านี้แจ้งผมหน่อยนะครับจะได้เอาไปใช้ครับผม)

แถมท้ายถ้าเบื่อ  ctrl + F5  ตอน Dev อาจแปะ Date Time ต่อท้ายตอน Refer ไปเลยเพราะหลายๆครั้งมันก็ไม่ได้ไฟล์ใหม่ต้องมานั่งกด ctrl+ F5 เราก็อาจะแปะ date time หรือ random ต่อท้ายไปจะได้ใหม่เสมอ

(Code ด้านล่างให้ทำตอน Dev นะพอขึ้น Production ไม่ครวทำเป็นอย่างยิ่ง)
ASP.NET

<script src="jquery.js?<%=DateTime.Now.Ticks %>" />

stylesheet

 <%= "<link href='/asset/Style.css?v" + new Random().Next(1000,9999).ToString() + "' rel='stylesheet' />" %>

PHP Refer

<link rel="stylesheet" href="mycss.css?v=<?php echo filemtime('mycss.css') ?>"/>

หวังว่าคงมีประโยชน์นะครับ

Leave a Reply