Adding a cookie in Shopify - javascript

I am trying to add a value in cookie in my store. Javascript is not an option because the content of the cookie needs to be invisible on the client-side page source.
In a PHP server it's done using a code like this:
<?php
$cookie_name = "PHPsecret";
$cookie_value = "The secret";
setcookie($cookie_name, $cookie_value, time() + (86400 * 30), "/"); // 86400 = 1 day
?>
Can someone please help me acheive this in Shopify? Even if it can be done with some work-around trick such as manipulating the cart attribiute etc. it's okay. Let me know how.
Much appreciated.

I needed to pass a Shopify variable, {{ cart.item_count }} to a subdomain using a cookie. For me, adding this in Javascript at the bottom of theme.liquid did the trick:
<script>
var nowCart = new Date();
var timeCart = nowCart.getTime();
var expireTimeCart = timeCart + 1000*36000;
nowCart.setTime(expireTimeCart); // " + nowCart.toUTCString() + "
document.cookie = "_count={{ cart.item_count }};domain=.example.com;expires=;SameSite=none;Secure=true";
</script>
</body>
</html>
In Shopify Liquid, there is to the best of my knowledge no way to "hide" a cookie. In fact, anyone who knows how to open their dev tools would be able to read your cookie either way...does it really need to stay a secret (consider adding it to a liquid variable instead)?
The next best option I can recommend is to put your Javascript into a separate .js file in the assets folder of your theme.liquid and include it in your theme like so, {{ "cookie-code.js" | asset_url | script_tag }}.
Once again, if the user can open dev tools, they could still read your cookie or look at your javascript file. Maybe clarify in more detail what exactly it is that you're trying to achieve?

Related

Loading javascript from server [duplicate]

