caching JavaScript files - javascript

Which is the best method to make the browser use cached versions of js files (from the serverside)?

Have a look at Yahoo! tips: https://developer.yahoo.com/performance/rules.html#expires.
There are also tips by Google: https://developers.google.com/speed/docs/insights/LeverageBrowserCaching

or in the .htaccess file
AddOutputFilter DEFLATE css js
ExpiresActive On
ExpiresByType application/x-javascript A2592000

I just finished my weekend project cached-webpgr.js
which uses the localStorage / web storage to cache JavaScript files. This approach is very fast. My small test showed
Loading jQuery from CDN: Chrome 268ms, FireFox: 200ms
Loading jQuery from localStorage: Chrome 47ms, FireFox 14ms
The code to achieve that is tiny, you can check it out at my Github project https://github.com/webpgr/cached-webpgr.js
Here is a full example how to use it.
The complete library:
function _cacheScript(c,d,e){var a=new XMLHttpRequest;a.onreadystatechange=function(){4==a.readyState&&(200==a.status?localStorage.setItem(c,JSON.stringify({content:a.responseText,version:d})):console.warn("error loading "+e))};a.open("GET",e,!0);a.send()}function _loadScript(c,d,e,a){var b=document.createElement("script");b.readyState?b.onreadystatechange=function(){if("loaded"==b.readyState||"complete"==b.readyState)b.onreadystatechange=null,_cacheScript(d,e,c),a&&a()}:b.onload=function(){_cacheScript(d,e,c);a&&a()};b.setAttribute("src",c);document.getElementsByTagName("head")[0].appendChild(b)}function _injectScript(c,d,e,a){var b=document.createElement("script");b.type="text/javascript";c=JSON.parse(c);var f=document.createTextNode(c.content);b.appendChild(f);document.getElementsByTagName("head")[0].appendChild(b);c.version!=e&&localStorage.removeItem(d);a&&a()}function requireScript(c,d,e,a){var b=localStorage.getItem(c);null==b?_loadScript(e,c,d,a):_injectScript(b,c,d,a)};
Calling the library
requireScript('jquery', '1.11.2', 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function(){
requireScript('examplejs', '0.0.3', 'example.js');
});

From PHP:
function OutputJs($Content)
{
ob_start();
echo $Content;
$expires = DAY_IN_S; // 60 * 60 * 24 ... defined elsewhere
header("Content-type: x-javascript");
header('Content-Length: ' . ob_get_length());
header('Cache-Control: max-age='.$expires.', must-revalidate');
header('Pragma: public');
header('Expires: '. gmdate('D, d M Y H:i:s', time()+$expires).'GMT');
ob_end_flush();
return;
}
works for me.
As a developer you'll probably quickly run into the situation that you don't want files cached, in which case see Help with aggressive JavaScript caching

In your Apache .htaccess file:
#Create filter to match files you want to cache
<Files *.js>
Header add "Cache-Control" "max-age=604800"
</Files>
I wrote about it here also:
http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/

I am heavily tempted to close this as a duplicate; this question appears to be answered in many different ways all over the site:
will a script in html's script tag with extension php be cached?
When does browser automatically clear cache of external JavaScript file?
Help with aggressive JavaScript caching
How to control web page caching, across all browsers?
How can I make the browser see CSS and Javascript changes?

The best (and only) method is to set correct HTTP headers, specifically these ones: "Expires", "Last-Modified", and "Cache-Control". How to do it depends on the server software you use.
In Improving performance… look for "Optimization on server side" for general considerations and relevant links and for "Client-side cache" for the Apache-specific advice.
If you are a fan of nginx (or nginx in plain English) like I am, you can easily configure it too:
location /images {
...
expires 4h;
}
In the example above any file from /images/ will be cached on the client for 4 hours.
Now when you know right words to look for (HTTP headers "Expires", "Last-Modified", and "Cache-Control"), just peruse the documentation of the web server you use.

