اصول ذخیره سازی مشتری در کلمات و مثال های واضح. آخرین ویرایش، Etag، Expires، Cache-Control: max-age و سایر هدرها. بهترین روش های ذخیره سازی ذخیره سازی ETag ساده

با گنجاندن CSS خارجی و جاوا اسکریپت، می‌خواهیم درخواست‌های غیرضروری HTTP را به حداقل برسانیم.

برای این منظور، فایل‌های .js و css. با سربرگ‌هایی ارائه می‌شوند که ذخیره‌سازی قابل اعتماد را تضمین می‌کنند.

اما وقتی یکی از این فایل ها در حین توسعه تغییر می کند، چه کار می کنید؟ همه کاربران آن را در حافظه پنهان دارند نسخه قدیمی- تا زمانی که حافظه نهان منسوخ شود، شکایات زیادی در مورد ادغام خرابی بخش های سرور و مشتری وجود خواهد داشت.

ذخیره سازی و نسخه سازی مناسب این مشکل را به طور کامل از بین می برد و همگام سازی قابل اعتماد و شفاف نسخه های سبک/اسکریپت را فراهم می کند.

ذخیره سازی ETag ساده

ساده ترین راه برای کش کردن منابع استاتیک استفاده از ETag است.

کافی است تنظیمات سرور مناسب را فعال کنید (برای آپاچی به طور پیش‌فرض فعال است) - و برای هر فایل در هدرها یک ETag داده می‌شود - یک هش بستگی به زمان به‌روزرسانی، اندازه فایل و (بر اساس inode) دارد. سیستم های فایل) اینود.

مرورگر چنین فایلی را کش می‌کند و در درخواست‌های بعدی، هدر If-None-Match را با ETag سند ذخیره شده مشخص می‌کند. با دریافت چنین هدر، سرور می تواند با کد 304 پاسخ دهد - و سپس سند از حافظه پنهان گرفته می شود.

به نظر می رسد این است:

اولین درخواست به سرور (پاک کردن کش) GET /misc/pack.js HTTP/1.1 Host: website

به طور کلی، مرورگر معمولاً یک سری هدر مانند User-Agent، Accept و غیره اضافه می کند. برای اختصار بریده می شوند.

پاسخ سرور سرور با یک سند با کد 200 و ETag پاسخ می دهد: HTTP/1.x 200 OK Content-Encoding: gzip Content-Type: text/javascript; charset=utf-8 برچسب: "3272221997" محدوده های پذیرش: بایت طول محتوا: 23321 تاریخ: جمعه، 02 مه 2008، ساعت 17:22:46 به وقت گرینویچ سرور: lighttpd درخواست مرورگر بعدی در درخواست بعدی، مرورگر If-None را اضافه می کند -Match: (تگ ذخیره شده در حافظه پنهان): GET /misc/pack.js HTTP/1.1 میزبان: سایت If-None-Match: "453700005" پاسخ سرور سرور به نظر می رسد - بله، سند تغییر نکرده است. این بدان معنی است که می توانید یک کد 304 صادر کنید و سند را دوباره ارسال نکنید. HTTP/1.x 304 اصلاح نشده محتوا-رمزگذاری: gzip برچسب: "453700005" نوع محتوا: text/javascript; charset=utf-8 محدوده پذیرش: بایت تاریخ: سه شنبه، 15 آوریل 2008، 10:17:11 GMT

گزینه جایگزین- اگر سند تغییر کرده باشد، سرور به سادگی 200 را با ETag جدید ارسال می کند.