We are currently working in a private beta and so are still in the process of making fairly rapid changes, although obviously as usage is starting to ramp up, we will be slowing down this process. That being said, one issue we are running into is that after we push out an update with new JavaScript files, the client browsers still use the cached version of the file and they do not see the update. Obviously, on a support call, we can simply inform them to do a ctrlF5 refresh to ensure that they get the up-to-date files from the server, but it would be preferable to handle this before that time.
Our current thought is to simply attach a version number onto the name of the JavaScript files and then when changes are made, increment the version on the script and update all references. This definitely gets the job done, but updating the references on each release could get cumbersome.
As I'm sure we're not the first ones to deal with this, I figured I would throw it out to the community. How are you ensuring clients update their cache when you update your code? If you're using the method described above, are you using a process that simplifies the change?
As far as I know a common solution is to add a ?<version> to the script's src link.
For instance:
<script type="text/javascript" src="myfile.js?1500"></script>
I assume at this point that there isn't a better way than find-replace to increment these "version numbers" in all of the script tags?
You might have a version control system do that for you? Most version control systems have a way to automatically inject the revision number on check-in for instance.
It would look something like this:
<script type="text/javascript" src="myfile.js?$$REVISION$$"></script>
Of course, there are always better solutions like this one.
Appending the current time to the URL is indeed a common solution. However, you can also manage this at the web server level, if you want to. The server can be configured to send different HTTP headers for javascript files.
For example, to force the file to be cached for no longer than 1 day, you would send:
Cache-Control: max-age=86400, must-revalidate
For beta, if you want to force the user to always get the latest, you would use:
Cache-Control: no-cache, must-revalidate
Google Page-Speed: Don't include a query string in the URL for static resources.
Most proxies, most notably Squid up through version 3.0, do not cache resources with a "?" in their URL even if a Cache-control: public header is present in the response. To enable proxy caching for these resources, remove query strings from references to static resources, and instead encode the parameters into the file names themselves.
In this case, you can include the version into URL ex: http://abc.com/v1.2/script.js and use apache mod_rewrite to redirect the link to http://abc.com/script.js. When you change the version, client browser will update the new file.
How about adding the filesize as a load parameter?
<script type='text/javascript' src='path/to/file/mylibrary.js?filever=<?=filesize('path/to/file/mylibrary.js')?>'></script>
So every time you update the file the "filever" parameter changes.
How about when you update the file and your update results in the same file size? what are the odds?
This usage has been deprected:
https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache
This answer is only 6 years late, but I don't see this answer in many places... HTML5 has introduced Application Cache which is used to solve this problem. I was finding that new server code I was writing was crashing old javascript stored in people's browsers, so I wanted to find a way to expire their javascript. Use a manifest file that looks like this:
CACHE MANIFEST
# Aug 14, 2014
/mycode.js
NETWORK:
*
and generate this file with a new time stamp every time you want users to update their cache. As a side note, if you add this, the browser will not reload (even when a user refreshes the page) until the manifest tells it to.
Not all browsers cache files with '?' in it. What I did to make sure it was cached as much as possible, I included the version in the filename.
So instead of stuff.js?123, I did stuff_123.js
I used mod_redirect(I think) in apache to to have stuff_*.js to go stuff.js
The common practice nowadays is to generate a content hash code as part of the file name to force the browser especially IE to reload the javascript files or css files.
For example,
vendor.a7561fb0e9a071baadb9.js
main.b746e3eb72875af2caa9.js
It is generally the job for the build tools such as webpack. Here is more details if anyone wants to try out if you are using webpack.
For ASP.NET pages I am using the following
BEFORE
<script src="/Scripts/pages/common.js" type="text/javascript"></script>
AFTER (force reload)
<script src="/Scripts/pages/common.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>
Adding the DateTime.Now.Ticks works very well.
For ASP.NET I suppose next solution with advanced options (debug/release mode, versions):
Js or Css files included by such way:
<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" />
<link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />
Global.JsPostfix and Global.CssPostfix is calculated by the following way in Global.asax:
protected void Application_Start(object sender, EventArgs e)
{
...
string jsVersion = ConfigurationManager.AppSettings["JsVersion"];
bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]);
int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
JsPostfix = "";
#if !DEBUG
JsPostfix += ".min";
#endif
JsPostfix += ".js?" + jsVersion + "_" + buildNumber;
if (updateEveryAppStart)
{
Random rand = new Random();
JsPosfix += "_" + rand.Next();
}
...
}
If you're generating the page that links to the JS files a simple solution is appending the file's last modification timestamp to the generated links.
This is very similar to Huppie's answer, but works in version control systems without keyword substitution. It's also better than append the current time, since that would prevent caching even when the file didn't change at all.
In PHP:
function latest_version($file_name){
echo $file_name."?".filemtime($_SERVER['DOCUMENT_ROOT'] .$file_name);
}
In HTML:
<script type="text/javascript" src="<?php latest_version('/a-o/javascript/almanacka.js'); ?>">< /script>
How it works:
In HTML, write the filepath and name as you wold do, but in the function only.
PHP gets the filetime of the file and returns the filepath+name+"?"+time of latest change
We have been creating a SaaS for users and providing them a script to attach in their website page, and it was not possible to attach a version with the script as user will attach the script to their website for functionalities and i can't force them to change the version each time we update the script
So, we found a way to load the newer version of the script each time user calls the original script
the script link provided to user
<script src="https://thesaasdomain.com/somejsfile.js" data-ut="user_token"></script>
the script file
if($('script[src^="https://thesaasdomain.com/somejsfile.js?"]').length !== 0) {
init();
} else {
loadScript("https://thesaasdomain.com/somejsfile.js?" + guid());
}
var loadscript = function(scriptURL) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = scriptURL;
head.appendChild(script);
}
var guid = function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
var init = function() {
// our main code
}
Explanation:
The user have attached the script provided to them in their website and we checked for the unique token attached with the script exists or not using jQuery selector and if not then load it dynamically with newer token (or version)
This is call the same script twice which could be a performance issue, but it really solves the problem of forcing the script to not load from the cache without putting the version in the actual script link given to the user or client
Disclaimer: Do not use if performance is a big issue in your case.
The jQuery function getScript can also be used to ensure that a js file is indeed loaded every time the page is loaded.
This is how I did it:
$(document).ready(function(){
$.getScript("../data/playlist.js", function(data, textStatus, jqxhr){
startProgram();
});
});
Check the function at http://api.jquery.com/jQuery.getScript/
By default, $.getScript() sets the cache setting to false. This appends a timestamped query parameter to the request URL to ensure that the browser downloads the script each time it is requested.
My colleague just found a reference to that method right after I posted (in reference to css) at http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/. Good to see that others are using it and it seems to work. I assume at this point that there isn't a better way than find-replace to increment these "version numbers" in all of the script tags?
In asp.net mvc you can use #DateTime.UtcNow.ToString() for js file version number. Version number auto change with date and you force clients browser to refresh automatically js file. I using this method and this is work well.
<script src="~/JsFilePath/JsFile.js?v=#DateTime.UtcNow.ToString()"></script>
One solution is to append a query string with a timestamp in it to the URL when fetching the resource. This takes advantage of the fact that a browser will not cache resources fetched from URLs with query strings in them.
You probably don't want the browser not to cache these resources at all though; it's more likely that you want them cached, but you want the browser to fetch a new version of the file when it is made available.
The most common solution seems to be to embed a timestamp or revision number in the file name itself. This is a little more work, because your code needs to be modified to request the correct files, but it means that, e.g. version 7 of your snazzy_javascript_file.js (i.e. snazzy_javascript_file_7.js) is cached on the browser until you release version 8, and then your code changes to fetch snazzy_javascript_file_8.js instead.
The advantage of using a file.js?V=1 over a fileV1.js is that you do not need to store multiple versions of the JavaScript files on the server.
The trouble I see with file.js?V=1 is that you may have dependant code in another JavaScript file that breaks when using the new version of the library utilities.
For the sake of backwards compatibility, I think it is much better to use jQuery.1.3.js for your new pages and let existing pages use jQuery.1.1.js, until you are ready to upgrade the older pages, if necessary.
Use a version GET variable to prevent browser caching.
Appending ?v=AUTO_INCREMENT_VERSION to the end of your url prevents browser caching - avoiding any and all cached scripts.
Cache Busting in ASP.NET Core via a tag helper will handle this for you and allow your browser to keep cached scripts/css until the file changes. Simply add the tag helper asp-append-version="true" to your script (js) or link (css) tag:
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/>
Dave Paquette has a good example and explanation of cache busting here (bottom of page) Cache Busting
location.reload(true);
see https://www.w3schools.com/jsref/met_loc_reload.asp
I dynamically call this line of code in order to ensure that javascript has been re-retrieved from the web server instead of from the browser's cache in order to escape this problem.
Athough it is framework specific, Django 1.4 has the staticfiles app functionality which works in a similar fashion to the 'greenfelt' site in the above answer
One simple way.
Edit htaccess
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} \.(jpe?g|bmp|png|gif|css|js|mp3|ogg)$ [NC]
RewriteCond %{QUERY_STRING} !^(.+?&v33|)v=33[^&]*(?:&(.*)|)$ [NC]
RewriteRule ^ %{REQUEST_URI}?v=33 [R=301,L]
You can add file version to your file name so it will be like:
https://www.example.com/script_fv25.js
fv25 => file version nr. 25
And in your .htaccess put this block which will delete the version part from link:
RewriteEngine On
RewriteRule (.*)_fv\d+\.(js|css|txt|jpe?g|png|svg|ico|gif) $1.$2 [L]
so the final link will be:
https://www.example.com/script.js
FRONT-END OPTION
I made this code specifically for those who can't change any settings on the backend. In this case the best way to prevent a very long cache is with:
new Date().getTime()
However, for most programmers the cache can be a few minutes or hours so the simple code above ends up forcing all users to download "the each page browsed". To specify how long this item will remain without reloading I made this code and left several examples below:
// cache-expires-after.js v1
function cacheExpiresAfter(delay = 1, prefix = '', suffix = '') { // seconds
let now = new Date().getTime().toString();
now = now.substring(now.length - 11, 10); // remove decades and milliseconds
now = parseInt(now / delay).toString();
return prefix + now + suffix;
};
// examples (of the delay argument):
// the value changes every 1 second
var cache = cacheExpiresAfter(1);
// see the sync
setInterval(function(){
console.log(cacheExpiresAfter(1), new Date().getSeconds() + 's');
}, 1000);
// the value changes every 1 minute
var cache = cacheExpiresAfter(60);
// see the sync
setInterval(function(){
console.log(cacheExpiresAfter(60), new Date().getMinutes() + 'm:' + new Date().getSeconds() + 's');
}, 1000);
// the value changes every 5 minutes
var cache = cacheExpiresAfter(60 * 5); // OR 300
// the value changes every 1 hour
var cache = cacheExpiresAfter(60 * 60); // OR 3600
// the value changes every 3 hours
var cache = cacheExpiresAfter(60 * 60 * 3); // OR 10800
// the value changes every 1 day
var cache = cacheExpiresAfter(60 * 60 * 24); // OR 86400
// usage example:
let head = document.head || document.getElementsByTagName('head')[0];
let script = document.createElement('script');
script.setAttribute('src', '//unpkg.com/sweetalert#2.1.2/dist/sweetalert.min.js' + cacheExpiresAfter(60 * 5, '?'));
head.append(script);
// this works?
let waitSwal = setInterval(function() {
if (window.swal) {
clearInterval(waitSwal);
swal('Script successfully injected', script.outerHTML);
};
}, 100);
Simplest solution? Don't let the browser cache at all. Append the current time (in ms) as a query.
(You are still in beta, so you could make a reasonable case for not optimizing for performance. But YMMV here.)
Below worked for me:
<head>
<meta charset="UTF-8">
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0" />
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
</head>
If you are using PHP and Javascript then the following should work for you especially in the situation where you are doing multiple times changes on the file. So, every time you cannot change its version. So, the idea is to create a random number in PHP and then assign it as a version of the JS file.
$fileVersion = rand();
<script src="addNewStudent.js?v=<?php echo $fileVersion; ?>"></script>
<script>
var version = new Date().getTime();
var script = document.createElement("script");
script.src = "app.js?=" + version;
document.body.appendChild(script);
</script>
Feel free to delete this if someone's already posted it somewhere in the plethora of answers above.
You can do this with .htaccess
Add into your .htaccess file the following lines:
# DISABLE CACHING
<IfModule mod_headers.c>
<FilesMatch "\.js$">
Header set Cache-Control "no-store, max-age=0"
</FilesMatch>
</IfModule>
A simple trick that works fine for me to prevent conflicts between older and newer javascript files. That means: If there is a conflict and some error occurs, the user will be prompted to press Ctrl-F5.
At the top of the page add something like
<h1 id="welcome"> Welcome to this page <span style="color:red">... press Ctrl-F5</span></h1>
looking like
Let this line of javascript be the last to be executed when loading the page:
document.getElementById("welcome").innerHTML = "Welcome to this page"
In case that no error occurs the welcome greeting above will hardly be visible and almost immediately be replaced by