I have a simple system that is pure JavaScript. It checks for changes in a simple text file that is never cached. When you upload a new version this file is changed. Just put the following JS at the top of the page.
(function(url, storageName) {
var fromStorage = localStorage.getItem(storageName);
var fullUrl = url + "?rand=" + (Math.floor(Math.random() * 100000000));
getUrl(function(fromUrl) {
// first load
if (!fromStorage) {
localStorage.setItem(storageName, fromUrl);
return;
}
// old file
if (fromStorage === fromUrl) {
return;
}
// files updated
localStorage.setItem(storageName, fromUrl);
location.reload(true);
});
function getUrl(fn) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", fullUrl, true);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === XMLHttpRequest.DONE) {
if (xmlhttp.status === 200 || xmlhttp.status === 2) {
fn(xmlhttp.responseText);
}
else if (xmlhttp.status === 400) {
throw 'unable to load file for cache check ' + url;
}
else {
throw 'unable to load file for cache check ' + url;
}
}
};
}
;
})("version.txt", "version");
just replace the "version.txt" with your file that is always run and "version" with the name you want to use for your local storage.

Related

Run python file from JavaScript [duplicate]

What I want is run python script just click on the button in the html page and show the python code result on my page.
Because it's just a small project, so I don't want to be overkill learning Django or other web frames even though I know it will work.
I made some searches, ajax seems the right solution for me, but I don't know how to execute python code by ajax. I know I can get some string back via ajax using following code:
function loadXMLDoc()
{
var xmlhttp;
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","test1.txt",true);
xmlhttp.send();
}
Thanks in advance for anyone who can help.
To extend #Liongold's comment, The full workflow goes like this:
Overview of how this happens
The javascript code for a button click gets executed. This code is running on the client from a browser.
The AJAX request gets sent over the internet just like an HTTP request, which is interpreted by a web application running on the computer that will run the Python code.
The python code creates a response, and formats it for sending back to the client.
The javascript reads the response as plain text, and decides what it means and how to use it. JSON is a very popular format for exchanging data via AJAX
What you need to do
Either:
Learn a server-side python framework. Flask is lightweight and will probably do what you want. The largest obstacle I've found here is dealing with Cross-origin (CORS) problems. Get started at http://flask.pocoo.org/docs/0.10/quickstart/
OR
See if you can port the python script INTO the browser. Does the code need to be run on a specific computer ( the server ) or could it theoretically be converted into javascript and run within the webpage. If the language difference is your only problem, have a look at http://www.skulpt.org/
I ran into a similar problem, and after searching for several hours, this is how i solved it. Assuming that the html file and the python file are the same folder.
<script>
function runScript() {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.status === 200) {
alert('Successful .... ' + request.responseText);
} else {
alert('Something went wrong, status was ' + request.status);
}
}
};
request.open('POST', 'test.py', true);
request.send(null);
return false;
};
document.getElementById('script-button').onclick = runScript;
</script>
This goes to your html file
-----------------------------
<button type="button" id="script-button">
add this line at the top of your python file
---------------------------------------------
test.py
------------
#!C:\Python34\python.exe -u
print("Testing 123")
add this directive to httpd.conf (Apache)
-----------------------------------------
# "C:/xampp/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "C:/xampp/<path to your project on the web server>">
AllowOverride All
Options Indexes FollowSymLinks Includes ExecCGI
AddHandler cgi-script .py .pyc
Order allow,deny
Allow from all
Require all granted
</Directory>

reading a text file line by line only with javascript

