Force reload of a directive's template - javascript

I am working on an AngularJS app with several directives. The directive's templates are stored in a separate html file. When editing these template, my browser does not detect any changes after a reload and always uses a cached version. Any other changes to the source code are detected and lead to a reload.
I guess the problem is somewhat the $templateCache which seems to be used by AngularJS when loading the template.
What I found in the source code of AngularJS 1.0.2 is the following from line 4317 which is part of the compileTemplateUrl():
$http.get(origAsyncDirective.templateUrl, {cache: $templateCache})
I am wondering if anyone else had this kind of problem and if there is a way to tell AngularJS when to cache and when not.

I know this is an old question, but here's a simpler fix, although it's a bit of a hack, it works for me, and doesn't require you to do anything to $templateCache.
Whenever I run into this problem (I see it in directive templates, but also static JSON files), I add a query parameter to the end of the URL being loaded, like this:
...
templateUrl: "partials/template.html?1",
...
Whenever I make a changes to the template, and it's not reloading, I increment that number at the end. As the browser doesn't know if this might mean something special to the server, it should attempt to reload that changed URL whether it's cached or not. This will also make sure the file is reloaded in the production environment.

The template cache is stored in your browser, as this is a javascript app. You can actually feed the $cache manually or stop your browser from caching the templates (as it would seem that for production, cache won't be a problem), using developer tools.
For force feeding the cache:
function Main($cache) {
$cache.data['first.html'] = {value: 'First template'};
$cache.data['second.html'] = {value: '<b>Second</b> template'};
}
Main.$inject = ['$xhr.cache'];​
See it working in this fiddle.
To stop your browser from caching the templates (cited from this Google Groups post, about this problem, exactly):
My team and I have ran into this same issue. Our solution for
development while using Chrome was to open Developer Tools, and select
the gear in the bottom right hand corner. Then select Network -
Disable cache.
This fixed all our partial/template caching issues.

app.controller('someCtrl', function ($scope, $cacheFactory, templateRequest)
{
$scope.refreshTemplate = function ()
{
var tpl = "<template name>";
$cacheFactory.get('templates').remove(tpl);
$templateRequest(tpl).then(function ok(){
console.log("Template "+tpl+" loaded.");
});
}
...
}
then when you call the refreshTemplate function you cause a re-load

Related

Chrome doesn't recognize my changes on my javascript file and loads old code?

I have been sitting here for almost an hour here to test the website I'm building. Since I wanted to see the new changes from my code I reloaded, but it was reloading old one. I opened the devetools to hard reload and empy cache hard reload, they both load my old code. I went to incognito mode and it did the same thing. I went to devtools again to disable the cache from the settings and checked the disable cache in the network tab; it still cache my old code. Add-ons to clear the cache didn't work as well. Man, I haven't had this problem before and it only happened last night and it's worst today.
I'm so lost now since chrome doesn't load my new changes from my javascript file. Is there a solution for this?
One solution for this problem is to force reloading the resource in order to avoid the cache. You can get this modifying the url with http get parameters:
Change:
<script src="myscripts.js"></script>
to:
<script src="myscripts.js?newversion"></script>
Where newversion can be any string as it will be ignored. A useful option is to use the date, or version, of your code.
I found this workaround particularly useful when I came across this same problem and wanted to ensure that all clients (not just my own browser!) would run the new version of the code.
I think there's an even better way:
You can use PHP to add the last modification date of your JavaScript file to the URI of that file.
<script src="js/my-script.js?<?php echo filemtime('js/my-script.js'); ?>">
</script>
The browser will receive:
<script src="js/my-script.js?1524155368"></script>
The URI of the file will automatically change if the file is updated.
This way the browser can still cache unchanged files while recognizing changes instantly.
Are you using any type of compilation tools (like gulp or grunt)? It's possible that there is an error in your code, and the tool is not compiling the updated code.
Otherwise, the solution #airos suggested should work. Appending any unique query string to the reference of your JS will always serve a fresh copy on first reload (since the browser will be caching a new URL).

Force HTML template reload in Angular2

I am working on Angular2 project and got an issue that Chrome caches HTML templates. It is not a problem for the development since I can make cache to be ignored in Chrome Dev mode.
But it is a real pain for the customer and his users...
I tried to add following to templateURL:
templateUrl: './pages/add-financial-deal.html?v=201610070907',
Updated URL is added into auto-generated JS but Chrome still uses cached JS even if I click Shift + F5. Checkout screenshot: http://screencast.com/t/bc2nf4zVcm
Is there any reliable way to get it working?
Thanks
Edit: Decmber 2nd
I have finally figured out what happening there. Despite the fact that I have added changes into TS (and auto-generated JS was also updated) Chrome is still loading file from in-memory cache - screencast.com/t/FGuaMXaKL . I have been waiting for 30 mins, but it still loads in-memory cached file. Is it intended behavior? How to avoid this?
I have finally fixed an issue which was actually 2 issues:
HTML templates were cached. This was fixed by adding extra parameter into template URL, like "template.html?v=201612041641"
JS files were staying in Chrome in-memory cache. Despite the fact that it should be kinda fast cache JS were cached for hours and hours. And Ctrl/Shift + F5 does not affect in-memory cache. Also, I tried to set cache control to "no-store, no-cache" in root html page. Finally, I set extra header into IIS Response header option "Control-Cache:no-cache" and now it works. JS files are stored on hard drive Chtome store, 304 status is recieved and changed files are properly updated

How to force client reload after deployment?

I'm using the MEAN stack (mongo, express, angular and node). I'm deploying relatively frequently to production...every couple of days. My concern is that I'm changing the client side code and the API at times and I would rather not have to ensure backwards compatibility of the API with previous versions of the client code.
In such a scenario, what is the most effective way of ensuring that all clients reload when I push to production? I have seen that Evernote for example has a pop-up that says something along the lines of please reload your browser for the latest version of Evernote. I would like to do something similiar...do I need to go down the path of socket.io or sock.js or am I missing something simple and there is a simpler way to achieve this?
Update:
AppCache was deprecated summer 2015 so the below is no longer the best solution. The new recommendation is to use Service Workers instead. However, Service Workers are currently still experimental with sketchy (read: probably no) support in IE and Safari.
Alternatively, many build tools now seamlessly incorporate cache-busting and file "versioning" techniques to address OPs question. WebPack is arguably the current leader in this space.
This might be a good use case for using HTML5's AppCache
You'd probably want to automate some of these steps into your deployment scripts, but here is some code you might find useful to get you started.
First, create your appcache manifest file. This will also allow you to cache resources in the client's browser until you explicitly modify the appcache manifest file's date.
/app.appcache:
CACHE MANIFEST
#v20150327.114142
CACHE:
/appcache.js
/an/image.jpg
/a/javascript/file.js
http://some.resource.com/a/css/file.css
NETWORK:
*
/
In app.appcache, the comment on line #v20150327.114142 is how we indicate to the browser that the manifest has changed and resources should be reloaded. It can be anything, really, as long as the file will look different to the browser from the previous version. During deployment of new code in your application, this line should be modified. Could also use a build ID instead.
Second, on any pages you want to use the appcache, modify the header tag as such:
<html manifest="/app.appcache"></html>
Finally, you'll need to add some Javascript to check the appcache for any changes, and if there are, do something about it. Here's an Angular module. For this answer, here's a vanilla example:
appcache.js:
window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Browser downloaded a new app cache.
// Swap it in and reload the page to get the latest hotness.
window.applicationCache.swapCache();
if (confirm('A new version of the application is available. Would you like to load it?')) {
window.location.reload();
}
}
else {
// Manifest didn't changed. Don't do anything.
}
}, false);
Alternatively, if AppCache won't work for your situation, a more ghetto solution would be to create a simple API endpoint that returns the current build ID or last deployment date-time. Your Angular application occasionally hits this endpoint and compares the result to it's internal version, and if different, reloads itself.
Or, you may consider a live-reload script (example), but, while very helpful in development, I'm not sure how good of an idea it is to use live/in-place-reloading of assets in production.
I will tell you my problem first then I will recommend a tentative solution. I wanted to force my user to log out and then log in when a production build is been deployed. At any point in time, there will be two versions of software deployed on production. A version which software which FE knows and a version which Backend knows. Most of the time they would be the same. At any point in time if they go out of sync then we need to reload the client to let the client know that a new production build has been pushed.
I am assuming 99.99% of the time the backend would have the knowledge of the latest version of the deployed software on production.
following are the two approaches which I would love to recommend:-
The backend API should always return the latest version of the software in the response header. On the frontend, we should have a common piece of code that would check if the versions returned by the API and that present on the FE are the same. if not then reload.
Whenever a user logs in. the BE should encode the latest software version in the JWT. And the FE should keep sending this as a bearer token along with every API request. The BE should also write a common interceptor for every API request. which would compare the software version in the JWT received from the API request and the
Maybe you can add hash to your client code file name. eg app-abcd23.js.
So the browser will reload the file instead of get it from cache. or you can just add the hash to url.eg app.js?hash=abcd23 but some browser may still use the cached version.
i know rails has assets-pipline to handle it, but i am not familiar with MEAN stack. there should be some package in npm for that purpose.
And i dont think it is really necessary to use socket.io if you want to notify the user their client code is out of date. you can define your version in both html meta tag and js file,if mismatch, show a popup and tell the user to refresh.
Try to limit your js/files to expire within smaller periodic time, ie: 1 days.
But in case you want something that pop-out and tell your user to reload (ctrl+f5) their browser, then simply make a script that popup that news if you just changed some of your files, mark the ip/session who have just reload/told to reload, so they will not be annoyed with multiple popup.
I was facing the same problem recently. I fixed this by appending my app's build number with my js/css files. All my script and style tags were included by a script in a common include files so it was trivial to add a 'build number' at the end of the js/css file path like this
/foo/bar/main.js?123
This 123 is a number that I keep track of in my same header file. I increment it whenever I want the client to force download all the js files of the app. This gives me control over when new versions are downloaded but still allows the browser to leverage cache for every request after the first one. That is until I push another update by increment the build number.
This also means I can have a cache expiry header of however long I want.
Set a unique key to local storage during the build process
I am using react static and loading up my own data file, in there i set the ID each time my content changes
Then the frontend client reads the key with from local storage
(if the key does not exist it must be the first visit of the browser)
if the key from local storage does not match it means the content has changed
fire line below to force reload
window.replace(window.location.href + '?' + key)
in my case i had to run this same line again a second latter
like
setTimeout( (window.replace(window.location.href + '?' + key))=> {} , 1000)
full code below:
const reloadIfFilesChanged = (cnt: number = 0, manifest: IManifest) => {
try {
// will fail if window does not exist
if (cnt > 10) {
return;
}
const id = localStorage.getItem('id');
if (!id) {
localStorage.setItem('id', manifest.id);
} else {
if (id !== manifest.id) {
// manifest has changed fire reload
// and set new id
localStorage.setItem('id', manifest.id);
location.replace(window.location.href + '?' + manifest.id);
setTimeout(() => {
location.replace(window.location.href + '?' + manifest.id + '1');
}, 1000);
}
}
} catch (e) {
// tslint:disable-next-line:no-parameter-reassignment
cnt++;
setTimeout(() => reloadIfFilesChanged(cnt, manifest), 1000);
}
};