Django/JS - Send file to users, as known as download functionality

I want to let users to download a specific file, by clicking on a button "Download". The button will be linked with many switchers, so I wrote a JS script that change the "href" tag to point to the correct static file.
I tried to follow many stackoverflow questions and read documentation about Django staticfiles, media files but did not understand what I need to do on my case. Any help would be really appreciated, let me please introduce what I did and ask for your help/opinion.
I want to let people download files that can be found in :
"/home/user/xxxx/xxx/project/my_app/static/"
Here is my function in views.py :
def send_file(request,file_name):
from django.contrib.staticfiles.storage import staticfiles_storage
import os
from wsgiref.util import FileWrapper
import mimetypes
filename = staticfiles_storage.url(file_name)
download_name = file_name
wrapper = FileWrapper(open(filename))
content_type = mimetypes.guess_type(filename)[0]
response = HttpResponse(wrapper, content_type=content_type)
response['Content-Length'] = os.path.getsize(filename)
response['Content-Disposition'] = "attachment; filename=%s" % download_name
return response
I need the exact path to open the file, so what I have done is that I defined on my settings STATIC_URL = "/home/user/xxxx/xxx/project/my_app/static/"
. I do not like this solution, because after it, if you check my source, you have the exact path of my project. If I defined STATIC_URL = "static/" it does not work. I looked for a way to get exact path for the static file but it did not work. Any help for this part ?
urls.py:
url(r'^download/static/(?P<file_name>[\w.]{0,256})$',views.send_file, name='send_file'),
template.html, only the button part :
Download
JS, only the part that when you click on a switcher, it changes the href tag of the HTML button :
"if you click on a switcher"
id = switcher-checked
var atag = document.getElementById("dl-link");
var url = "http://localhost:8000/test/download/static/"+id+".csv";
atag.setAttribute("href",url);
Is there a solution to use the {% url 'my_app:send_file %} tag in my JS ? I found that one solution is to put the script directly within "template.html", is it a good behaviour ?
My downloading is working perfectly, but I feel like all my choices are pretty bad (STATIC_URL and JS var url definition). I know that my question is quite dense, but I really need this help. Any examples would be more than appreciated. Thank you.
Couple of points. first one for STATIC_URL you can use "/static/" with starting and ending with slash instead of complete path. since you are trying download from same domain name no need to use complete URL "http://localhost:8000/your-url". You can simply use "/your-url" in js var url variable.
Django cannot render js files, so we have only one option, keeping it in template.html. For better maintaining of js code, try declaring global variable with urls in the template on document load and use them in your script. So that script part will be clear. for ex,
var all_my_urls = {
"url":"{% url 'my_app:send_file'%}"
}

Cookie set with javascript, not recognised with PHP (same domain and path)

These are my cookies:
My cookies
I'm running my website from my own computer using a WAMP server. I access my main page from http://127.0.0.1/Zulaijen/, and this is the javascript funcion to set the cookies (User and Session):
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "; expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + expires;
}
When I read them using javascript, it works fine. I get my session. Then I go to another PHP page named 'uploader.php' with this code:
if(!isset($_COOKIE['TestCookie']))
setcookie("TestCookie", "Hello World!", time()+3600);
print_r($_COOKIE);
echo("Session: " . $_COOKIE['Session'] . "<br/>User: " . $_COOKIE['User'] . "<br/>");
And the result is:
Array ( [TestCookie] => Hello World! )
Notice: Undefined index: Session in D:\wamp\www\Zulaijen\uploader.php
on line 30
Notice: Undefined index: User in D:\wamp\www\Zulaijen\uploader.php on line 30
Which means my PHP code is not reading the cookies I set with javascript. It only reads the one I set with my PHP code (TestCookie). And I don't understand why. They are within the same domain and the same path.
You should try setting cookie path. Could be that the cookie paths for PHP and JavaScript isn't matching, hence the cookie will not be shared between the two.
JavaScript cookie path:
How do I set path while saving a cookie value in JavaScript?
PHP coookie path (see path section):
http://php.net/manual/en/function.setcookie.php
I finally found out what was causing the problem (by accident). It's very confusing, but it has a very simple solution.
In order to read the cookies from PHP, you must read them from the very beginning of the file.
Doing this:
<?php print_r($_COOKIE); ?>
At the very beginning of the file (before any HTML code) prints every cookie I set correctly as it should. Even if you set them from PHP, if you don't do it from the very beginning of the file you won't be able to get them.
The reason why I was able to read the one I was setting with PHP was simply because I was setting it right before reading it, or so it seems.

