I am facing some difficulty to update cache information from the server by using HTML 5 offline caching method.
Here is the list of steps,
1- Created one cache.manifest file with following entries
CACHE MANIFEST
# Version 1.0
CACHE:
/loading.js
/images/pan-icon.png
NETWORK:
*
Then i jest add following event binder to load updated information from the server
window.addEventListener('load', function (e) {
window.applicationCache.update();
window.applicationCache.addEventListener('updateready', function (e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Browser downloaded a new app cache.
window.applicationCache.swapCache();
console.log('Updated');
} else {
console.log('No Update');
}
}, false);
}, false);
But it alwayes failed to get latest 'loading.js' from the server. I need to clear the cache to get update from the server.
Is there any way to update this forefully.
Please help me
I am using ASP .NET MVC framework to build my web application
When ever you change the content of a file that is defined in your manifest, you must update the manifest file as well in order for the browser to pull down the latest content of that file.
From the gotchas section from MDN (https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache)
When applications are cached, simply updating the resources (files) that are used in a web page is not enough to update the files that have been cached. You must update the cache manifest file itself before the browser retrieves and uses the updated files. You can do this programmatically using window.applicationCache.swapCache(), though resources that have already been loaded will not be affected. To make sure that resources are loaded from a new version of the application cache, refreshing the page is ideal.
Related
My Meteor project has two part:
Home page: can be visited by anyone.
Admin Console: provide some management tools to administrator only
When I running this project in production mode:
$ meteor --production
Meteor will combine all the client side code into one big file, that make "Admin Console" code also delivered to normal visitors.
Is there any way to "minify" javascript/css files into two files?
one for normal visitor, one for admin?
I also pack this project into Android package, "Admin Console" code also exists in apk file, how can I exclude them ?
Thanks.
You can use meteor dynamic imports to only download code to the client based on the view the client is using. I have not tried this yet, but it should be possible to not load files dynamically based on the user's role.
Something like:
//must be called inside a meteor method or publish function
async function adminOnlyApi() {
if(Roles.userIsInRole(Meteor.userId, ['admin']) {
return await import('path/to/lib');
}
return {};
}
Assuming the lib exports a default object with a key 'foo' and value 'bar', calling adminOnlyApi.foo when logged in as admin should return 'bar', and return undefined when logged in with any other user...
I've been diving into ASP.NET MVC internal functionality much (different reasons), but still can not cover all the behaviour. One of those which I did not is subj.
The way it works is the following:
if I bundle some files (css files for instance), the framework detects those changes and generates new id for the new bundle (to make it easy for browsers to refresh the changes) like href="/Content/css?v=qartPE4jGe-l1U0I7kNDZPZzVTdh0kT8VBZZA_uURjI1".
What I am actually trying to understand:
How exactly the framework (that's possibly not MVC but .NET stuff) detects that the files are changed (as there are no directory watchers active (as I can change the file even when web-server if off-line) to see the file changes live, and also the system detects actually the file content changes (I tried just to re-save files without changing their contents and the bundle number did not change as well))?
(I consider that obviously the system can not compare every file content to detect its changings on every request came).
Where (and how) the frameworks stores current bundle id and how it stores previous versions (as previous bundles are still available when go to their urls)?
Thanks a lot!
The ASP.NET Optimization framework caches the bundle response in HttpContext.Cache and uses a CacheDependency to monitor each file in the bundle for changes. This is why updating the files directly invalidates the cache and regenerates the bundle.
The bundle file name is a hash of the bundle contents which ensures the URL changes when any of the bundle files are modified. The bundle's virtual path is used as the cache key.
The relevant code from the library (note this is slightly out of date but I believe the logic is still the same):
internal BundleResponse GetBundleResponse(BundleContext context)
{
// check to see if the bundle response is in the cache
BundleResponse bundleResponse = Bundle.CacheLookup(context);
if (bundleResponse == null || context.EnableInstrumentation)
{
// if not, generate the bundle response and cache it
bundleResponse = this.GenerateBundleResponse(context);
if (context.UseServerCache)
{
this.UpdateCache(context, bundleResponse);
}
}
return bundleResponse;
}
private void UpdateCache(BundleContext context, BundleResponse response)
{
if (context.UseServerCache)
{
// create a list of all the file paths in the bundle
List<string> list = new List<string>();
list.AddRange(
from f in response.Files
select f.FullName);
list.AddRange(context.CacheDependencyDirectories);
string cacheKey = Bundle.GetCacheKey(context.BundleVirtualPath);
// insert the response into the cache with a cache dependency that monitors
// the bundle files for changes
context.HttpContext.Cache.Insert(cacheKey, response, new CacheDependency(list.ToArray()));
context.HttpContext.Response.AddCacheItemDependency(cacheKey);
this._cacheKeys.Add(cacheKey);
}
}
Finally as for old bundle URLs working, I think you will find they are either returned from your browser cache or actually return the latest version of the bundle since the bundle path doesn't change, only the version query string.
What's a good strategy for versioning Durandal js and html files?
I noticed that, during development, your browser cache must be disabled in order for you to receive up to date files on each refresh. This is a must for during development.
However, my concern is that when I go to production with my continuous deployment strategy (deploying multiple times per day), that users' browsers will be caching older versions of my app which might lead to unpredictable behaviour.
The approach that springs to mind would be to version the js and html urls somehow so that there is a version number embedded into every request. But I am unsure as to how to make that work internally within the Durandal framework.
Ok, here is the direction that I am heading in. Basically there is something built into requirejs to handle this.
At the top of my main.js, in the call to requirejs.config I can set a urlArgs property that will be appended to every call requirejs makes for a module.
requirejs.config({
paths: {
'text': 'durandal/amd/text'
},
urlArgs: 'v=1.0.0.0'
});
When I want to force production users to get a new version of the requirejs modules I can just increment the version number which will invalidate the browsers cache.
(In my project I have a way of injecting the version number of the assembly containing my main ASP.NET MVC assembly into this property, but the code for that would have distracted from the simplicity of the above example).
Hope this helps someone!
For .NET, add the main-built.js file as a script bundle in App_Start/BundleConfig:
public static void RegisterBundles(BundleCollection bundles)
{
//...
bundles.Add(new ScriptBundle("~/Scripts/main-built").Include(
"~/App/main-built.js"));
//...
}
Reference the script bundle on your index page:
#if (HttpContext.Current.IsDebuggingEnabled)
{
<script type="text/javascript" src="~/Scripts/require.js" data-main="App/main"></script>
}
else
{
<!-- Remember to run the weyland optimizer to create the main-built.js -->
#Scripts.Render("~/Scripts/main-built")
}
As long as you have the default Web.Release.Config file, Visual Studio will automatically remove debug attributes while also minifying and versioning your bundles upon publishing.
I am using ASP.NET optimization package to minify and bundle the scripts, and CSS files.
I am also developing a mobile UI for my ASP.NET application which uses a HTML5 cache manifest.
The optimization package updates the version of the dynamic bundle URL when the files change and the application cache is recycled.
I would like to be able to update my manifest version whenever this happens and include the dynamic URLs the optimization package provides in the manifest.
How can I read the current version (the "v" parameter) or anything else to trigger a manifest update?
/_assets/bundles/global?v=fmbQlO0mGjXyliVEBImQIr5yoMX0Tw0tlMK45jlwHZ81
Example Code:
string version= "2.6";
StringBuilder output = new StringBuilder();
output.AppendLine("CACHE MANIFEST");
output.AppendLine(string.Format("# v{0}", ??????));
output.AppendLine("CACHE:");
output.AppendLine(Scripts.Url("~/bundles/global").ToString());
...
The Application Manifest will automatically trigger an update if it is changed.
With static assets, people usually changed a version number in a comment so that the file was changed and would trigger an update, even though the content under the CACHE, NETWORK and FALLBACK sections were unchanged.
When you are using the URLs generated by System.Web.Optimization, the URL will change when the content of any of the CSS or JavaScript files in the bundles changes. This means that the manifest file will automatically be different to the previous version of the file and will trigger an update.
There is no need to force the file to be different by updating a version comment.
I want to create a file and then serve it using Meteor, but I don't want the server to restart when I create/update the file in the public directory.
The user will click on a button to create a config file on the server and I want the user to be able to download that config file.
Is there a way to do this without triggering the server to restart?
I have tried creating a link to the file and creating a hidden file but nothing has worked.
Thanks for your time.
Try meteor run --production. That might solve your problem.
Server restarts because you are running it in Development mode,
When it runs in production, it doesn't restart on content changes.
To run in production, only way I know is, after bundling application,
Have a look here: http://docs.meteor.com/#deploying
If you doesn't want to run in production mode, here is a workaround:
In order to prevent reloading, you have to generate your files in a folder that is located outside of your project's repository.
Then you will have your meteor app to serve the content of that folder.
Here is an example that uses the connect npm repository to make your local folder /meteor/generated_files served under the url hostname.com/downloads/:
var connect = Npm.require('connect');
var fs = Npm.require('fs');
function serveFolder(urlPath, diskPath){
if(!fs.existsSync(diskPath))
return false;
RoutePolicy.declare(urlPath, 'network');
WebApp.connectHandlers.use(urlPath, connect.static(diskPath));
return true;
}
serveFolder('/downloads', '/meteor/generated_files/');
I published the very primitive package I have that does just that.