During development, nothing's more frustrating than making CSS/JS changes that don't reflect in the browser. Our team encountered this exact issue with Nginx in a VirtualBox environment, where HTML files updated properly but JavaScript and CSS files stubbornly served stale content despite correct cache headers.
Here's our original nginx configuration that worked for HTML but failed for other static files:
server {
server_name static.server.local;
root /var/www/static;
location / {
access_log off;
expires 0;
add_header Cache-Control private;
}
}
The root cause wasn't Nginx's caching mechanism, but rather VirtualBox's shared folder implementation interacting with Nginx's sendfile
system call. When files were edited from the host OS (Mac OSX in our case), the changes weren't properly detected through the VirtualBox shared folder interface.
Adding this single directive to your nginx configuration completely resolves the issue:
http {
sendfile off;
server {
# Your existing server configuration
}
}
For those who can't disable sendfile globally, you can target specific locations:
location /static/ {
sendfile off;
expires 0;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
}
As an additional measure during development, consider adding cache-busting query parameters:
location ~* \.(js|css)$ {
sendfile off;
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-cache, must-revalidate, proxy-revalidate';
if ($query_string ~* "v=\d+\.\d+\.\d+") {
expires 1y;
}
}
For more reliable change detection in VirtualBox shared folders, you might want to configure Nginx to not rely on filesystem metadata:
server {
# ... other config ...
location / {
sendfile off;
directio 4k;
open_file_cache off;
}
}
Working with static files in a development environment often requires immediate visibility of changes without cache interference. A common Nginx configuration for this scenario looks like:
server {
server_name static.server.local;
root /var/www/static;
location / {
access_log off;
expires 0;
add_header Cache-Control private;
}
}
While HTML files respond as expected (returning 304 for unmodified files and 200 with fresh content when modified), CSS and JavaScript files exhibit strange behavior - they return 200 status but serve stale content after modification.
The headers appear correct:
Cache-Control:max-age=0
private
Expires:Fri, 13 May 2011 14:13:13 GMT
Last-Modified:Fri, 13 May 2011 14:13:05 GMT
The issue becomes more puzzling when considering the VirtualBox environment. Files edited:
- Via host IDE (NetBeans on Mac OSX) → Changes not reflected
- Via guest editor (vim on Ubuntu) → Changes appear immediately
The solution lies in VirtualBox's interaction with Nginx's sendfile
mechanism. VirtualBox's shared folder system (vboxsf) doesn't properly handle sendfile
operations, leading to caching anomalies.
Here's the complete working configuration for VirtualBox development environments:
server {
server_name static.server.local;
root /var/www/static;
sendfile off; # Critical for VirtualBox shared folders
location / {
access_log off;
expires 0;
add_header Cache-Control "no-store, no-cache, must-revalidate";
add_header Pragma "no-cache";
# Additional headers for maximum cache prevention
add_header Last-Modified "";
if_modified_since off;
}
}
For comprehensive cache prevention:
- Add version hashes to filenames in production (e.g., styles.a1b2c3.css)
- Consider browser hard reload (Ctrl+F5) during development
- For VirtualBox users: Keep guest additions updated
Verify with curl:
curl -I http://static.server.local/test.css
Look for these critical headers:
Cache-Control: no-store, no-cache, must-revalidate
Expires: 0
Pragma: no-cache