Web page doesn't reflect code changes [duplicate]

How do I clear a browsers cache with JavaScript?
We deployed the latest JavaScript code but we are unable to get the latest JavaScript code.
Editorial Note: This question is semi-duplicated in the following places, and the answer in the first of the following questions is probably the best. This accepted answer is no longer the ideal solution.
How to force browser to reload cached CSS/JS files?
How can I force clients to refresh JavaScript files?
Dynamically reload local Javascript source / json data
Update: See location.reload() has no parameter for background on this nonstandard parameter and how Firefox is likely the only modern browser with support.
You can call window.location.reload(true) to reload the current page. It will ignore any cached items and retrieve new copies of the page, css, images, JavaScript, etc from the server. This doesn't clear the whole cache, but has the effect of clearing the cache for the page you are on.
However, your best strategy is to version the path or filename as mentioned in various other answers. In addition, see Revving Filenames: don’t use querystring for reasons not to use ?v=n as your versioning scheme.
You can't clear the cache with javascript.
A common way is to append the revision number or last updated timestamp to the file, like this:
myscript.123.js
or
myscript.js?updated=1234567890
Try changing the JavaScript file's src? From this:
<script language="JavaScript" src="js/myscript.js"></script>
To this:
<script language="JavaScript" src="js/myscript.js?n=1"></script>
This method should force your browser to load a new copy of the JS file.
Other than caching every hour, or every week, you may cache according to file data.
Example (in PHP):
<script src="js/my_script.js?v=<?=md5_file('js/my_script.js')?>"></script>
or even use file modification time:
<script src="js/my_script.js?v=<?=filemtime('js/my_script.js')?>"></script>
You can also force the code to be reloaded every hour, like this, in PHP :
<?php
echo '<script language="JavaScript" src="js/myscript.js?token='.date('YmdH').'">';
?>
or
<script type="text/javascript" src="js/myscript.js?v=<?php echo date('YmdHis'); ?>"></script>
window.location.reload(true) seems to have been deprecated by the HTML5 standard. One way to do this without using query strings is to use the Clear-Site-Data header, which seems to being standardized.
put this at the end of your template :
var scripts = document.getElementsByTagName('script');
var torefreshs = ['myscript.js', 'myscript2.js'] ; // list of js to be refresh
var key = 1; // change this key every time you want force a refresh
for(var i=0;i<scripts.length;i++){
for(var j=0;j<torefreshs.length;j++){
if(scripts[i].src && (scripts[i].src.indexOf(torefreshs[j]) > -1)){
new_src = scripts[i].src.replace(torefreshs[j],torefreshs[j] + 'k=' + key );
scripts[i].src = new_src; // change src in order to refresh js
}
}
}
try using this
<script language="JavaScript" src="js/myscript.js"></script>
To this:
<script language="JavaScript" src="js/myscript.js?n=1"></script>
Here's a snippet of what I'm using for my latest project.
From the controller:
if ( IS_DEV ) {
$this->view->cacheBust = microtime(true);
} else {
$this->view->cacheBust = file_exists($versionFile)
// The version file exists, encode it
? urlencode( file_get_contents($versionFile) )
// Use today's year and week number to still have caching and busting
: date("YW");
}
From the view:
<script type="text/javascript" src="/javascript/somefile.js?v=<?= $this->cacheBust; ?>"></script>
<link rel="stylesheet" type="text/css" href="/css/layout.css?v=<?= $this->cacheBust; ?>">
Our publishing process generates a file with the revision number of the current build. This works by URL encoding that file and using that as a cache buster. As a fail-over, if that file doesn't exist, the year and week number are used so that caching still works, and it will be refreshed at least once a week.
Also, this provides cache busting for every page load while in the development environment so that developers don't have to worry with clearing the cache for any resources (javascript, css, ajax calls, etc).
or you can just read js file by server with file_get_contets and then put in echo in the header the js contents
Maybe "clearing cache" is not as easy as it should be. Instead of clearing cache on my browsers, I realized that "touching" the file will actually change the date of the source file cached on the server (Tested on Edge, Chrome and Firefox) and most browsers will automatically download the most current fresh copy of whats on your server (code, graphics any multimedia too). I suggest you just copy the most current scripts on the server and "do the touch thing" solution before your program runs, so it will change the date of all your problem files to a most current date and time, then it downloads a fresh copy to your browser:
<?php
touch('/www/control/file1.js');
touch('/www/control/file2.js');
touch('/www/control/file2.js');
?>
...the rest of your program...
It took me some time to resolve this issue (as many browsers act differently to different commands, but they all check time of files and compare to your downloaded copy in your browser, if different date and time, will do the refresh), If you can't go the supposed right way, there is always another usable and better solution to it. Best Regards and happy camping.
I had some troubles with the code suggested by yboussard. The inner j loop didn't work. Here is the modified code that I use with success.
function reloadScripts(toRefreshList/* list of js to be refresh */, key /* change this key every time you want force a refresh */) {
var scripts = document.getElementsByTagName('script');
for(var i = 0; i < scripts.length; i++) {
var aScript = scripts[i];
for(var j = 0; j < toRefreshList.length; j++) {
var toRefresh = toRefreshList[j];
if(aScript.src && (aScript.src.indexOf(toRefresh) > -1)) {
new_src = aScript.src.replace(toRefresh, toRefresh + '?k=' + key);
// console.log('Force refresh on cached script files. From: ' + aScript.src + ' to ' + new_src)
aScript.src = new_src;
}
}
}
}
If you are using php can do:
<script src="js/myscript.js?rev=<?php echo time();?>"
type="text/javascript"></script>
Please do not give incorrect information.
Cache api is a diferent type of cache from http cache
HTTP cache is fired when the server sends the correct headers, you can't access with javasvipt.
Cache api in the other hand is fired when you want, it is usefull when working with service worker so you can intersect request and answer it from this type of cache
see:ilustration 1 ilustration 2 course
You could use these techiques to have always a fresh content on your users:
Use location.reload(true) this does not work for me, so I wouldn't recomend it.
Use Cache api in order to save into the cache and intersect the
request with service worker, be carefull with this one because
if the server has sent the cache headers for the files you want
to refresh, the browser will answer from the HTTP cache first, and if it does not find it, then it will go to the network, so you could end up with and old file
Change the url from you stactics files, my recomendation is you should name it with the change of your files content, I use md5 and then convert it to string and url friendly, and the md5 will change with the content of the file, there you can freely send HTTP cache headers long enough
I would recomend the third one see
You can also disable browser caching with meta HTML tags just put html tags in the head section to avoid the web page to be cached while you are coding/testing and when you are done you can remove the meta tags.
(in the head section)
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0"/>
Refresh your page after pasting this in the head and should refresh the new javascript code too.
This link will give you other options if you need them
http://cristian.sulea.net/blog/disable-browser-caching-with-meta-html-tags/
or you can just create a button like so
<button type="button" onclick="location.reload(true)">Refresh</button>
it refreshes and avoid caching but it will be there on your page till you finish testing, then you can take it off. Fist option is best I thing.
I tend to version my framework then apply the version number to script and style paths
<cfset fw.version = '001' />
<script src="/scripts/#fw.version#/foo.js"/>
Cache.delete() can be used for new chrome, firefox and opera.
I found a solution to this problem recently. In my case, I was trying to update an html element using javascript; I had been using XHR to update text based on data retrieved from a GET request. Although the XHR request happened frequently, the cached HTML data remained frustratingly the same.
Recently, I discovered a cache busting method in the fetch api. The fetch api replaces XHR, and it is super simple to use. Here's an example:
async function updateHTMLElement(t) {
let res = await fetch(url, {cache: "no-store"});
if(res.ok){
let myTxt = await res.text();
document.getElementById('myElement').innerHTML = myTxt;
}
}
Notice that {cache: "no-store"} argument? This causes the browser to bust the cache for that element, so that new data gets loaded properly. My goodness, this was a godsend for me. I hope this is helpful for you, too.
Tangentially, to bust the cache for an image that gets updated on the server side, but keeps the same src attribute, the simplest and oldest method is to simply use Date.now(), and append that number as a url variable to the src attribute for that image. This works reliably for images, but not for HTML elements. But between these two techniques, you can update any info you need to now :-)
Most of the right answers are already mentioned in this topic. However I want to add link to the one article which is the best one I was able to read.
https://www.fastly.com/blog/clearing-cache-browser
As far as I can see the most suitable solution is:
POST in an iframe. Next is a small subtract from the suggested post:
=============
const ifr = document.createElement('iframe');
ifr.name = ifr.id = 'ifr_'+Date.now();
document.body.appendChild(ifr);
const form = document.createElement('form');
form.method = "POST";
form.target = ifr.name;
form.action = ‘/thing/stuck/in/cache’;
document.body.appendChild(form);
form.submit();
There’s a few obvious side effects: this will create a browser history entry, and is subject to the same issues of non-caching of the response. But it escapes the preflight requirements that exist for fetch, and since it’s a navigation, browsers that split caches will be clearing the right one.
This one almost nails it. Firefox will hold on to the stuck object for cross-origin resources but only for subsequent fetches. Every browser will invalidate the navigation cache for the object, both for same and cross origin resources.
==============================
We tried many things but that one works pretty well. The only issue is there you need to be able to bring this script somehow to end user page so you are able to reset cache. We were lucky in our particular case.
window.parent.caches.delete("call")
close and open the browser after executing the code in console.
Cause browser cache same link, you should add a random number end of the url.
new Date().getTime() generate a different number.
Just add new Date().getTime() end of link as like
call
'https://stackoverflow.com/questions.php?' + new Date().getTime()
Output: https://stackoverflow.com/questions.php?1571737901173
I've solved this issue by using
ETag
Etags are similar to fingerprints, and if the resource at a given URL changes, a new Etag value must be generated. A comparison of them can determine whether two representations of a resource are the same.
Ref: https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete
Cache.delete()
Method
Syntax:
cache.delete(request, {options}).then(function(found) {
// your cache entry has been deleted if found
});