I don't want solution using Node.js, FileReader, or whatever else exept javascript!
Developing the html page, I encountered a problem as follows:
I get accurate results with this procedure, unfortunately the procedure remembers result of the first login page. Whatever text file in the meantime change the content, the procedure returns the first result.
Can someone give advice!
var filePath = "../../dir/sub dir/text_file.txt";
function getBackData(filePath){
var axd, i, artx, txli, tdr;
if(window.XMLHttpRequest){
axd = new XMLHttpRequest();
}else{
axd = new ActiveXObject("Microsoft.XMLHTTP");
}
axd.open('GET', filePath, true);
axd.onreadystatechange = function(){
if(axd.readyState == 4 && axd.status == 200){
artx = axd.responseText;
txli = artx.split("\n");
for(i = 0; i < txli.length; i++){
alert(txli[i]);
}
}
}
axd.send(null);
}
You could try :axd setRequestHeader('Cache-Control', 'no-cache');
Or try: axd.open('GET', filePath+'?_=' + new Date().getTime()), true); This will prevent your server from using the cash, because each request is different.
This is probably because the browser cache it. If you send a parameter which is almost always different like timestamp, you can disable the cache. Or you can try to use POST, since post request are never cached.
You are not allowed to request local files directly with ajax - you need a server to serve them. The browser is sandboxed and cannot generally open local files. This is a security measure - imagine what would happen if any website was allowed to open your files!
There are ways to set up a simple server for your images, like http-server. This allows you to serve files directly off a chosen directory, like so:
npm install -g http-server
http-server path-to-text-files/
Then you can request the files normally with ajax, at a path relative to the one your server is serving, like so:
url = "/dir/subdir/text-file.txt";
...
ajax.open('GET', url, true);
...
ajax.send(null);

Why is this a Cross Domain Request and how to solve it? [duplicate]

I'm currently working through the book "Head first HTML5 programming". I want to load the content of a file named sales.json from a web server on my own machine. I used wampserver for this.
In the folder wamp/www/gumball/ I put all relevant .html, .js and .css files, and also the sales.json file.
My JavaScript code is very simple:
window.onload = function() {
var url = "http://localhost/gumball/sales.json";
var request = new XMLHttpRequest();
request.open("GET", url);
request.onload = function() {
if (request.status == 200) {
updateSales(request.responseText);
}
};
request.send(null);
}
function updateSales(responseText) {
var salesDiv = document.getElementById("sales");
salesDiv.innerHTML = responseText;
}
This doesn't do anything! Typing the link: http://localhost/gumball/sales.json in my browser opens the right file, so the link should be correct. Even when using the .js files that come with the book (with a finished version of the application I'm trying to make), nothing loads.
Testing with alert statements tells me the request.onload event never happens. I'm clueless as to why this is the case.
A fact I don't quite understand yet: when I type: http://localhost/gumball/sales.json: in my browser (I added a colon at the end of the link), I get a 403 Forbidden error! Why does this happen? Does this have something to do with my problem?
I open html document with firefox
Your HTML document must be open with a URL in http://, not file://, if you want it to be able to open in javascript another document, unless the second document is served with relevant CORS headers.
This is due to same origin policy.
As you have a local WAMP server, there is no problem : simply open your file using a http:// URL like you do for your JSON file.

xmlHttpRequest displays eurosign as questionmark