Javascript debugging difficult as browser doesn't refresh the scripts!

I'm trying to debug a Javascript written in the Mootools framework. Right now I am developing a web application on top of Rails and my webserver is the rails s that boots WEBrick.
When I modify a particular tree.js file thats called with in one a mootools init script,
require: {
css: [MUI.path.plugins + 'tree/css/style.css'],
js: [MUI.path.plugins + 'tree/scripts/tree.js'],
onload: function(){
if (buildTree) buildTree('tree1');
}
},
the changes are not loaded as the headers being sent to the client are Last Modified: 10 July, 2010..... which is obviously not true since I just modified the file.
How do I get rid of this annoying caching. If I go directly to the script in my browser (Chrome) it doesn't show the changes until I hit refresh, but this doesn't fix my problem when I go back to my application and hit refresh, it still loads the pre-modified script.
This has happen to me also in FF, I think it is a cache header sent by the server or the browser itself.
Anyway a simple way to avoid this problem while in development is adding a random param to the file name of the script.
instead of calling 'tree/scripts/tree.js' use 'tree/scripts/tree.js?'+random that should invalidate all caches.
As frisco says, adding a random number in development does the trick but you will likely find that the problem still affects you production. You want to push new JavaScript changes to your users but can't until their browsers stop caching the file. In order to do this, just get the files mtime and add that as the random string. This will only change when the file is modified and so the JavaScript will be loaded from cache if it has not been changed or it will be loaded from the server, if it has.
PHP has the function filemtime but as I'm not familiar with Ruby, I'm afraid I can't help you further in that direction (sorry!). However, this answer seems to accomplish what you want.
Try the Ctrl+F5 trick. To avoid hitting browser cache.
More info here:
What requests do browsers' "F5" and "Ctrl + F5" refreshes generate?