ترکیب Last-Modified + If-Modified-Since به روشی مشابه کار می کند:

  • سرور تاریخ آخرین اصلاح را در هدر Last-Modified ارسال می کند (به جای ETag)
  • مرورگر سند را کش می کند و دفعه بعد که همان سند درخواست می شود، تاریخ نسخه کش شده را در سربرگ If-Modified-Since ارسال می کند (به جای If-None-Match)
  • سرور تاریخ ها را بررسی می کند و اگر سند تغییر نکرده باشد فقط کد 304 را بدون محتوا ارسال می کند.
  • این روش ها به طور قابل اعتماد و خوبی کار می کنند، اما مرورگر هنوز باید برای هر اسکریپت یا سبک درخواست کند.

    حافظه پنهان هوشمند نسخه سازی

    رویکرد کلی برای نسخه سازی - به طور خلاصه:

  • نسخه (یا تاریخ اصلاح) به همه اسکریپت ها اضافه می شود. به عنوان مثال، http://site/my.js به http://site/my.v1.2.js تبدیل می شود
  • همه اسکریپت ها توسط مرورگر ذخیره می شوند
  • هنگام به روز رسانی اسکریپت، نسخه به نسخه جدید تغییر می کند: http://site/my.v2.0.js
  • آدرس تغییر کرده است، بنابراین مرورگر فایل را دوباره درخواست و کش می کند
  • نسخه قدیمی 1.2 به تدریج از حافظه پنهان خارج می شود
  • ذخیره سازی سخت

    ذخیره سازی سخت- نوعی پتک که به طور کامل درخواست ها را برای اسناد ذخیره شده به سرور میخکوب می کند.

    برای انجام این کار، فقط سرصفحه Expires و Cache-Control: max-age را اضافه کنید.

    به عنوان مثال، برای کش کردن 365 روز در PHP:

    Header("Expires: ".gmdate("D, d M Y H:i:s", time()+86400*365)." GMT"); header("Cache-Control: max-age="+86400*365);

    یا می‌توانید با استفاده از mod_header در آپاچی، محتوا را به‌طور دائم کش کنید:

    با دریافت چنین هدرهایی، مرورگر سند را برای مدت طولانی ذخیره می کند. تمام دسترسی های بیشتر به سند مستقیماً از کش مرورگر بدون تماس با سرور انجام می شود.

    اکثر مرورگرها (Opera, اینترنت اکسپلورر 6+، سافاری) در صورت وجود علامت سوال در آدرس، اسناد را کش نکنید، زیرا آنها پویا در نظر گرفته می شوند.

    به همین دلیل نسخه را به نام فایل اضافه می کنیم. البته، با چنین آدرس هایی باید از راه حلی مانند mod_rewrite استفاده کنید، در ادامه مقاله به این موضوع خواهیم پرداخت.

    P.S اما فایرفاکس آدرس ها را با علامت سوال ذخیره می کند...

    وضوح نام خودکار

    بیایید نحوه تغییر خودکار و شفاف نسخه ها بدون تغییر نام خود فایل ها را بررسی کنیم.

    نام با نسخه -> فایل

    ساده ترین کار این است که نام همراه نسخه را به نام فایل اصلی تبدیل کنید.

    در سطح آپاچی این کار را می توان با 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 برای این مورد استفاده می شود:

    اضافه کردن سرصفحه "انقضا" "Mon, 28 Jul 2014 23:30:00 GMT" اضافه کردن سرصفحه "Cache-Control" "max-age=315360000"

    و با هم پیکربندی آپاچی زیر را پیاده سازی می کند:

    RewriteEngine در # نسخه را حذف می کند و در همان زمان متغیری را تنظیم می کند که فایل نسخه شده RewriteRule ^/(.*\.)v+\.(css|js|gif|png|jpg)$ /$1$2 # کش سخت فایل های نسخه شده Header add "Expires" "Mon, 28 Jul 2014 23:30:00 GMT" env=VERSIONED_FILE Header add "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"])؛ )

    نتیجه در صفحه:

    بهينه سازي

    برای جلوگیری از تماس‌های غیرضروری آمار، می‌توانید آرایه‌ای را با فهرستی از نسخه‌های فعلی در یک متغیر جداگانه ذخیره کنید.

    $versions["css"] = آرایه("group.css" => "1.1", "other.css" => "3.0"، )

    در این مورد، نسخه فعلی از آرایه به سادگی در HTML جایگزین می شود.

    شما می توانید از هر دو رویکرد عبور کنید و در طول توسعه یک نسخه را بر اساس تاریخ اصلاح - برای ارتباط و در تولید - یک نسخه از یک آرایه برای عملکرد تولید کنید.

    قابلیت کاربرد

    این روش کش در همه جا کار می کند، از جمله جاوا اسکریپت، CSS، تصاویر، فیلم های فلش و غیره.

    هر زمان که سند تغییر کند مفید است، اما مرورگر باید همیشه نسخه فعلی و به‌روز را داشته باشد.

    کش نقش مهمی در عملکرد تقریباً هر برنامه وب در سطح کار با پایگاه داده ها، وب سرورها و همچنین روی کلاینت ایفا می کند.

    در این مقاله سعی خواهیم کرد تا حافظه پنهان مشتری را درک کنیم. به طور خاص، ما بررسی خواهیم کرد که هدرهای HTTP توسط مرورگرها و سرورهای وب مورد استفاده قرار می گیرند و معنی آنها چیست.

    اما ابتدا، بیایید دریابیم که چرا اصلاً کش سمت مشتری نیاز است؟ .

    صفحات وب از تعداد زیادی تشکیل شده است عناصر مختلف: تصاویر، فایل های css و js و غیره برخی از این عناصر در چندین صفحه از سایت استفاده می شوند. کش سمت کلاینت به توانایی مرورگرها برای ذخیره کپی از فایل ها (پاسخ های سرور) اشاره دارد تا دوباره آنها را دانلود نکنند. این به شما امکان می دهد تا سرعت بارگذاری مجدد صفحه را به میزان قابل توجهی افزایش دهید، در ترافیک صرفه جویی کنید و همچنین بار روی سرور را کاهش دهید.

    چندین هدر HTTP مختلف برای کنترل فرآیندهای کش سمت مشتری وجود دارد. بیایید در مورد هر یک از آنها صحبت کنیم.

    هدرهای Http برای کنترل کش کردن مشتری

    ابتدا، بیایید به نحوه تعامل سرور و مرورگر در غیاب حافظه پنهان نگاه کنیم. برای درک واضح، سعی کردم روند ارتباط بین آنها را در قالب یک چت متنی تصور و تجسم کنم. برای چند دقیقه تصور کنید که سرور و مرورگر افرادی هستند که با یکدیگر مکاتبه دارند :)

    بدون کش (در صورت عدم وجود هدرهای http در حافظه پنهان)

    همانطور که می بینیم، هر بار که تصویر cat.png نمایش داده می شود، مرورگر آن را دوباره از سرور دانلود می کند. من فکر می کنم نیازی به توضیح نیست که این کار کند و بی اثر است.

    هدر پاسخ آخرین اصلاح شده و هدر درخواست if-Modified-Since.

    ایده این است که سرور یک هدر آخرین اصلاح شده را به فایل (پاسخ) که به مرورگر می دهد اضافه می کند.

    مرورگر اکنون می داند که فایل در 1 دسامبر 2014 ایجاد شده (یا اصلاح شده است). دفعه بعد که مرورگر به همان فایل نیاز داشته باشد، درخواستی با عنوان if-Modified-Since ارسال می کند.

    اگر فایل اصلاح نشده باشد، سرور یک پاسخ خالی با وضعیت 304 (Not Modified) به مرورگر ارسال می کند. در این حالت، مرورگر می‌داند که فایل به‌روزرسانی نشده است و می‌تواند نسخه‌ای را که آخرین بار ذخیره کرده است نمایش دهد.

    بنابراین، با استفاده از Last-Modified در بارگذاری صرفه جویی می کنیم فایل بزرگ، با یک پاسخ سریع خالی از سرور خارج می شود.

    هدر پاسخ Etag و هدر درخواست If-None-Match.

    اصل عملکرد Etag بسیار شبیه به Last-Modified است، اما بر خلاف آن، به زمان گره نخورده است. زمان یک چیز نسبی است.

    ایده این است که هنگام ایجاد و هر بار تغییر، سرور فایل را با یک تگ مخصوص به نام ETag تگ می کند و همچنین یک هدر به فایل (پاسخ) که به مرورگر ارسال می کند اضافه می کند:

    برچسب ET: "686897696a7c876b7e"

    اکنون مرورگر می داند که فایل نسخه فعلی دارای ETag برابر با "686897696a7c876b7e" است. دفعه بعد که مرورگر به همان فایل نیاز داشت، درخواستی با عنوان If-None-Match ارسال می کند: "686897696a7c876b7e".

    اگر منطبق نباشد: "686897696a7c876b7e"

    سرور می تواند برچسب ها را با هم مقایسه کند و در صورتی که فایل اصلاح نشده باشد، یک پاسخ خالی با وضعیت 304 (Not Modified) به مرورگر ارسال کند. مانند Last-modified، مرورگر متوجه می شود که فایل به روز نشده است و می تواند یک کپی از حافظه پنهان نمایش دهد.

    عنوان منقضی شده است

    اصل عملکرد این هدر با Etag و Last-modified که در بالا توضیح داده شد متفاوت است. با استفاده از Expired، "تاریخ انقضا" ("دوره مربوط") فایل تعیین می شود. آن ها در اولین بارگذاری، سرور به مرورگر اطلاع می دهد که تا تاریخ مشخص شده در Expired قصد تغییر فایل را ندارد:

    دفعه بعد، مرورگر با دانستن اینکه "تاریخ انقضا" هنوز نرسیده است، حتی سعی نمی کند درخواستی را به سرور ارائه دهد و فایل را از حافظه پنهان نمایش می دهد.

    این نوع کش مخصوصاً برای تصاویر مقالات، نمادها، فاویکون ها، برخی فایل های css و js و غیره مرتبط است.

    هدر کنترل حافظه پنهان با دستورالعمل حداکثر سن.

    اصل عملکرد Cache-control: max-age بسیار شبیه Expired است. در اینجا، "تاریخ انقضا" فایل نیز مشخص می شود، اما در ثانیه تنظیم می شود و به زمان خاصی وابسته نیست، که در بیشتر موارد بسیار راحت تر است.

    برای مرجع:

    • 1 روز = 86400 ثانیه
    • 1 هفته = 604800 ثانیه
    • 1 ماه = 2629000 ثانیه
    • 1 سال = 31536000 ثانیه

    به عنوان مثال:

    Cache-Control: max-age=2629000;

    هدر Cache-control علاوه بر حداکثر سن، دستورالعمل های دیگری نیز دارد. بیایید نگاهی گذرا به محبوب ترین آنها بیندازیم:

    عمومی
    واقعیت این است که درخواست‌ها نه تنها توسط مشتری نهایی کاربر (مرورگر)، بلکه توسط پروکسی‌های میانی مختلف، شبکه‌های CDN و غیره قابل ذخیره‌سازی هستند. بنابراین، دستورالعمل عمومی مطلقاً به هر سرور پروکسی اجازه می دهد تا مانند یک مرورگر، کش را انجام دهد.

    خصوصی
    بخشنامه بیان می کند که این فایل(پاسخ سرور) مختص کاربر نهایی است و نباید توسط پروکسی‌های میانی مختلف ذخیره شود. در عین حال، امکان کش کردن به مشتری نهایی (مرورگر کاربر) را فراهم می کند. به عنوان مثال، این مربوط به صفحات نمایه کاربر داخلی، درخواست‌های داخل یک جلسه و غیره است.

    به شما امکان می دهد مشخص کنید که کلاینت باید هر بار درخواستی از سرور ارائه کند. گاهی اوقات با هدر Etag که در بالا توضیح داده شد استفاده می شود.

    بدون فروشگاه
    به مشتری دستور می دهد که تحت هیچ شرایطی نباید یک کپی از درخواست یا بخش هایی از درخواست را نگه دارد. این سخت‌ترین سرصفحه است که هر حافظه پنهان را لغو می‌کند. این به طور خاص برای کار با اطلاعات محرمانه اختراع شد.

    باید تجدید اعتبار شود
    این دستورالعمل به مرورگر دستور می دهد تا درخواستی اجباری از سرور برای تأیید مجدد محتوا ارائه دهد (به عنوان مثال، اگر از eTag استفاده می کنید). واقعیت این است که http در یک پیکربندی خاص به حافظه پنهان اجازه می دهد تا محتوای قدیمی را ذخیره کند. must-revalidate مرورگر را موظف می‌کند که در هر شرایطی با درخواست از سرور، تازه بودن محتوا را بررسی کند.

    proxy-revalidate
    این همان چیزی است که باید مجدداً تأیید شود، اما فقط برای پراکسی‌های کش اعمال می‌شود.

    s-maxage
    عملاً تفاوتی با max-age ندارد، به جز اینکه این دستورالعمل فقط توسط حافظه پنهان پراکسی های مختلف در نظر گرفته می شود، اما توسط خود مرورگر کاربر نه. حرف "s -" از کلمه "به اشتراک گذاشته شده" (به عنوان مثال CDN) می آید. این دستورالعمل به طور خاص برای CDN ها و دیگر حافظه های پنهان واسطه در نظر گرفته شده است. مشخص کردن آن، مقادیر دستور حداکثر سن و هدر Expired را لغو می کند. با این حال، اگر شبکه‌های CDN نمی‌سازید، بعید است که هرگز به s-maxage نیاز نداشته باشید.

    چگونه می توانم ببینم چه هدرهایی در سایت استفاده می شود؟

    می توانید سرصفحه های درخواست http و سرصفحه های پاسخ را در دیباگر مرورگر مورد علاقه خود مشاهده کنید. در اینجا نمونه ای از ظاهر آن در کروم آمده است:

    همین مورد را می توان در هر مرورگر یا http sniffer که به خود احترام می گذارد مشاهده کرد.

    راه اندازی کش در Apache و Nginx

    ما اسناد را برای راه اندازی سرورهای محبوب بازگو نمی کنیم. شما همیشه می توانید آن را تماشا کنید و. در زیر چند مثال واقعی ارائه می دهیم تا نشان دهیم فایل های پیکربندی چگونه هستند.

    مثال تنظیمات آپاچیبرای کنترل Expires

    ما "تاریخ انقضا" متفاوتی را برای آن تعیین می کنیم انواع مختلففایل ها. یک سال برای تصاویر، یک ماه برای اسکریپت ها، استایل ها، پی دی اف ها و آیکون ها. برای هر چیز دیگری - 2 روز.

    ExpiresActive در ExpiresByType تصویر/jpg "دسترسی به اضافه 1 سال" ExpiresByType تصویر/jpeg "دسترسی به اضافه 1 سال" ExpiresByType تصویر/گیف "دسترسی به اضافه 1 سال" ExpiresByType تصویر/png "دسترسی به علاوه 1 سال" ExpiresByType plus 1saccess ماه" ExpiresByType برنامه/pdf "دسترسی به اضافه 1 ماه" ExpiresByType متن/x-javascript "دسترسی به اضافه 1 ماه" ExpiresByType تصویر/x-icon "دسترسی به اضافه 1 سال" Expiresپیش فرض "دسترسی به اضافه 2 روز"

    نمونه پیکربندی Nginx برای کنترل Expires

    ما "تاریخ انقضا" متفاوتی را برای انواع مختلف فایل ها تنظیم می کنیم. یک هفته برای تصاویر، یک روز برای سبک ها و اسکریپت ها.

    سرور ( #... مکان ~* \.(gif|ico|jpe?g|png)(\?+)?$ ( انقضا 1w; ) مکان ~* \.(css|js)$ ( انقضا 1d; ) #...)

    نمونه پیکربندی آپاچی برای کنترل کش (حداکثر سن و عمومی/خصوصی/بدون کش) مجموعه سرصفحه Cache-Control "max-age=2592000, public" مجموعه هدر Cache-Control "max-age=88000, private, must- revalidate" Header set Cache-Control "private, no-store, no-cache, must-revalidate, no-transform, max-age=0" مجموعه سرصفحه Pragma "no-cache" نمونه پیکربندی Nginx برای سرور فایل های استاتیک با کنترل کش ( #... مکان ~* \.(?:ico|css|js|gif|jpe?g|png)$ ( add_header Cache-Control "max-age=88000, public"; ) #... ) در نتیجه

    "هر چیزی را که می توان در حافظه پنهان ذخیره کرد" یک شعار خوب برای یک توسعه دهنده وب است. گاهی اوقات می توانید فقط چند ساعت را صرف پیکربندی کنید و در عین حال تجربه کاربری سایت خود را به میزان قابل توجهی بهبود بخشید، بار سرور را به میزان قابل توجهی کاهش دهید و در ترافیک صرفه جویی کنید. نکته اصلی این است که زیاده روی نکنید و همه چیز را با در نظر گرفتن ویژگی های منبع خود به درستی تنظیم کنید.

    ذخیره سازی با پیکربندی مناسب مزایای عملکردی عظیمی را ارائه می دهد، پهنای باند را صرفه جویی می کند و هزینه های سرور را کاهش می دهد، اما بسیاری از سایت ها حافظه پنهان را ضعیف اجرا می کنند و شرایط مسابقه ای ایجاد می کند که باعث می شود منابع به هم پیوسته از همگام سازی خارج شوند.

    اکثریت قریب به اتفاق بهترین شیوه هاحافظه پنهان به یکی از دو الگو اشاره دارد:

    الگوی شماره 1: محتوای غیرقابل تغییر و حافظه پنهان حداکثر سنی طولانی کش-کنترل: max-age=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"، "/styles-v2 .css" و "/cats-v1.jpg" نیاز دارم 08:14

    نقدی: یک عکس با گربه ها وجود دارد، اما بقیه نه. سرور؟ 08:14

    سرور: آسان - در اینجا CSS و JS جدید است. بار دیگر، نقدی: عمر مفید آنها بیش از یک سال نیست. 08:15

    پول نقد: عالی! 08:15

    صفحه: متشکرم! 08:15

    پول نقد: هوم، مدت زیادی است که از "/script-v1.js" و "/styles-v1.css" استفاده نکرده ام. زمان حذف آنها فرا رسیده است. 12:32

    با استفاده از این الگو، شما هرگز محتوای یک URL خاص را تغییر نمی دهید، بلکه خود URL را تغییر می دهید:

    هر URL چیزی دارد که همراه با محتوا تغییر می کند. این می تواند یک شماره نسخه، یک تاریخ اصلاح شده یا یک هش محتوا باشد (که من برای وبلاگ خود انتخاب کردم).

    اکثر چارچوب‌های سمت سرور ابزارهایی دارند که به شما امکان می‌دهند کارهایی از این قبیل را به راحتی انجام دهید (در جنگو من از Manifest​Static Files Storage استفاده می‌کنم). همچنین کتابخانه های بسیار کوچکی در Node.js وجود دارد که همان مشکلات را حل می کند، به عنوان مثال gulp-rev.

    با این حال، این الگو برای مواردی مانند مقالات و پست های وبلاگ مناسب نیست. URL های آنها را نمی توان نسخه کرد و محتوای آنها ممکن است تغییر کند. به طور جدی، من اغلب اشتباهات گرامری و نقطه گذاری دارم و باید بتوانم مطالب را به سرعت به روز کنم.

    الگوی شماره 2: محتوای قابل تغییر که همیشه در سرور Cache-Control اعتبار دارد: بدون کش
    • محتوای 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

    سرور: ... اما من "/about/" دارم نسخه جدید. پول نقد، نگه دارید، اما مانند دفعه قبل، فراموش نکنید که اول از من بپرسید. 09:47

    نقدی: فهمیدم! 09:47

    صفحه: عالی! 09:47

    توجه: no-cache به معنای "نه کش نیست" نیست، بلکه به معنای "بررسی" (یا تایید مجدد) منبع ذخیره شده در سرور است. و no-store به مرورگر می گوید که اصلاً کش نکند. همچنین، باید مجدداً اعتبارسنجی مجدد اجباری باشد، بلکه به این معناست که منبع ذخیره‌شده تنها در صورتی استفاده می‌شود که جوان‌تر از حداکثر سن تعیین‌شده باشد و فقط در غیر این صورت اعتبار مجدد می‌شود. همه چیز اینگونه شروع شد کلید واژه هابرای ذخیره سازی

    در این الگو، می‌توانیم یک ETag (شناسه نسخه دلخواه شما) یا یک هدر آخرین تغییر را به پاسخ اضافه کنیم. دفعه بعد که مشتری محتوا را درخواست کرد، به ترتیب یک If-None-Match یا If-Modified-Since خروجی می شود که به سرور اجازه می دهد بگوید "از آنچه دارید استفاده کنید، حافظه پنهان شما به روز است"، یعنی HTTP 304 را برگرداند.

    اگر ارسال ETag / Last-Modified امکان پذیر نباشد، سرور همیشه کل محتوا را ارسال می کند.

    این الگو همیشه به تماس های شبکه نیاز دارد، بنابراین به خوبی الگوی اول نیست، که می تواند بدون درخواست شبکه انجام شود.

    غیرعادی نیست که ما زیرساختی برای الگوی اول نداریم، اما ممکن است مشکلاتی در مورد درخواست های شبکه در الگوی 2 ایجاد شود. در نتیجه، از یک گزینه میانی استفاده می شود: حداکثر سن و محتوای قابل تغییر. این یک سازش بد است.

    استفاده از حداکثر سن با محتوای قابل تغییر معمولاً انتخاب اشتباهی است

    و متاسفانه، صفحات Github یک نمونه است.

    تصور کن:

    • /مقاله/
    • /styles.css
    • /script.js

    با هدر سرور:

    Cache-Control: باید مجدداً تأیید شود، حداکثر سن = 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 را تغییر می‌دهیم تا ساختار جدید را به درستی منعکس کند و هم جاوا اسکریپت را برای هماهنگی با محتوا و سبک. همه این منابع مستقل هستند، اما هدرهای کش نمی توانند این را بیان کنند. در نتیجه، کاربران ممکن است خودشان را پیدا کنند آخرین نسخهیک/دو منبع و نسخه قدیمی بقیه.

    حداکثر سن نسبت به زمان پاسخ تنظیم می شود، بنابراین اگر همه منابع به عنوان بخشی از یک آدرس واحد منتقل شوند، در همان زمان منقضی می شوند، اما هنوز احتمال کمی برای عدم همزمانی وجود دارد. اگر صفحاتی دارید که جاوا اسکریپت را شامل نمی شود یا سبک های دیگر را شامل می شود، تاریخ انقضای حافظه پنهان آنها همگام نیست. و بدتر از آن، مرورگر دائماً در حال بیرون کشیدن محتوا از حافظه نهان است، بدون اینکه بداند HTML، CSS و JS به یکدیگر وابسته هستند، بنابراین می تواند با خوشحالی یک چیز را از لیست خارج کند و همه چیز را فراموش کند. با در نظر گرفتن همه این عوامل در کنار هم، باید درک کنید که احتمال عدم تطابق نسخه ها بسیار زیاد است.

    برای کاربر، نتیجه ممکن است صفحه بندی شکسته یا مشکلات دیگر باشد. از اشکالات کوچک تا محتوای کاملاً غیرقابل استفاده.

    خوشبختانه کاربران دارای خروجی اضطراری هستند...

    تازه کردن صفحه گاهی کمک می کند

    اگر صفحه با به‌روزرسانی بارگیری شود، مرورگرها همیشه اعتبارسنجی مجدد سمت سرور را انجام می‌دهند و حداکثر سن را نادیده می‌گیرند. بنابراین، اگر کاربر به دلیل حداکثر سن چیزی خراب شده باشد، یک به‌روزرسانی ساده صفحه می‌تواند همه چیز را برطرف کند. اما، البته، پس از پیدا شدن قاشق ها، رسوبات همچنان باقی می ماند و نگرش نسبت به سایت شما تا حدودی متفاوت خواهد بود.

    یک کارگر خدماتی می تواند عمر این اشکالات را افزایش دهد

    به عنوان مثال، شما یک کارگر خدمات مانند زیر دارید:

    نسخه Const = "2"; self.addEventListener("install", event => ( event.waitUntil(caches.open(`static-$(version)`) .then(cache => cache.addAll([ "/styles.css", "/script .js" ]))))); self.addEventListener("activate", event => ( // …حذف کش های قدیمی... )); self.addEventListener("fetch", event => ( event.respondWith(caches.match(event.request) .then(response => پاسخ || fetch(event.درخواست))); ));

    این کارگر خدمات:

    • اسکریپت و سبک های کش
    • در صورت وجود مطابقت از حافظه پنهان استفاده می کند، در غیر این صورت به شبکه دسترسی پیدا می کند

    اگر CSS/JS را تغییر دهیم، شماره نسخه را نیز افزایش می‌دهیم که باعث به‌روزرسانی می‌شود. با این حال، از آنجایی که addAll ابتدا به حافظه نهان دسترسی پیدا می‌کند، می‌توانیم به دلیل حداکثر سن و نسخه‌های CSS و JS مطابقت نداشته باشیم.

    هنگامی که آنها کش شدند، ما CSS و JS ناسازگار را تا به‌روزرسانی بعدی سرویس‌کار خواهیم داشت - و این در صورتی است که در طول به‌روزرسانی دوباره در شرایط مسابقه قرار نگیریم.

    می‌توانید از کش کردن در سرویس‌کار صرفنظر کنید:

    Self.addEventListener("install", event => ( event.waitUntil(caches.open(`static-$(version)`) .then(cache => cache.addAll([ new Request("/styles.css", ( cache: "no-cache" )), new Request("/script.js"، ( cache: "no-cache" )) ])));

    متأسفانه، گزینه‌های کش در Chrome/Opera پشتیبانی نمی‌شوند و به تازگی به ساخت شبانه فایرفاکس اضافه شده‌اند، اما می‌توانید خودتان این کار را انجام دهید:

    Self.addEventListener("install", event => ( event.waitUntil(caches.open(`static-$(version)`) .then(cache => Promise.all([ "/styles.css", "/script Js. در 404، 500 و غیره if (!response.ok) throw Error("not ok" return(url, answer ))));

    در این مثال، من کش را با استفاده از یک عدد تصادفی بازنشانی می‌کنم، اما می‌توانید جلوتر رفته و در هنگام ساخت، یک هش از محتوا اضافه کنید (این شبیه کاری است که sw-precache انجام می‌دهد). این نوعی پیاده‌سازی الگوی اول با استفاده از جاوا اسکریپت است، اما فقط با سرویس‌کار کار می‌کند، نه مرورگرها و CDN.

    کارگران سرویس و کش HTTP با هم عالی کار می کنند، آنها را مجبور به جنگ نکنید!

    همانطور که می بینید، می توانید باگ های کش را در سرویس کار خود برطرف کنید، اما بهتر است ریشه مشکل را حل کنید. تنظیم صحیحذخیره سازی نه تنها کار سرویس دهنده را آسان تر می کند، بلکه به مرورگرهایی که از سرویس دهنده ها پشتیبانی نمی کنند (Safari، IE/Edge) کمک می کند و همچنین به شما امکان می دهد حداکثر استفاده را از CDN خود ببرید.

    هدرهای کش مناسب همچنین می تواند به روز رسانی یک سرویس دهنده را بسیار آسان تر کند.

    نسخه Const = "23"; self.addEventListener("نصب"، رویداد => ( event.waitUntil(caches.open(`static-$(نسخه)`) .then(cache => cache.addAll([ "/"، "/script-f93bca2c. js، "/styles-a837cb1e.css، "/cats-0e9a2ef4.jpg" ])))؛ ));

    در اینجا صفحه اصلی را با الگوی شماره 2 (تأیید مجدد سمت سرور) و سایر منابع با الگوی شماره 1 (محتوای غیرقابل تغییر) کش کردم. هر به روز رسانی Service Worker یک درخواست به صفحه اصلی ایجاد می کند و همه منابع دیگر تنها در صورتی بارگذاری می شوند که URL آنها تغییر کرده باشد. این خوب است زیرا باعث صرفه جویی در ترافیک و بهبود عملکرد می شود، صرف نظر از اینکه آیا از نسخه قبلی ارتقا می دهید یا خیلی نسخه قدیمی.

    در اینجا مزیت قابل توجهی نسبت به پیاده سازی بومی وجود دارد، زمانی که کل باینری حتی با یک تغییر کوچک بارگیری می شود یا باعث مقایسه پیچیده می شود. فایل های باینری. به این ترتیب می توانیم یک برنامه وب بزرگ را با بار نسبتاً کم به روز کنیم.

    کارکنان خدماتی به‌جای یک عصا موقت، به‌عنوان یک تقویت‌کننده بهتر عمل می‌کنند، بنابراین به جای مبارزه با آن، با حافظه پنهان کار کنید.

    وقتی با دقت استفاده می شود، محتوای حداکثر سن و متغیر می تواند بسیار خوب باشد

    حداکثر سن اغلب انتخاب اشتباهی برای محتوای قابل تغییر است، اما نه همیشه. به عنوان مثال، مقاله اصلی دارای حداکثر سن سه دقیقه است. شرایط مسابقه مشکلی نیست زیرا هیچ وابستگی در صفحه با استفاده از الگوی ذخیره‌سازی یکسان وجود ندارد (CSS، JS و تصاویر از الگوی شماره 1 استفاده می‌کنند - محتوای غیرقابل تغییر)، بقیه موارد از این الگو استفاده نمی‌کنند.

    این الگو به این معنی است که من می‌توانم به راحتی یک مقاله محبوب بنویسم، و CDN من (Cloudflare) می‌تواند بار را از روی سرور بردارد، به شرطی که سه دقیقه منتظر بمانم تا مقاله به‌روزرسانی شده در دسترس قرار گیرد. قابل دسترسی برای کاربران.

    این الگو باید بدون تعصب استفاده شود. اگر بخش جدیدی به مقاله اضافه کردم و از مقاله دیگری به آن لینک دادم، وابستگی ایجاد کردم که باید برطرف شود. کاربر می تواند روی لینک کلیک کرده و یک کپی از مقاله بدون قسمت مورد نظر دریافت کند. اگر بخواهم از این کار جلوگیری کنم، باید مقاله را بازخوانی کنم، نسخه کش مقاله را از Cloudflare حذف کنم، سه دقیقه صبر کنم و تنها پس از آن پیوند را به مقاله دیگری اضافه کنم. بله، این الگو نیاز به احتیاط دارد.

    هنگامی که به درستی استفاده می شود، حافظه نهان باعث بهبود عملکرد قابل توجه و صرفه جویی در پهنای باند می شود. اگر بتوانید به راحتی URL را تغییر دهید یا از اعتبارسنجی مجدد سمت سرور استفاده کنید، محتوای تغییرناپذیر را ارائه دهید. اگر به اندازه کافی شجاع هستید و مطمئن هستید که محتوای شما وابستگی‌هایی ندارد که می‌تواند از همگام‌سازی خارج شود، محتوای حداکثر سن و قابل تغییر را با هم ترکیب کنید.

    هنگام ایجاد تغییرات در وب‌سایت‌ها، اغلب با این واقعیت مواجه می‌شویم که محتویات صفحات، فایل‌های css و اسکریپت‌ها (.js) توسط مرورگر کش می‌شوند و برای مدت طولانی بدون تغییر باقی می‌مانند. این منجر به این واقعیت می شود که برای اینکه تغییرات ایجاد شده در همه مرورگرها منعکس شود، لازم است مشتریان را به ترکیبات پیچیده F5 یا Ctrl + F5 عادت دهید. و هر از گاهی مطمئن شوید که آنها فشرده شده اند.

    این روند کاملا خسته کننده و ناخوشایند است. البته می‌توانید با تغییر نام فایل‌ها در هر بار از وضعیت خارج شوید، اما باز هم ناخوشایند است.

    با این حال، راهی وجود دارد که به ما امکان می‌دهد با همان نام‌ها باقی بمانیم و ذخیره فایل‌های css. یا .js را در لحظه‌ای که به آن نیاز داریم، بازنشانی کنیم. و Ctrl + F5 را برای همیشه فراموش کنید.

    نکته اصلی این است که ما در پایان یک شبه پارامتر به فایل‌های css. یا .js خود اضافه می‌کنیم که هر از چند گاهی آن را تغییر می‌دهیم و در نتیجه حافظه پنهان مرورگر را بازنشانی می‌کنیم.

    بنابراین، ورود در کد منبعاکنون به شکل زیر خواهد بود:

    جایی که 186485 یک ترکیب دلخواه است که همان فایل را خروجی می‌کند، اما مرورگر به لطف شبه پارامتر آن را جدید تفسیر می‌کند. ?186485

    حال برای اینکه هر بار تمام رخدادهای پارامتر خود را تغییر ندهیم، آن را در یک فایل php قرار می دهیم که به تمام مکان هایی که نیاز داریم وصل می کنیم: