I'm loading a rather large text file using the require.js text plugin. It is required by a module that parses it as JSON and uses the data to hydrate some models. After that, the original text is no longer needed.
As far as I know require.js keeps everything it has loaded in memory. Is there a way to prevent that?
Another option would be to load the text file manually via AJAX but doing it via require.js would be much more convenient.
I do NOT want cache busting solutions. The file is only loaded one time and I just don't want to keep it in memory when I no longer need it.
According to the requirejs doocumentation you can "undef" a module:
http://requirejs.org/docs/api.html#undef
This won't free memory for pieces of your code that have already required the module, but for those you could unset the local version via my_module = undefined.
Related
Appending a file's hash to its url seems like a common thing to do to ensure files can have infinitely far cache expiration dates without causing problems when a new version of the file is available.
How is this task usually accomplished in Node.js?
Being clearer
Instead of asking the browser to load main.js, I would ask for main.085cc38ce00780e9365ee07275bfb8d8.js, where 085cc38ce00780e9365ee07275bfb8d8 is the file hash. So that when I change the content of my main file, the hash will also change and it will be as if the HTML were requesting a completely different file.
The solution I'm looking for must tackle:
Renaming the file or mapping the name-with-hash to name-without-hash
If files are renamed, getting my HTML markup to reference the correct file name with hash.
For context: My current build pipeline uses Gulp and docker, so I rebuild everything on every change, but I am open for any solution.
This issue AngularJS disable partial caching on dev machine suggests using $templateCache.removeAll() to clear the cache templates. However what if you just want to fire this once upon each deployment cycle in order to get visitor browsers to refresh/update the template? Our problem was some browsers were not updating the template html files, we'd end up with new CSS mixed with old HTML. I do not want this function to fire all the time, that would defeat the point of cache templates to begin with (right?).
Per the title question, what's a recommended way to clear $templateCache "once", for example some ideas I've crunched:
Does Angular have an internal method of detecting if the template file has changed? And then if so "update" it.
Does Angular have an internal "version" or "date" we could compare and add a conditional to fire function removeAll()?
Does $templateCache ever itself know to refresh? What were the Angular creator's intentions in forcing templateCache on us if HTML files are bound to change overtime and served to multiple browsers.
I do not want to use grunt to add workflow overhead for something that happens periodically, nor to chop up the html file templates into variables. (Is this a good method for template cache busting in angular?)
The alternative I can see is simply adding and removing removeAll() code manually, that would be silly.
We decided to go with simply tacking on UNIX timestamp version to files which were changed like file.php?v=154325232. The reason being we weren't actually using Angular templateCache, in that we weren't storing the template data itself inside templateCache. I thought Angular automatically stores any async loaded directive template files into templateCache, thats not true, you have to explicitly use templateCache to get a file (Good tutorial on that https://thinkster.io/templatecache-tutorial).
So our solution is just boring old versioning, which is most understandable by browser headers and for non-mega-scaling websites, just fine.
$modifiedTs = filemtime($filename);
if ($modifiedTs != $lastModificationTs){
echo "$filename?v=" . time();
}
How to check if a file has changed?
Lastly the way I read templateCache, its not intended to save data between browser sessions rather its a cache service during the session. It has nothing to do with the browser cache, rather Angular stores it internally. So its meant for websites that dynamically navigate and load URLs (ie: not a true page refresh but an AJAX trick) which is how most of Google websites are today.
Prevent browser cache of angular templates
Best way to manually clear out $templateCache in AngularJS
The current popular method is to create a task using a node module that preprocesses Angular templates into a file in which you add into the js stack.
You could install gulp-ng-html2js and make it a gulp task. This would output a file say templates.js, which you then add to the head.
https://www.npmjs.com/package/gulp-ng-html2js
Then call it out in your app as a module dependency. app.module('myApp',['templates']);
So before each deployment, run this gulp task.
And if needed add a cache breaker query string templates.js?v=123
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.
When I use google maps, I am interested in its implemention, so I use the firebug to inspect.
Then I found that its javascript loading strategy is rather interesting. Take this page for example:
The overlay example
Then when I open this page first time, the following js are loaded:
https://maps.googleapis.com/maps/api/js?sensor=false
https://maps.gstatic.com/intl/en_us/mapfiles/api-3/9/13b/main.js
https://maps.gstatic.com/cat_js/intl/en_us/mapfiles/api-3/9/13b/%7Bcommon,map,util,poly%7D.js
https://maps.gstatic.com/cat_js/intl/en_us/mapfiles/api-3/9/13b/%7Bonion,geometry%7D.js
But if I refresh the page(use the ctrl+f5), the following js are loaded:
https://maps.googleapis.com/maps/api/js?sensor=false
https://maps.gstatic.com/intl/en_us/mapfiles/api-3/9/13b/main.js
However the page still works, the overlay is drawn in the map. But where is the poly.js and etc?
Also, can anyone tell me how to load the js by components? For exmaple the common util poly in the example.
What should I know when I write the different components?
1. When poly.js loads, it passes a string to google.maps.__gjsload___.
Here's an excerpt:
google.maps.__gjsload__('common', '\'use strict\';var Ai=isNa...
The rest of the file is just the contents of that string.
My hunch is this function probably stores this string in localStorage or sessionStorage so that it only has to be retrieved once.
2. Also, if you want to learn about loading js files as-needed, look into AMD and/or CommonJS:Modules.
A good imlementation of AMD (my preference) is RequireJS.
Update
I did some poking around, and localStorage and sessionStorage do not appear to be being used on this page. I also can't duplicate your results. In Firebug, poly.js always loads for me. There may be some magic happening somewhere, but I don't see it.
However, it's entirely possible to store a string in localStorage and sessionStorage for retrieval without having to make an extra js call.
Also,any one can tell me how to load the js by components?
this touches on the topic of asynchronous javascript file loading. if you've ever used a language that has a way to "include" a file at any point in a script, you'll understand that javascript does not have this capability. because of that, there is this whole paradigm of "aysnc javascript addition" via script tag injection.
script tag injection: you dynamically make a script tag, and set its source to the file you need, and insert that tag into the DOM, and voila, a new file has been loaded and executed. With javascript heavy applications, this is common, especially when loading third party applications. Google does it alllll the time, just check out google analytics' include script for a good example of this.
Now, since this is a touchy and delicate type of coding to do, some "javascript component / module / asset loading" frameworks have refined it and made it pretty stable. common.js, require.js, etc have all done good jobs at this.
What should I know when I write the different components ?
For what you're doing with google maps, you don't really need to know much. but if you get into javascript module pattern development, you need to know this: make sure you protect your global namespace from being cluttered by your own variables, so encapsulate all of your work in closures when possible, and (recommended but not required) start them all with a ; so they don't break each other if they get loaded out of order.
There are a lot of questions and answers on SO related to my problem [I want the browser to cache js/css forever. During a new release if some of the js/css files have been updated, the browser should reload and cache them.]
This solution seemed most appropriate to me :
What is an elegant way to force browsers to reload cached CSS/JS files?
However, there is just one thing that I am unable to figure out.
The solution makes use of last_modified_time. However, I am not allowed to use it. I need to use some other mechanism.
What are the options? Is there a possibility of pre-calculating the versions during build and updating(replacing) them in jsps via build script (before deployment, so that the version numbers are not calculated on run time)? Any existing tool for this purpose? I use Java/Jsp.
We always use
file.css?[deploytimestamp]
This way the CSS file is cached for each deployment at the client. The same goes for our minified javascript. Is this an option for you?
It may not be the best way, but this is what I am doing now:
All of my js/css have a [source control = svn] revision number
References in my jsp are like /foo/path1/path2/xyz000000/foo.
Build Step 1 - Generate a map of css|js files and their revision numbers
Build Step 2 - Replace xyz000000 references in jsps with a hash of svn revisions
A rule in url rewriter to direct all /foo/path1/path2/xyz<767678>/foo. to /foo/path1/path2/foo.[js|css]
Infinitely cache the css|js files
Whenever there is a commit, the revision number changes and so do the references in .jsp
Generate an md5-hash of each css file after deployment. Use this hash instead of the timestamp in the url of the css.
file.css?[hash of file.css contents]
It may be wise to calculate the hashes once after deployment and store them to gain some performance. You could store them in a database, or even in a PHP array in a separate file that is included in your website code.