You can use dynamic imports - if you're using ES6 modules (which seems to be the case) - or the Cache-Control response header if you're using any server that allows you to control your response headers through files like .htaccess
.
I know this question is 5 years old, but I faced this problem yesterday and bundlers are not always available for all types of projects.
Solution 1: Dynamic Imports
Dynamic imports can be used at the top level of a module just like the regular import
declaration. You just need to add the await
operator and assign its value to a constant.
The following example considers that you are using PHP and that you do not wish to emit your import line with it, only the version number.
index.php
<?php
// Add your dynamic version number somewhere accessible
// to JS (constant, element attribute, etc.).
echo '<script>const assetsVersion = "' . $assets_version . '";</script>';
app.js
// Add your import to the top-level of your module referencing
// the version number in the string.
const { MyImport } = await import("./my-import.js?v=" + assetsVersion);
This solution allows you to keep your current cache-bust technique - and also works regardless of the back-end technology used.
Solution 2: Cache-Control
This option requires you to modify your .htaccess
file. Setting the no-cache
response directive will make your browser validate your cached assets before actually using them (not the same as the no-store
directive).
The validation is done through the If-None-Match
and the If-Modified-Since
request headers. The server will respond with a 304 status code if the file wasn't modified or with a 200 status code if the asset was updated - causing your browser to re-download it.
.htaccess
<IfModule mod_headers.c>
<FilesMatch "\.(css|js)$">
Header set Cache-Control "no-cache"
</FilesMatch>
</IfModule>
If you're using Apache you might face issues with your server always returning 200 (due to a bug as far as I know). Removing the ETag
header will probably solve it (worked for me):
<IfModule mod_headers.c>
<FilesMatch "\.(css|js)$">
Header set Cache-Control "no-cache"
Header unset ETag
</FilesMatch>
</IfModule>
This solution affects both module imports and normal scripts.