I've created a page that uses the CKEditor javascript rich edit control.
It's a pretty neat control, especially seeing as it's free, but I'm having serious issues with the way it allows you to add templates.
To add a template you need to modify the templates js file in the CKEditor templates folder. The documentation page describing it is here.
This works fine until I want to update a template or add a new one (or anything else that requires me to modify the js file).
Internet Explorer caches the js file and doesn't pick up the update. Emptying the cache allows the update to be picked up, but this isn't an acceptable solution. Whenever I update a template I do not want to tell all of the users across the organisation to empty their IE cache. There must be a better way!
Is there a way to stop IE caching the js file? Or is there another solution to this problem?
Update
Ok, I found this section in the CKEditor API that will allow me to use the "insert timestamp into the url" solution suggested by several people.
So the script now looks like this:
config.templates_files =
[
'/editor_templates/site_default.js?time=' + utcTimeMilliseconds
];
Thanks for your help guys.
You can add rand seed to your js file. I mean <script src='jsFile.js?seed=12345'
And every time you want to empty cache - change seed number
Update:
as I understood you have to write like this config.templates_files = [ '/mytemplates.js?seed=12345' ];
Youo can add a timestamp query parameter when you include your .js file..
so instead of <script type="text/javascript" src="somefile.js"></script> you can <script type="text/javascript" src="somefile.js?timestampgoeshere"></script>
this should make the file to always get reloaded (the timestamp needs to be dynamic and changing for each load of the page..)
I am afraid you'll have to hack into the FCKEditor code and force the client JavaScript to load fresh copy of the XML file. You can do so by appending a ?random=<a random number> to the URL of the XML file being requested. FCKEditor is opensource so you should be able to locate the lines the request the XML and modify accordingly.
Set Expires-Header accordingly, e.g. in Apache
ExpiresActive On
ExpiresByType text/javascript access
This is not recommended for a real web application, only for intranet scenarios because the files will not be cachable.
every time you load the js file, pass a variable of a random number as a variable.
src='/libs/js/myfile.js?4859487594573
same trick for ajax loaded files.
Multiple methods (don't need to do them all):
press ^F5 (control + F5) - that'll load without cache
set pragma/cache headers on sending
use a random variable in the GET query string
.NET / C# :
public static void DisallowBrowserCache( )
{
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(false);
}
You could make ASP.NET write a js file to the outputstream (http://server.com/jsFile.aspx, set http headers), and control the caching behavior of the response with the above method.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I force the refresh of javascript files in a browser?
My application in ASP.NET MVC based and javascript files are included in .csHtml file.
I require this so that the user do not have to do a [Ctrl+F5] or manually clear cache and the most recent version of javascript file is loaded everytime in the browser.
I appreciate if some examples can be provided.
Primary technique suggested is to use a dummy paramater while including the file.
Also I do not what to change the parameter manually every time I modify a js file. Need some examples if this can be done automatically.
EDIT 1:
Please provide solution to this with ASP.NET MVC prospective.
Put a version number in the filename for your JS files (like jQuery does). Then, whenever you rev the JS files, you bump the version and change the HTML files that include it.
The jQuery file naming example:
jquery-1.8.3.js
jquery-1.9.0.js
This lets you set very long caching on your server for the JS files themselves which really helps with performance on your site. But, any time you rev the JS files, the viewer gets the new JS files immediately because the newly named files are pulled by the new HTML file because they aren't in the browser cache.
You want to use Bundling and Minification. Depending on your version of MVC, the implementation is slightly different. In the newest version, it is used by default.
Bundling and Minification will combine and minify all your scripts (and styles sheets) into one file (or multiple, depending on how you use it) and serve them up with a unique parameter. Any time a file changes in that particular bundle (and thus the user would require to download the new files) the parameter automatically changes.
For MVC3, you'll need to install Microsoft Web Optimization.
Then in your global.ascx, you'd do something like this and call it from Application_Start:
private static void SetupBundling()
{
var jsBundle = new Bundle("~/Scripts/js", typeof(JsMinify));
jsBundle.AddDirectory("~/Scripts/", "*.js", false);
jsBundle.AddDirectory("~/Scripts/anothr-good-folder/", "*.js", false);
BundleTable.Bundles.Add(jsBundle);
var randomBundle = new Bundle("~/Scripts/random", typeof(JsMinify));
randomBundle.AddFile("~/Scripts/random/main.js");
randomBundle.AddFile("~/Scripts/random/cool.js");
BundleTable.Bundles.Add(randomBundle);
var cssBundle = new Bundle("~/Content/css", typeof(CssMinify));
cssBundle.AddDirectory("~/Content/", "*.css", false);
BundleTable.Bundles.Add(cssBundle);
}
So that first bundle will bundle every .js file in your ~/Scripts folder. In your head file you can reference it like:
<script src="#Microsoft.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")" type="text/javascript"></script>
And it will be rendered like:
<script src="/Scripts/js?v=-2573834892993289" type="text/javascript"></script>
And any time one of your .js files change (or .css), so will the parameter.
Similar implementation for the CSS bundle, and also if you want to reference the randomBundle only on certain pages.
You can do cache-busting by attaching a random hash or number URL parameter after each javascript file URL like so:
http://www.bestsiteonearth.yes/cool_javascript.js?cache_buster=2187sasas1289012890aohkjaiosa0990
Since that number is different each time the page is loaded the URL will not be cached. More info here. Tutorial gives PHP examples, but if you know how to create a hash or random number in any language & can attach it to a URL you are good to go.
Personally I use PHP, but the way I do this is to search the output buffer for static files, such as images, scripts and stylesheets (and audio, video, whatever), then retrieve their modification time from the filesystem and append it as /t=TIMESTAMP. I then use .htaccess to strip the timestamp off and get the original filename. This is preferred over query strings because many clients will not cache files with query strings, and it's also preferred over versioning because it updates automatically simply by modifying the file.
I've seen that a lot and I just don't know what it means. This, for example:
<script src="http://server.com/file.js?y=2345678" type="text/javascript"></script>
If it is in deed possible to 'catch' the value of 'y' in the javascript file, how would that be?
Thank you.
PS. I know what mod_rewrite is and that is not the answer, just in case :)
This is to force the browser not to cache the file, by making it believe that it is a dynamic file with get parameter rather than a static one.
This is often used to facilitate caching of the JS file. You set a far-future Expires header which means the browser may cache it for a very long time. If you change something in the file you also update the number in the querystring, which will make the browser refetch the file. This works because caching is for unique filenames and the querystring is part of the filename (as far as the browser is concerned).
A similar approach to this is to use rewrite rules in the web server to have some part of the file name which it doesnät care about. Here's a Nginx rule to show what I mean:
rewrite ^/style\..*\.css$ /style.css;
I use this rule to have filenames like style.42750cad6.css, which always points to the file style.css. The text in the middle is changed whenever I change style.css. The difference between the first approach is that this does not use the querystring so the caching will work in more browsers.
ok the way i see it in two ways.
it can be used to load js without caching
for every request to the server, the server might log information(if logging is enabled), if i am using it for analytics i can therefore use a different parameter for locations and from the log i can analyse and get required details.
I'm thinking of doing some online file manipulation for mobile users, the idea being that the user provides a URL to the file, then the file contents are modified by the JS, and can then be downloaded. But I haven't been able to figure out how to get the file when it's on a separate domain using just JS.
Is this possible? If so any hints or examples would be appreciated.
Just wanted to add that part of what I wanted to do was make it available without my hosting it. I'm thinking of something like a a file they can host somewhere,and then all of the bandwidth is their own...and that of wherever they are getting the file from of course.
The only way to load contents of a file on another domain is from within a <script> tag. This is how JSONP works. Look into getting your target file into this format.
The other way would be to use a local proxy. Create a web service method that loads and returns the contents of the file, then call that locally using your favorite JavaScript framework.
Depending on how you think of public webservices, and within some limitations I'm still mapping, you can do this using an ajax call to YQL, like so.
(will expand the answer later).
http://query.yahooapis.com/v1/public/yql?q=select%20%2a%20from%20data.uri%20where%20url=%22http://t3.gstatic.com/images?q=tbn:ANd9GcSyART8OudfFJQ5oBplmhZ6HIIlougzPgwQ9qcgknK8_tivdW0EOg%22
One of the limitations of this method is file size, it currently tops out at 25k.
I'm making an application that draws a lot of widgets and tiles on a canvas. The core UI will be defined by a long string of characters and drawn at page load by javascript. Since that core UI is big, >250K, and never changes, whats a good way to cache that?
I know I COULD just stick it in a variable at the top of the file, but is there a more efficient way? Like if wrote:
var img = new Image();
img.src = 'moose.png'
I assume that the browser will download and cache this image, so that on subsequent requests it won't have to hit my server again. But how do I do that with a chunk of text?
EDIT: basically I'm looking for an alternative to this:
var myUI = "AAAABBBCBVBVNCNDGAGAGABVBVB.... etc. for about 20 pages";
You can create a JavaScript file that contains the string of text.
var text='.....';
Then you can just include the script:
<script src="/ui.initialization.js" type="text/javascript"></script>
Followed by whatever other javascript you use to render the UI. The browser will cache the js file.
EDIT
I'm assuming you're opposed to having the long string of text inline. By moving it to a separate file, you allow the browser to cache it (if it's truly static and your server is configured with proper cache-control for static resources).
Here's some information for tweaking caching on Apache (I'm assuming you're running PHP on Apache).
Most static resources are cache-able by a browser. Just put your data in a .txt, .dat, .xml or whatever (even a .js) and load it with your javascript via AJAX.
time to download 250K over anything above 1Mbps thruput is < 1 second .. this is an issue for you?
And the very file you are downloading that contains that javascript with 250K baggage is going to be cached itself, probably.
You can use google gears or the new HTML 5 data storage features, supported by FF 3.5 and others.
Use Google page speed or YSlow to figure out what other (HTTP) improvments you can do.
I'm researching this for a project and I'm wondering what other people are doing to prevent stale CSS and JavaScript files from being served with each new release. I don't want to append a timestamp or something similar which may prevent caching on every request.
I'm working with the Spring 2.5 MVC framework and I'm already using the google api's to serve prototype and scriptaculous. I'm also considering using Amazon S3 and the new Cloudfront offering to minimize network latency.
I add a parameter to the request with the revision number, something like:
<script type="text/javascript" src="/path/to/script.js?ver=456"></script>
The 'ver' parameter is updated automatically with each build (read from file, which the build updates). This makes sure the scripts are cached only for the current revision.
Like #eran-galperin, I use a parameter in the reference to the JS file, but I include a server-generated reference to the file's "last modified" date. #stein-g-strindhaug suggests this approach. It would look something like this:
<script type="text/javascript" src="/path/to/script.js?1347486578"></script>
The server ignores the parameter for the static file and the client may cache the script until the date code changes. If (and only if) you modify the JS file on the server, the date code will change automatically.
For instance, in PHP, my script to create this code looks like this:
function cachePreventCode($filename) {
if (!file_exists($filename))
return "";
$mtime = filemtime($filename);
return $mtime;
}
So then when your PHP file includes a reference to a CSS file, it might look like this:
<link rel="stylesheet" type="text/css" href="main.css?<?= cachePreventCode("main.css") ?>" />
... which will create ...
<link rel="stylesheet" type="text/css" href="main.css?1347489244" />
With regards to cached files, I have yet to run into any issues of bugs related to stale cached files by using the querystring method.
However, with regards to performance, and echoing Todd B's mention of revving by filename, please check out Steve Souders' work for more on the topic:
"Squid, a popular proxy, doesn’t cache resources with a querystring. This hurts performance when multiple users behind a proxy cache request the same file - rather than using the cached version everybody would have to send a request to the origin server."
"Proxy administrators can change the configuration to support caching resources with a querystring, when the caching headers indicate that is appropriate. But the default configuration is what web developers should expect to encounter most frequently."
http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/
Use a conditional get request with an If-Modified-Since header
This is actually a very hard issue, and something that you can spend a while engineering the correct solution for.
I would recommend publishing your files using a timestamp and/or version built into the url, so instead of:
/media/js/my.js you end up with:
/media/js/v12/my.js or something similar.
You can automate the versioning/timestamping with any tool.
This has the added benefit of NOT breaking the site as you roll out new versions, and lets you do real side-by-side testing (unlike a rewrite rule that just strips the version and sends back the newest file).
One thing to watch out for with JS or CSS is when you include dependent urls inside of them (background images, etc) you need to make sure the JS/CSS timestamp/version changes if a resource inside does (as well as rewrite them, but that is possible with a very simple regex and a resource manifest).
No matter what you do make sure not to toss a ?vblah on the end, as you are basically throwing caching out the window when you do that (which is unfortunate, as it is by far the easiest way to handle this)
If you get the "modified time" of the file as a timestamp it will be cached until the file is modified. Just use a helper function (or whatever it is called in other frameworks) to add script/css/image tags that get the timestamp from the file. On a unix like system (wich most survers are) you could simply touch the files to force the modified time to change if necessary.
Ruby on Rails uses this strategy in production mode (by default I beleave), and uses a normal timestamp in development mode (to be really sure something isn't cached).
If you use MAVEN, you can use this, ADD on you pom.xml:
<properties>
<maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format>
<timestamp>${maven.build.timestamp}</timestamp>
</properties>
With this you can acess ${timestamp} in your view.
Like this sample:
<script type="text/javascript" src="/js/myScript.js?t=${timestamp}"></script>
Based on Todd Berman's answer of incorporating a revision number into the URL (but not as a query string), a perhaps slightly more convenient approach would be to have the server transform the versioned URL into a canonical form. This could be done with symlinks, e.g.:
/media/js/v12/my.js => /media/js/my.js
or you could set up server-side URL rewrites to always transform paths of the form /media/js/v*/my.js to, say, /media/js/my.js.