How can I edit on my server files without restarting nodejs when i want to see the changes?

I'm trying to setup my own nodejs server, but I'm having a problem. I can't figure out how to see changes to my application without restarting it. Is there a way to edit the application and see changes live with node.js?
Nodules is a module loader for Node that handles auto-reloading of modules without restarting the server (since that is what you were asking about):
http://github.com/kriszyp/nodules
Nodules does intelligent dependency tracking so the appropriate module factories are re-executed to preserve correct references when modules are reloaded without requiring a full restart.
Check out Node-Supervisor. You can give it a collection of files to watch for changes, and it restarts your server if any of them change. It also restarts it if it crashes for some other reason.
"Hot-swapping" code is not enabled in NodeJS because it is so easy to accidentally end up with memory leaks or multiple copies of objects that aren't being garbage collected. Node is about making your programs accidentally fast, not accidentally leaky.
EDIT, 7 years after the fact: Disclaimer, I wrote node-supervisor, but had handed the project off to another maintainer before writing this answer.
if you would like to reload a module without restarting the node process, you can do this by the help of the watchFile function in fs module and cache clearing feature of require:
Lets say you loaded a module with a simple require:
var my_module = require('./my_module');
In order to watch that file and reload when updated add the following to a convenient place in your code.
fs.watchFile(require.resolve('./my_module'), function () {
console.log("Module changed, reloading...");
delete require.cache[require.resolve('./my_module')]
my_module = require('./my_module');
});
If your module is required in multiple files this operation will not affect other assignments, so keeping module in a global variable and using it where it is needed from global rather than requiring several times is an option. So the code above will be like this:
global.my_module = require ('./my_module');
//..
fs.watchFile(require.resolve('./my_module'), function () {
console.log("Module changed, reloading...");
delete require.cache[require.resolve('./my_module')]
global.my_module = require('./my_module');
});
Use this:
https://github.com/remy/nodemon
Just run your app like this: nodemon yourApp.js
There should be some emphasis on what's happening, instead of just shotgunning modules at the OP. Also, we don't know that the files he is editing are all JS modules or that they are all using the "require" call. Take the following scenarios with a grain of salt, they are only meant to describe what is happening so you know how to work with it.
Your code has already been loaded and the server is running with it
SOLUTION You need to have a way to tell the server what code has changed so that it can reload it. You could have an endpoint set up to receive a signal, a command on the command line or a request through tcp/http that will tell it what file changed and the endpoint will reload it.
//using Express
var fs = require('fs');
app.get('reload/:file', function (req, res) {
fs.readfile(req.params.file, function (err, buffer) {
//do stuff...
});
});
Your code may have "require" calls in it which loads and caches modules
SOLUTION since these modules are cached by require, following the previous solution, you would need a line in your endpoint to delete that reference
var moduleName = req.params.file;
delete require.cache[moduleName];
require('./' + moduleName);
There's a lot of caveats to get into behind all of this, but hopefully you have a better idea of what's happening and why.
What's “Live Coding”?
In essence, it's a way to alter the program while it runs, without
restarting it. The goal, however, is to end up with a program that
works properly when we (re)start it. To be useful, it helps to have an
editor that can be customized to send code to the server.
Take a look: http://lisperator.net/blog/livenode-live-code-your-nodejs-application/
You can also use the tool PM2. Which is a advanced production process tool for node js.
http://pm2.keymetrics.io/
I think node-inspector is your best bet.
Similar to how you can Live Edit Client side JS code in Chrome Dev tools, this utilizes the Chrome (Blink) Dev Tools Interface to provide live code editing.
https://github.com/node-inspector/node-inspector/wiki/LiveEdit
A simple direct solution with reference to all answers available here:
Node documentation says that fs.watch is more efficient than fs.watchFile & it can watch an entire folder.
(I just started using this, so not really sure whether there are any drawbacks)
fs.watch("lib", (event_type, file_name) => {
console.log("Deleting Require cache for " + file_name);
delete require.cache[ require.resolve("./lib/" + file_name)];
});

Categories

Resources