Tag Archive caching

Byphunsanit

PHP: no-cache css javascript

ตามคำแนะนำในการทำเว็บให้เร็วคือให้แยกไฟล์ภาพ, css และ javascript ออกมาเพราะว่าไฟล์พวกนี้แทบจะเหมือนๆ กันทุกๆหน้า และเปลี่ยนไม่บ่อยนัก การ set server จึงกำหนดให้ทางฝั่ง browser จดจำ static content (css, images,js files) พวกนี้เอาไว้ จะได้ไม่ต้องโหลดไฟล์พวกนี้ใหม่ ทำให้สิ้นเปลือง (สิ้นเปลือง bandwide แบนด์วิธอันล้ำค่าและมีราคาที่เช่ามาจาก isp และ cpu, ram ที่ใช่จัดการจ่ายไฟล์จาก server ไปให้บราวน์เซอร์ของยูเซอร์)

ปัญหาก็คือ เมื่อเราแก้ไฟล์ image, css หรือ javascript อัพโหลดขึ้นไปบน server แล้วแต่ user ยังได้รับไฟล์ version เดิมๆ อยู่ ที่นิยมกันก็คือ ใส่ตัวแปรแบบสุ่มหรือเวลาตามหลังชื่อไฟล์ เช่น

<link href="styles.css?ts=150151" rel="stylesheet" type="text/css">
...
<script src="scripts.js?ts=150151">
...
<img src="logo.png?ts=150151">

เมื่อต้องการให้ใช้ไฟล์ version ใหม่ก็เปลี่ยนค่าของ ts เป็นค่าอื่น ตัว browser จะถือว่าเป็นคนละไฟล์กับไฟล์เดิมที่เก็บไว้ใน cache ของมันเอง ปัญหาก็คือถ้ามีไฟล์พวกนี้ 100 จุด หรือ 1000 จุดก็ต้องไล่แก้ทั้งหมดให้เหมือนๆกันถึงจะเปลี่ยนไฟล์ทุกตัวให้เป็นตัวใหม่พร้อมๆกัน อาจจะทำเป็น global variable หรือใช้ function จัดการให้แต่มันซับซ้อนเกินไป

อีกวิธีที่ทำได้ง่ายแต่ได้ผลกับทุกๆ ไฟล์คือใช้

header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');

เมื่อต้องการให้ browser โหลดไฟล์ใหม่อีกครั้ง โดยใส่ใน header ของเว็บ

อ่านเพิ่มเติม HTTP Caching

Byphunsanit

CodeIgniter: Cache

เพื่อให้ผู้ใช้เข้าหน้าเพจด้วยความรวดเร็วจึงต้องทำ caching เก็บส่วนที่ไม่ได้เปลี่ยนแปลงบ่อย และสามารถใช้ซ่้ำๆ ได้

เริ่มจากสร้างไฟล์เก็บ config ขึ้นมาก่อน

<?php
defined('BASEPATH') or exit('No direct script access allowed');

$config['caching']['adapter'] = 'memcached';
$config['caching']['backup'] = 'file';

โดย

adapter
คือ จะเลือกใช้ driver ตัวไหนในการทำ cache ระหว่าง

Drivers Value
Alternative PHP Cache (APC) Caching apc
Dummy Cache dummy
File-based Caching file
Memcached Caching memcached
Redis Caching redis
WinCache Caching wincache
backup
เป็นตัวเลือกสำรองถ้าตัวแรกไม่สามารถทำงานได้ เช่น เครื่องที่เราใช้ไม่ได้ลง Memcached ไว้ ก็จะใช้ file แทน ( cache file ถูกเก็บไว้ที่ \application\cache หรือ ตาม config $config[‘cache_path’])

โหลด Driver ได้ 2 วิธีคือ

Auto-loading
เหมาะกับงานที่ต้องใช้ cache บ่อยๆ ทำได้โดยเพิ่ม ‘cache’ เข้าไป

$autoload['drivers'] = [..., 'cache', ...];
load driver
โหลด driver เฉพาะ controller ที่ต้องใช้ cache เท่านั้น

    public function __construct()
    {
        parent::__construct();

        $this->load->driver('cache');
    }

การใช้งาน

<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Welcome extends CI_Controller
{
    /**
     * Index Page for this controller.
     *
     * Maps to the following URL
     *         http://example.com/index.php/welcome
     *    - or -
     *         http://example.com/index.php/welcome/index
     *    - or -
     * Since this controller is set as the default controller in
     * config/routes.php, it's displayed at http://example.com/
     *
     * So any other public methods not prefixed with an underscore will
     * map to /index.php/welcome/<method_name>
     * @see https://codeigniter.com/user_guide/general/urls.html
     */
    public function index()
    {
        $cacheKey = 'home' . date('Y-m-d'); /* unque id */
        $cacheKey = mb_ereg_replace('([^\w\s\d\-_~,;\[\]\(\).])', '', $cacheKey);

        if (!$datas = $this->cache->get($cacheKey)) {

            $datas = $this->load->view('welcome_message', '', true);

            $this->cache->save($cacheKey, $datas, 300);
        }

        echo $datas;
    }

}

เพราะว่า file driver เป็นการเขียนไฟล์ลงบน hard disk จริงๆ จึงควรแน่ใจว่าไฟล์ถูกรูปแบบที่ os สามารถเขียนไฟล์ได้ โดนอาจจะใช้ md5 เข้ารหัส $cacheKey ก่อน

$cacheKey = md5($cacheKey);

หรือใช้

$cacheKey = mb_ereg_replace('([^\w\s\d\-_~,;\[\]\(\).])', '', $cacheKey);

อ่านเพิ่มเติม