Clear the cache in JavaScript

How do I clear a browsers cache with JavaScript?
We deployed the latest JavaScript code but we are unable to get the latest JavaScript code.
Editorial Note: This question is semi-duplicated in the following places, and the answer in the first of the following questions is probably the best. This accepted answer is no longer the ideal solution.
How to force browser to reload cached CSS/JS files?
How can I force clients to refresh JavaScript files?
Dynamically reload local Javascript source / json data
Update: See location.reload() has no parameter for background on this nonstandard parameter and how Firefox is likely the only modern browser with support.
You can call window.location.reload(true) to reload the current page. It will ignore any cached items and retrieve new copies of the page, css, images, JavaScript, etc from the server. This doesn't clear the whole cache, but has the effect of clearing the cache for the page you are on.
However, your best strategy is to version the path or filename as mentioned in various other answers. In addition, see Revving Filenames: don’t use querystring for reasons not to use ?v=n as your versioning scheme.
You can't clear the cache with javascript.
A common way is to append the revision number or last updated timestamp to the file, like this:
myscript.123.js
or
myscript.js?updated=1234567890
Try changing the JavaScript file's src? From this:
<script language="JavaScript" src="js/myscript.js"></script>
To this:
<script language="JavaScript" src="js/myscript.js?n=1"></script>
This method should force your browser to load a new copy of the JS file.
Other than caching every hour, or every week, you may cache according to file data.
Example (in PHP):
<script src="js/my_script.js?v=<?=md5_file('js/my_script.js')?>"></script>
or even use file modification time:
<script src="js/my_script.js?v=<?=filemtime('js/my_script.js')?>"></script>
You can also force the code to be reloaded every hour, like this, in PHP :
<?php
echo '<script language="JavaScript" src="js/myscript.js?token='.date('YmdH').'">';
?>
or
<script type="text/javascript" src="js/myscript.js?v=<?php echo date('YmdHis'); ?>"></script>
window.location.reload(true) seems to have been deprecated by the HTML5 standard. One way to do this without using query strings is to use the Clear-Site-Data header, which seems to being standardized.
put this at the end of your template :
var scripts = document.getElementsByTagName('script');
var torefreshs = ['myscript.js', 'myscript2.js'] ; // list of js to be refresh
var key = 1; // change this key every time you want force a refresh
for(var i=0;i<scripts.length;i++){
for(var j=0;j<torefreshs.length;j++){
if(scripts[i].src && (scripts[i].src.indexOf(torefreshs[j]) > -1)){
new_src = scripts[i].src.replace(torefreshs[j],torefreshs[j] + 'k=' + key );
scripts[i].src = new_src; // change src in order to refresh js
}
}
}
try using this
<script language="JavaScript" src="js/myscript.js"></script>
To this:
<script language="JavaScript" src="js/myscript.js?n=1"></script>
Here's a snippet of what I'm using for my latest project.
From the controller:
if ( IS_DEV ) {
$this->view->cacheBust = microtime(true);
} else {
$this->view->cacheBust = file_exists($versionFile)
// The version file exists, encode it
? urlencode( file_get_contents($versionFile) )
// Use today's year and week number to still have caching and busting
: date("YW");
}
From the view:
<script type="text/javascript" src="/javascript/somefile.js?v=<?= $this->cacheBust; ?>"></script>
<link rel="stylesheet" type="text/css" href="/css/layout.css?v=<?= $this->cacheBust; ?>">
Our publishing process generates a file with the revision number of the current build. This works by URL encoding that file and using that as a cache buster. As a fail-over, if that file doesn't exist, the year and week number are used so that caching still works, and it will be refreshed at least once a week.
Also, this provides cache busting for every page load while in the development environment so that developers don't have to worry with clearing the cache for any resources (javascript, css, ajax calls, etc).
or you can just read js file by server with file_get_contets and then put in echo in the header the js contents
Maybe "clearing cache" is not as easy as it should be. Instead of clearing cache on my browsers, I realized that "touching" the file will actually change the date of the source file cached on the server (Tested on Edge, Chrome and Firefox) and most browsers will automatically download the most current fresh copy of whats on your server (code, graphics any multimedia too). I suggest you just copy the most current scripts on the server and "do the touch thing" solution before your program runs, so it will change the date of all your problem files to a most current date and time, then it downloads a fresh copy to your browser:
<?php
touch('/www/control/file1.js');
touch('/www/control/file2.js');
touch('/www/control/file2.js');
?>
...the rest of your program...
It took me some time to resolve this issue (as many browsers act differently to different commands, but they all check time of files and compare to your downloaded copy in your browser, if different date and time, will do the refresh), If you can't go the supposed right way, there is always another usable and better solution to it. Best Regards and happy camping.
I had some troubles with the code suggested by yboussard. The inner j loop didn't work. Here is the modified code that I use with success.
function reloadScripts(toRefreshList/* list of js to be refresh */, key /* change this key every time you want force a refresh */) {
var scripts = document.getElementsByTagName('script');
for(var i = 0; i < scripts.length; i++) {
var aScript = scripts[i];
for(var j = 0; j < toRefreshList.length; j++) {
var toRefresh = toRefreshList[j];
if(aScript.src && (aScript.src.indexOf(toRefresh) > -1)) {
new_src = aScript.src.replace(toRefresh, toRefresh + '?k=' + key);
// console.log('Force refresh on cached script files. From: ' + aScript.src + ' to ' + new_src)
aScript.src = new_src;
}
}
}
}
If you are using php can do:
<script src="js/myscript.js?rev=<?php echo time();?>"
type="text/javascript"></script>
Please do not give incorrect information.
Cache api is a diferent type of cache from http cache
HTTP cache is fired when the server sends the correct headers, you can't access with javasvipt.
Cache api in the other hand is fired when you want, it is usefull when working with service worker so you can intersect request and answer it from this type of cache
see:ilustration 1 ilustration 2 course
You could use these techiques to have always a fresh content on your users:
Use location.reload(true) this does not work for me, so I wouldn't recomend it.
Use Cache api in order to save into the cache and intersect the
request with service worker, be carefull with this one because
if the server has sent the cache headers for the files you want
to refresh, the browser will answer from the HTTP cache first, and if it does not find it, then it will go to the network, so you could end up with and old file
Change the url from you stactics files, my recomendation is you should name it with the change of your files content, I use md5 and then convert it to string and url friendly, and the md5 will change with the content of the file, there you can freely send HTTP cache headers long enough
I would recomend the third one see
You can also disable browser caching with meta HTML tags just put html tags in the head section to avoid the web page to be cached while you are coding/testing and when you are done you can remove the meta tags.
(in the head section)
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0"/>
Refresh your page after pasting this in the head and should refresh the new javascript code too.
This link will give you other options if you need them
http://cristian.sulea.net/blog/disable-browser-caching-with-meta-html-tags/
or you can just create a button like so
<button type="button" onclick="location.reload(true)">Refresh</button>
it refreshes and avoid caching but it will be there on your page till you finish testing, then you can take it off. Fist option is best I thing.
I tend to version my framework then apply the version number to script and style paths
<cfset fw.version = '001' />
<script src="/scripts/#fw.version#/foo.js"/>
Cache.delete() can be used for new chrome, firefox and opera.
I found a solution to this problem recently. In my case, I was trying to update an html element using javascript; I had been using XHR to update text based on data retrieved from a GET request. Although the XHR request happened frequently, the cached HTML data remained frustratingly the same.
Recently, I discovered a cache busting method in the fetch api. The fetch api replaces XHR, and it is super simple to use. Here's an example:
async function updateHTMLElement(t) {
let res = await fetch(url, {cache: "no-store"});
if(res.ok){
let myTxt = await res.text();
document.getElementById('myElement').innerHTML = myTxt;
}
}
Notice that {cache: "no-store"} argument? This causes the browser to bust the cache for that element, so that new data gets loaded properly. My goodness, this was a godsend for me. I hope this is helpful for you, too.
Tangentially, to bust the cache for an image that gets updated on the server side, but keeps the same src attribute, the simplest and oldest method is to simply use Date.now(), and append that number as a url variable to the src attribute for that image. This works reliably for images, but not for HTML elements. But between these two techniques, you can update any info you need to now :-)
Most of the right answers are already mentioned in this topic. However I want to add link to the one article which is the best one I was able to read.
https://www.fastly.com/blog/clearing-cache-browser
As far as I can see the most suitable solution is:
POST in an iframe. Next is a small subtract from the suggested post:
=============
const ifr = document.createElement('iframe');
ifr.name = ifr.id = 'ifr_'+Date.now();
document.body.appendChild(ifr);
const form = document.createElement('form');
form.method = "POST";
form.target = ifr.name;
form.action = ‘/thing/stuck/in/cache’;
document.body.appendChild(form);
form.submit();
There’s a few obvious side effects: this will create a browser history entry, and is subject to the same issues of non-caching of the response. But it escapes the preflight requirements that exist for fetch, and since it’s a navigation, browsers that split caches will be clearing the right one.
This one almost nails it. Firefox will hold on to the stuck object for cross-origin resources but only for subsequent fetches. Every browser will invalidate the navigation cache for the object, both for same and cross origin resources.
==============================
We tried many things but that one works pretty well. The only issue is there you need to be able to bring this script somehow to end user page so you are able to reset cache. We were lucky in our particular case.
window.parent.caches.delete("call")
close and open the browser after executing the code in console.
Cause browser cache same link, you should add a random number end of the url.
new Date().getTime() generate a different number.
Just add new Date().getTime() end of link as like
call
'https://stackoverflow.com/questions.php?' + new Date().getTime()
Output: https://stackoverflow.com/questions.php?1571737901173
I've solved this issue by using
ETag
Etags are similar to fingerprints, and if the resource at a given URL changes, a new Etag value must be generated. A comparison of them can determine whether two representations of a resource are the same.
Ref: https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete
Cache.delete()
Method
Syntax:
cache.delete(request, {options}).then(function(found) {
// your cache entry has been deleted if found
});

Categories

Resources