Say I for some reason want to serve my CSS through PHP (because of pre-processing, merging, etc). What do I need to do in my PHP to make this work well? Other than the most obvious:
header('content-type: text/css; charset=utf-8');
What about headers related to caching, modification times, etags, etc? Which ones should I use, why and how? How would I parse incoming headers and respond appropriately (304 Not Modified for example)?
Note: I know this can be tricky and that it would be a lot easier to just do what I want to do with the CSS before I deploy it as a regular CSS file. If I wanted to do it that way, I wouldn't have asked this question. I'm curious to how to do this properly and would like to know. What I do or could do beforehand with the CSS is irrelevant; I just want to know how to serve it properly :)
Note 2: I really would like to know how to do this properly. I feel most of the activity on this question has turned into me defending why I would want to do this, rather than getting answers on how to do this. Would very much appreciate it if someone could answer my question rather than just suggesting things like SASS. I'm sure it's awesome, and I might try it out sometime, but that's not what I'm asking about now. I want to know how to serve CSS through PHP and learn how to deal with the caching and things like that properly.
Css files will be stored in public folder. const http = require('http'); const path = require('path'); const express = require('express'); const bodyParser = require('body-parser'); const route = require('./routes'); const app = express(); app. use(bodyParser.
A commendable effort. Caching gets way too little good will. Please enjoy my short prose attempting to help you on your way.
Sending an ETag
and a Last-Modified
header will enable the browser to send a If-Modified-Since
and a If-None-Match
header back to your server on subsequent requests. You may then, when applicable, respond with a 304 Not Modified
HTTP status code and an empty body, i.e. Content-Length: 0
. Including a Expires
header will help you to serve fresh content one day when the content has indeed changed.
Sounds simple enough, but it can be a bit tricky to get just right. Luckily for us all, there is really good guidance available.
Once you get it up and running, please turn to REDbot to help you smooth out any rough corners you may have left in.
For the value of the ETag
, you will want to have something you can reproduce, but will still change whenever the content does. Otherwise you will not be able to tell whether the incoming value matches or not. A good candidate for a reproducible value which still changes when the content does, is an MD5 hash of the mtime
of the file being served through the cache. In your case, it would probably be a sum for all the files being merged.
For Last-Modified
the logical answer is the actual mtime
of the file being served. Why neglect the obvious. Or for a group of files, as in your case, use the most recent mtime
in the bunch.
For Expires
, simply choose an appropriate TTL
, or time-to-live, for the asset. Add this number to the asset's mtime
, or the value you chose for Last-Modified
, and you have your answer.
You may also want to include Cache-Control
headers to let possible proxies on the way know how to properly serve their clients.
For a more concrete response to your question, please refer to these questions predating yours:
The easiest way to serve CSS (or JavaScript) through PHP would be to use Assetic, a super-useful PHP asset manager similar to Django's contrib.staticfiles or Ruby's Jammit. It handles caching and cache invalidation, dynamic minification, compression, and all the "tricky bits" that were mentioned in other answers.
To understand how to write your own asset server properly, I strongly recommend you read Assetic's source code. It's very commented and readable, and you'll learn a lot about best practices regarding caching, minification, and everything else that Assetic does so well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With