{"id":807,"date":"2015-04-27T18:12:00","date_gmt":"2015-04-27T16:12:00","guid":{"rendered":"https:\/\/blog.risingstack.comautomatic-cache-busting-for-your-css\/"},"modified":"2024-07-04T10:11:20","modified_gmt":"2024-07-04T08:11:20","slug":"automatic-cache-busting-for-your-css","status":"publish","type":"post","link":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/","title":{"rendered":"Automatic Cache Busting for Your CSS"},"content":{"rendered":"\n<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>This article is a guest post from&nbsp;<a href=\"https:\/\/twitter.com\/sufianrhazi\">Sufian Rhazi<\/a>, who is a speaker at&nbsp;<a href=\"http:\/\/jsconfbp.com\/?utm_source=rsblog&amp;utm_medium=cachebusting&amp;utm_campaign=JSConf\/\">JSConf Budapest<\/a>&nbsp;on 14-15th May 2015.<\/p><\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"astsandcodetransformation\">ASTs and Code Transformation<\/h2>\n\n\n\n<p>In order to have a high-performance website, you\u2019ve got to take advantage of HTTP caching. If a CDN or your browser has some of your site in its cache, that translates to less time waiting for packets to transfer over the wire.<\/p>\n\n\n\n<p>In an ideal world, all of your JS, CSS, and images should be able to live in a cache forever. But how can this be done if these assets need to change over time?<\/p>\n\n\n\n<p>In this article, I\u2019ll show you a strategy to transform image URLs in your CSS files so that you can make your website faster.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"httpcaching101\">HTTP Caching 101<\/h2>\n\n\n\n<p>HTTP works on request and response pairs: a request is made to a URL, and a response contains the contents of the resource that exists at that URL.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img fetchpriority=\"high\" decoding=\"async\" width=\"287\" height=\"277\" src=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/request-response-without-cache-busting.png\" alt=\"Request -&gt; Response without Cache Busting\" class=\"wp-image-1083\"\/><\/figure>\n\n\n\n<p>Responses also can hold&nbsp;<a href=\"http:\/\/tools.ietf.org\/html\/rfc7234\">caching headers<\/a>&nbsp;that tell clients that they can re-use responses to requests if certain conditions apply. For example, if you ask for the same URL twice within the cache lifetime, you\u2019ll be able to save a network request and get the second response from a cache.<\/p>\n\n\n\n<p>Since URLs are the primary key for determining whether a response is contained in a cache, it\u2019s common practice to add a cache buster to a URL in order to force the request to be unique and avoid a cached response.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cssandcachebusting\">CSS and Cache Busting<\/h2>\n\n\n\n<p>Your CSS probably contains several image URL references. Since we want to take advantage of caching, it\u2019d be fantastic if we could tell clients that our images should be cacheable forever. Adding a&nbsp;<code>Cache-Control: max-age=31536000<\/code>&nbsp;header and an&nbsp;<code>Expires<\/code>&nbsp;header with a year from now date should do the trick.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em>\/* File: simple.css *\/<\/em>\n\n.simple {\n    background: url('one.jpg');\n}\n.complex {\n    background: url(\"two.png\") center bottom no-repeat,\n        url(three.png) left top no-repeat;\n}\n<\/code><\/pre>\n\n\n\n<p>When your browser sees this CSS file and needs to render matching HTML, it will make requests for those images. If we set the expiration date to a year, browsers will only need to make requests to those images once. But what if the images need to be changed?<\/p>\n\n\n\n<p>We\u2019ll need to add a cache buster to these URLs so that we don\u2019t accidentally show people the old cached images. Some people suggest adding timestamps or numbers in a query parameter to the URLs, but I prefer to add a hash of the contents to the filename itself, since that will always change when the image contents change and additionally&nbsp;<a href=\"https:\/\/github.com\/h5bp\/server-configs-apache\/blob\/02a601e5914a504e019c46b76bb21adab89cb686\/src\/.htaccess#L677-692\">work with all HTTP caches<\/a>.<\/p>\n\n\n\n<p>For this, since we care mostly about the hash value changing if images we provide have changed, let\u2019s use&nbsp;<a href=\"http:\/\/en.wikipedia.org\/wiki\/MD5\">MD5<\/a>, a cryptographic hash function. While MD5 is not appropriate for verification of untrusted data, it does provide&nbsp;<a href=\"http:\/\/stackoverflow.com\/a\/8199245\">uniform distribution<\/a>&nbsp;when truncated and if we use the first 32 bits, there will be a&nbsp;1 in 3,506,097&nbsp;chance of a collision if we have 50 revisions of the same file. That seems to be pretty good odds for most sites, but you could always add more bits for additional collision resistance.<\/p>\n\n\n\n<p>If we place these cache busters right before the file extension and strip it out server side, when a file gets modified and our images get new cache busters, the HTTP requests will look like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"687\" height=\"335\" src=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/cache-busting-and-file-changes.png\" alt=\"Cache Busting and File Changes\" class=\"wp-image-1082\" srcset=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/cache-busting-and-file-changes.png 687w, https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/cache-busting-and-file-changes-300x146.png 300w\" sizes=\"(max-width: 687px) 100vw, 687px\" \/><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><strong>Note<\/strong>: Before&nbsp;<a href=\"https:\/\/tools.ietf.org\/html\/rfc7230\">RFC 7230<\/a>&nbsp;was published,&nbsp;<a href=\"https:\/\/tools.ietf.org\/html\/rfc2616\">RFC 2616<\/a>&nbsp;had language which&nbsp;<a href=\"http:\/\/www.rfc-editor.org\/errata_search.php?rfc=2616&amp;eid=3056\">did not include the query as part of the URL<\/a>. There are many&nbsp;<a href=\"http:\/\/stevesouders.com\/blog\/2008\/08\/23\/revving-filenames-dont-use-querystring\">old and misconfigured caches<\/a>&nbsp;which do not accept the latest HTTP standards, I would avoid using query parameters for cache busting.<\/p><\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"transformingyourcssinjs\">Transforming Your CSS in JS<\/h2>\n\n\n\n<p>So let\u2019s write some JS that transforms the above simple.css to what we want:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em>\/* File: simple.transformed.css *\/<\/em>\n\n.simple {\n    background: url(one.cbe7e7eb.jpg);\n}\n\n.complex {\n    background: url(two.b4238023.png) center bottom no-repeat,\n        url(three.c8bf6e59.png) left top no-repeat;\n}\n<\/code><\/pre>\n\n\n\n<p>Instead of blindly replacing strings, let\u2019s parse the file into an AST, search for URLs within the AST, replace them with URLs that contain the cache buster and then generate the built CSS file from the transformed AST. To do this, we\u2019ll be using the gonzales and MD5 <span class=\"glossary-tooltip glossary-term-2996\" tabindex=\"0\"><span class=\"glossary-link\"><a href=\"https:\/\/blog.risingstack.com\/glossary\/npm\/\" target=\"_blank\" class=\"glossary-only-link\">npm<\/a><\/span><span class=\"hidden glossary-tooltip-content clearfix\"><span class=\"glossary-tooltip-text\">npm is a software registry that serves over 1.3 million packages. npm is used by open source developers from all around the world to share and borrow code, as well as many businesses. There are three components to npm: the website the Command Line Interface (CLI) the registry Use the website to discover and download packages, create user profiles, and...<\/span><\/span><\/span> packages to parse CSS and calculate MD5 hashes.<\/p>\n\n\n\n<p>Gonzales has a very simple API. The core transformation function in our script is very straightforward:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var fs = require('fs');\nvar path = require('path');\nvar gonzales = require('gonzales');\nvar md5 = require('MD5');\n\nfunction transformCSS(sourcePath, destPath) {\n    var contents = fs.readFileSync(sourcePath, 'utf-8');\n    \n    <em>\/\/ Parse our CSS into an AST<\/em>\n    var ast = gonzales.srcToCSSP(contents);\n    \n    <em>\/\/ Perform the AST transformation<\/em>\n    var transformedAst = transformAst(ast, versionUrl);\n\n    <em>\/\/ Generate CSS from the transformed AST<\/em>\n    var output = gonzales.csspToSrc(ast);\n    fs.writeFileSync(destPath, output, 'utf-8');\n}\n<\/code><\/pre>\n\n\n\n<p>Once we parse the source with gonzales, we have an AST, which gonzales represents as a nested array. It\u2019s a bit of a strange format, but our original CSS looks like this parsed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#091;\"stylesheet\",\n  &#091;\"ruleset\",\n    &#091;\"selector\",\n      &#091;\"simpleselector\",\n        &#091;\"clazz\",\n          &#091;\"ident\", \"simple\"]\n        ],\n        &#091;\"s\", \" \"]\n      ]\n    ],\n    &#091;\"block\",\n      &#091;\"s\", \" \"],\n      &#091;\"declaration\",\n        &#091;\"property\",\n          &#091;\"ident\", \"background\"]\n        ],\n        &#091;\"value\",\n          &#091;\"s\", \" \"],\n          &#091;\"uri\", &#091; \"string\", \"\\\"one.jpg\\\"\"]]\n        ]\n      ]\n    ]\n    ...etc...\n<\/code><\/pre>\n\n\n\n<p>If you look through the gonzales AST documentation, you can find out what each of these arrays means. But if you just tilt your head to the side, squint a little, and ignore the s items that represent whitespace, you\u2019ll see this tree:<\/p>\n\n\n\n<p>ast<\/p>\n\n\n\n<p>Which represents the first part of our CSS file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.simple {\n    background: url(\"one.jpg\");\n}\n<\/code><\/pre>\n\n\n\n<p>This data structure represents the parsed values of the CSS code. Now all we need to do is find all of the URL nodes and replace them with a filename that includes the cache busting hash.<\/p>\n\n\n\n<p>So all we need to do is write a recursive function which will walk through the AST and replace the nodes with the result of a visitor:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function transformAst(node, transformer) {\n    for (var i = 1; i &lt; node.length; ++i) {\n        if (Array.isArray(node&#091;i])) {\n            node&#091;i] = transformAst(node&#091;i], transformer);\n        }\n    }\n    return transformer(node);\n}\n<\/code><\/pre>\n\n\n\n<p>With this transformAst function, we can simply write a visitor function looks for uri nodes and replaces them with those that have cache-busting paths:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>function transformWalker(node) {\n    if (node&#091;0] === 'uri') {\n        var url;\n        <em>\/\/ There are 2 types of strings in URI nodes<\/em>\n        if (node&#091;1]&#091;0] === 'string') {\n            <em>\/\/ One which is surrounded by quotes<\/em>\n            url = node&#091;1]&#091;1].substr(1, node&#091;1]&#091;1].length - 2);\n        } else if (node&#091;1]&#091;0] === 'raw') {\n            <em>\/\/ The other which is simply raw text<\/em>\n            url = node&#091;1]&#091;1];\n        }\n        var buffer = fs.readFileSync(url);\n        var cachebuster = md5(buffer).substr(0, 8); <em>\/\/ only first 32 bits<\/em>\n        var ext = path.extname(url);\n        var versioned = url.substr(0, ext.length) + cachebuster + ext;\n        return &#091;'uri', &#091;'raw', versioned]];\n    }\n    return node;\n}\n<\/code><\/pre>\n\n\n\n<p>And there we have it, a script that adds cache busting hashes to image URLs found within a CSS file!<\/p>\n\n\n\n<p>Using ASTs is a strategy that can be used to accomplish tasks that are much more complex than simple string replacement. It could be used to programmatically change CSS units, perform automatic browser prefixing of declaration properties, or do even more drastic structural changes. In fact, it\u2019d be very easy to modify this code to automatically inline small images into base64 data uris, which could save additional HTTP requests.<\/p>\n\n\n\n<p>AST transformation is not limited to CSS; this can be used to parse&nbsp;<strong>any<\/strong>&nbsp;structured languages: JavaScript, HTML, CSS, C, Go, Lisp, C++, Haskell, or even FORTRAN. So go ahead and&nbsp;<strong>use your newfound skills to transform your code!<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>This article is a guest post from\u00a0<a href=\"https:\/\/twitter.com\/sufianrhazi\">Sufian Rhazi<\/a>, who is a speaker at\u00a0<a href=\"http:\/\/jsconfbp.com\/?utm_source=rsblog&amp;utm_medium=cachebusting&amp;utm_campaign=JSConf\/\">JSConf Budapest<\/a>\u00a0on 14-15th May 2015.<\/p><\/blockquote>\n\n\n\n<p>\n","protected":false},"excerpt":{"rendered":"<p>A strategy that takes advantage of HTTP cache busting to transform image URLs in your CSS files, so that you can make your website even faster.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[14],"class_list":["post-807","post","type-post","status-publish","format-standard","hentry","category-devops","tag-edited"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Automatic Cache Busting for Your CSS - RisingStack Engineering<\/title>\n<meta name=\"description\" content=\"A strategy that takes advantage of HTTP cache busting to transform image URLs in your CSS files, so you can make your website even faster.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Automatic Cache Busting for Your CSS - RisingStack Engineering\" \/>\n<meta property=\"og:description\" content=\"A strategy that takes advantage of HTTP cache busting to transform image URLs in your CSS files, so you can make your website even faster.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/\" \/>\n<meta property=\"og:site_name\" content=\"RisingStack Engineering\" \/>\n<meta property=\"article:published_time\" content=\"2015-04-27T16:12:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-07-04T08:11:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/request-response-without-cache-busting.png\" \/>\n<meta name=\"author\" content=\"RisingStack Engineering\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"RisingStack Engineering\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/\"},\"author\":{\"name\":\"RisingStack Engineering\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#\\\/schema\\\/person\\\/7cd795f2e5173258661ba604144b0b22\"},\"headline\":\"Automatic Cache Busting for Your CSS\",\"datePublished\":\"2015-04-27T16:12:00+00:00\",\"dateModified\":\"2024-07-04T08:11:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/\"},\"wordCount\":1037,\"publisher\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2021\\\/07\\\/request-response-without-cache-busting.png\",\"keywords\":[\"edited\"],\"articleSection\":[\"DevOps\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/\",\"name\":\"Automatic Cache Busting for Your CSS - RisingStack Engineering\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2021\\\/07\\\/request-response-without-cache-busting.png\",\"datePublished\":\"2015-04-27T16:12:00+00:00\",\"dateModified\":\"2024-07-04T08:11:20+00:00\",\"description\":\"A strategy that takes advantage of HTTP cache busting to transform image URLs in your CSS files, so you can make your website even faster.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/#primaryimage\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2021\\\/07\\\/request-response-without-cache-busting.png\",\"contentUrl\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2021\\\/07\\\/request-response-without-cache-busting.png\",\"width\":287,\"height\":277},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/automatic-cache-busting-for-your-css\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blog.risingstack.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Automatic Cache Busting for Your CSS\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#website\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/\",\"name\":\"RisingStack Engineering\",\"description\":\"Node.js Tutorials &amp; Resources\",\"publisher\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blog.risingstack.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#organization\",\"name\":\"RisingStack Engineering\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/logo-white-f0fca36fce94ceacd3d608caa6649361-1.svg\",\"contentUrl\":\"https:\\\/\\\/blog.risingstack.com\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/logo-white-f0fca36fce94ceacd3d608caa6649361-1.svg\",\"width\":180,\"height\":45,\"caption\":\"RisingStack Engineering\"},\"image\":{\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blog.risingstack.com\\\/#\\\/schema\\\/person\\\/7cd795f2e5173258661ba604144b0b22\",\"name\":\"RisingStack Engineering\",\"url\":\"https:\\\/\\\/blog.risingstack.com\\\/author\\\/coolsp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Automatic Cache Busting for Your CSS - RisingStack Engineering","description":"A strategy that takes advantage of HTTP cache busting to transform image URLs in your CSS files, so you can make your website even faster.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/","og_locale":"en_US","og_type":"article","og_title":"Automatic Cache Busting for Your CSS - RisingStack Engineering","og_description":"A strategy that takes advantage of HTTP cache busting to transform image URLs in your CSS files, so you can make your website even faster.","og_url":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/","og_site_name":"RisingStack Engineering","article_published_time":"2015-04-27T16:12:00+00:00","article_modified_time":"2024-07-04T08:11:20+00:00","og_image":[{"url":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/request-response-without-cache-busting.png","type":"","width":"","height":""}],"author":"RisingStack Engineering","twitter_card":"summary_large_image","twitter_misc":{"Written by":"RisingStack Engineering","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/#article","isPartOf":{"@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/"},"author":{"name":"RisingStack Engineering","@id":"https:\/\/blog.risingstack.com\/#\/schema\/person\/7cd795f2e5173258661ba604144b0b22"},"headline":"Automatic Cache Busting for Your CSS","datePublished":"2015-04-27T16:12:00+00:00","dateModified":"2024-07-04T08:11:20+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/"},"wordCount":1037,"publisher":{"@id":"https:\/\/blog.risingstack.com\/#organization"},"image":{"@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/request-response-without-cache-busting.png","keywords":["edited"],"articleSection":["DevOps"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/","url":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/","name":"Automatic Cache Busting for Your CSS - RisingStack Engineering","isPartOf":{"@id":"https:\/\/blog.risingstack.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/#primaryimage"},"image":{"@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/request-response-without-cache-busting.png","datePublished":"2015-04-27T16:12:00+00:00","dateModified":"2024-07-04T08:11:20+00:00","description":"A strategy that takes advantage of HTTP cache busting to transform image URLs in your CSS files, so you can make your website even faster.","breadcrumb":{"@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/#primaryimage","url":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/request-response-without-cache-busting.png","contentUrl":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/07\/request-response-without-cache-busting.png","width":287,"height":277},{"@type":"BreadcrumbList","@id":"https:\/\/blog.risingstack.com\/automatic-cache-busting-for-your-css\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.risingstack.com\/"},{"@type":"ListItem","position":2,"name":"Automatic Cache Busting for Your CSS"}]},{"@type":"WebSite","@id":"https:\/\/blog.risingstack.com\/#website","url":"https:\/\/blog.risingstack.com\/","name":"RisingStack Engineering","description":"Node.js Tutorials &amp; Resources","publisher":{"@id":"https:\/\/blog.risingstack.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.risingstack.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/blog.risingstack.com\/#organization","name":"RisingStack Engineering","url":"https:\/\/blog.risingstack.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.risingstack.com\/#\/schema\/logo\/image\/","url":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/05\/logo-white-f0fca36fce94ceacd3d608caa6649361-1.svg","contentUrl":"https:\/\/blog.risingstack.com\/wp-content\/uploads\/2021\/05\/logo-white-f0fca36fce94ceacd3d608caa6649361-1.svg","width":180,"height":45,"caption":"RisingStack Engineering"},"image":{"@id":"https:\/\/blog.risingstack.com\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/blog.risingstack.com\/#\/schema\/person\/7cd795f2e5173258661ba604144b0b22","name":"RisingStack Engineering","url":"https:\/\/blog.risingstack.com\/author\/coolsp\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/posts\/807","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/comments?post=807"}],"version-history":[{"count":1,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/posts\/807\/revisions"}],"predecessor-version":[{"id":4230,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/posts\/807\/revisions\/4230"}],"wp:attachment":[{"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/media?parent=807"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/categories?post=807"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.risingstack.com\/wp-json\/wp\/v2\/tags?post=807"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}