I use this script (from dynamicdrive) to dynamically fill div with id:
var bustcachevar=1 //bust potential caching of external pages after initial request? (1=yes, 0=no)
var loadedobjects=""
var rootdomain="http://"+window.location.hostname
var bustcacheparameter=""
function ajaxpage(url, containerid){
var page_request = false
if (window.XMLHttpRequest) // if Mozilla, Safari etc
page_request = new XMLHttpRequest();
else if (window.ActiveXObject){ // if IE
try {
page_request = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e){
try{
page_request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e){}
}
}
else
return false
page_request.onreadystatechange=function(){
loadpage(page_request, containerid)
}
if (bustcachevar) //if bust caching of external page
bustcacheparameter=(url.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime()
page_request.open('GET', url+bustcacheparameter, true)
page_request.send(null)
}
function loadpage(page_request, containerid){
if (page_request.readyState == 4 && (page_request.status==200 || window.location.href.indexOf("http")==-1))
document.getElementById(containerid).innerHTML=page_request.responseText
}
Everything works fine until I load a page with for example a euro-sign in it.
Codepage's are set correctly on the page but it displays a questionmark.
I don't know enough javascript to fix this problem.
Thanks in advance for any advice!
NOTE: Thanks to friend I now know that saving the file you want to load using this script in UTF-8 fixes the problem. But I can't be sure that every page I load is UTF-8 encoded so my question is:
is there a way for the script to set the right charset? Is there a way to let the script adapt to the codepage of the file you want to load?
It seems like you have an encoding problem somewhere.
I highly suggest you to use UTF-8 everywhere as it is the established standard for the web. Check that the page doing the ajax call and the dynamically loaded page are encoded in UTF-8 and sent by the server with correct headers (the headers should contain something like Content-type: text/html; charset=UTF-8).
Also it is a best practice to replace exotic characters by their html firendly code in html pages to avoid such issues. Use € for €.
This is my hypothesis (and I think it's been confirmed by your updates):
When you write the remote document you are loading, you just open your editor, hit the € symbol in your keyboard and save. Since you never picked any encoding, your editor used the ANSI code page. And here's the issue: the ANSI code page basically depends on where you live. In Western Europe, Win-1252 is a popular choice and encodes the euro symbol as 0x80.
When you write the target HTML doc where you want to insert it, you do exactly the same and get a Win-1252 document. However, the webserver doesn't know what the encoding is. Many times, it'll default to something like ISO-8859-1 and it happens that ISO-8859-1 does not even have an euro symbol!
JavaScript reads 0x80 and writes 0x80.
The browser finds 0x80 in an HTML document that's supposedly ISO-8859-1. In such encoding, the 0x80 is actually blank.
So you don't have to fix your JavaScript code (there's nothing fixable there, mainly because there's nothing wrong there). You need to find out what your site's encoding is and generate files that actually use such encoding (advanced editors will let you choose).

How can I take common large chunks of oft-reused HTML source code?

A slew of pages I've written for one of my web projects share some 144 identical lines of code, reproduced in each file. If I update one of those lines, I have to go back through ALL of the pages that share the code and update for each page. Is there a straightforward way to include HTML from a separate file?
And for bonus points, since so many pages use this code, it would be nice not to have to reload it for each page. Is there an easy way to store it in the browser's cache or only load the "content" section of the pages while leaving the rest of the page static?
Fountains of Thanks for any wisdom on this.
Mike
To include HTML from a separate file, use SSI (Server-Side Includes). This requires SSI support to be installed on the server, however.
You would write something like this in your files:
<!--#include file="included.html" -->
and that would include the file included.html when the page is accessed.
To load only the content of each page, use the XMLHTTPRequest object from JavaScript:
function LoadContent(url)
{
if (typeof(XMLHttpRequest) == "undefined")
{
try
{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch(e)
{
try
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e)
{
// fallback for browsers without XMLHttpRequest
window.location.href = "no-ajax.php?url="+escape(url);
return;
}
}
}
else
{
xmlhttp = new XMLHttpRequest();
}
xmlhttp.open("GET", url, false); // this request will be synchronous (will pause the script)
xmlhttp.send();
if(xmlhttp.status > 399) // 1xx, 2xx and 3xx status codes are not errors
{
// put error handling here
}
document.getElementById("content").innerHTML = xmlhttp.responseText;
}
If we're assuming that you're talking straight html pages, with no server code (asp.net, php, or server side include ability), then in order to do both the including and the caching, you're going to need to use an iframe.
Each of your pages that duplicate the 144 lines of content should replace it with an iframe like so:
<iframe src="pagewithcontent.html"></iframe>
pagewithcontent.html would obviously be where you move the content to. The browser will cache the page appropriately, so that each parent page will simply get the shared content without making another request.
There's an article here that goes into great depth about html includes, and some javascript methods of doing it. I would strongly recommend against the javascript methods.
My answer reflects the assumption that you can't do anything on the server side. However, by far the best solution is to do so if you can.

Categories