Javascript - Load new cache on deploy - javascript

I want to load a new version of my javascript,css,html etc.. every time i deploy my page. I saw that i could add ?<version> to the script's src link, Is there any other new/more reliable way of doing this?
UPDATE I'm looking for something like a variable that would allow me to update the URL automatically if a new file is loaded rather than me renaming the files manually. Is this possible?

I think that an elegant way is to use a gulpfile which rename your *.css and *.js filename to include a hash of file content at the end.
1) Gulp library : deal with filename
https://github.com/sindresorhus/gulp-rev
Example of what it does : transform filename unicorn.css into unicorn-d41d8cd98f.css
2) Gulp library : deal with index.html include
To inject css and js, you could use another gulp librairie :
https://www.npmjs.com/package/gulp-inject
This one allow you to include automatically css and js in your index.html using file directories.
3) What you have to do
All you have to do is to create a gulp task which use these two library. I swear it's not to hard. I don't have enough time to do a demonstration (I'll do it in the next few days).
This solution presents two advantage :
Only changed files are cache reloaded on the user side
You don't need to use an external js library inside your project,
which increase a risk of failure.

Add the resource's last-edited time to the src/href of the resource's element, or add an MD5 of all related times if you're linking to an aggregation script that might include sub-directories, etc.
http://verens.com/2008/04/09/javascript-cache-problem-solved/

Related

Custom script and css versioning best practices and automation with gruntjs

I've decided to start versioning the custom css and js files i use in my WP themes so that when I update a site a page reload is not needed to display the changes to users(long overdue, I know).
Is just adding a version number as a query string at the end of the call and keeping the real file name static a good practice(as in "script.js?v=xyz")? How will this affect browser caching when the version number is not changed? Will it cache normally and only get a new version when i change the version number?
If the above is the way to go, i would like to automate this with Grunt so when I run my "build" command the PHP file where the files get enqueued in WP gets modified to contain a random hash + the date as the version parameter in the wp_enqueue_script command. I presume that when i run my development command with livereload and everything, the scripts having said version will not affect livereload so i do not need to remove the versioning, correct?
How would you do this, what npm module would you use and what would be the commands i need to add to my Gruntfile.js?
As a sidenote, i know that the version number added by wordpress by default to all scripts and css is considered a security risk as it exposes the WP version you're rolling and i've been removing it via functions.php, but, i would like to enable it, yet have it not use the WP version but something random that gets changed with each WP update. Any idea how one would implement this? I'm surprised that i was not able to find a plugin that does this.
Thank you ver much, community!
I have certainly done this, as a way of indicating to browsers that they should download a newer version of a stylesheet. This isn't particularly elegant, but one thing I've done is declared cache-busting parameter (xyz in your example) as a PHP constant:
// inc/constants.php
define('CACHEPARAMETER', '20161027');
And my grunt build task modifies this using grunt-text-replace:
replace: {
cacheparam: {
src: ['inc/constants.php'],
overwrite: true, // overwrite matched source files
replacements: [{
from: /'CACHEPARAMETER', '[0-9]{8}'/g,
to: "'CACHEPARAMETER', '<%= grunt.template.today('yyyymmdd') %>'"
}]
}
}
I'm enqueueing this in functions.php, which I do like this:
include "inc/constants.php";
wp_enqueue_style( 'my-style', get_stylesheet_uri(), array(), CACHEPARAMETER);
Hope this helps.

Does Google's mod_pagespeed provide auto versioning of CSS and js files?

https://developers.google.com/speed/pagespeed/module/
This link doesn't talk specifically about CSS and js auto versioning but I read somewhere that this module can be used for auto versioning of CSS and js files. Would like to confirm about this.
Please let me know if auto versioning is part of google's mod_pagespeed module and if it can be used with my Apache tomcat 8 server ?
Any references to the above functionality will be greatly appreciated.
I have done some testing and from what I can see, the answer is no, well at least no in the sense that it won't auto version immediately after a change.
For reference, I'm running Apache 2.4.10.
From my tests, I had 4 javascript files that I was monitoring, these files were being optimised by pagespeed and the resulting file had a hash of ...pagespeed.jc.bFZBaW2xkN.js.
Within this file, it also gives hashes for each file it combines.
var mod_pagespeed_64gxmrG5cP = ...
var mod_pagespeed_r8BXvaG1ZV = ...
var mod_pagespeed_86DySW9yKu = ...
var mod_pagespeed_FAqlx5ADkk = ...
I found that I would make changes to files but nothing would change until I did a hard refresh (using Chrome).
When hard refreshing, I noticed the main file name ...pagespeed.jc.bFZBaW2xkN.js hash would update and looking within the file showed the change but that the inner hashes that represented the combined file were still the same.
I ended up implementing my own auto versioning in a php function that just appends the file modified time to the end of the file as a query eg. somejavascriptfile.js?v=0123456789
Now if I touch the file, the main combined file updates its hash but the inner hashes also update.
Hope this helps anyone else out there wondering the same thing.

How can I access images from Javascript using Grails Asset-Pipeline plugin?

I have just upgraded to Grails 2.4 and am using the Asset-Pipeline1.8.7 plugin. I am wondering how to access the images from Javascript. I am using the Google Maps Javascript V3 API and need to set some marker icons in Javascript. Is there a way to create some Javascript vars on a GSP using the tag and then access the file in my app.js code? If that is not possible, how do a reference the compiled images in assets?
You could define a globally available object that holds the root-path to your assets dir and use this to build-up URLs to your assets.
Add this snippet to your layouts head-section
<g:javascript>
window.grailsSupport = {
assetsRoot : '${ raw(asset.assetPath(src: '')) }'
};
</g:javascript>
Then use it elsewhere like this:
<g:javascript>
var pathToMyImg = window.grailsSupport.assetsRoot + 'images/google_maps_marker.png';
</g:javascript>
Update 2015-08-06
While checking the release notes of the asset-pipeline plugin I noticed that non-digest versions of assets are no longer stored in the WAR-file. This would mean that my proposed solution breaks when the application is deployed as a WAR:
May 31, 2015
2.2.3 Release - No longer storing non digest versions in war file, cutting overhead in half. Also removed Commons i/o dependency. Faster byte stream.
This means that you have to explicitly define all your images beforehand and are no longer able to construct the path dynamically in your scripts:
<g:javascript>
window.grailsSupport = {
myImage1 : '${assetPath(src: 'myImage1.jpg')}',
myImage2 : '${assetPath(src: 'myImage2.jpg')}'
};
</g:javascript>
Update 2016-05-25
It is now possible to configure if non-digest versions of the assets are included in the built war-file by setting grails.assets.skipNonDigests (default is false):
It is normally not necessary to turn off 'skipNonDigests'. Tomcat will automatically still serve files by non digest name and will copy them out using storagePath via the manifest.properties alias map. This simply cuts storage in half. However, if you are attempting to do things like upload to a cdn outside of the cdn-asset-pipeline plugin and via the contents of 'target/assets'. This may still be useful.
Note that you still might use the proposed solution to define all required images beforehand to work around caching issues in the browser (as the digest-version of the asset has its content-hash in the filename).
Yes you can by putting a ${assetPath(src: 'img.png')} in your gsp
I don't know what the ideal solution is in your case but a solution might be:
Use relative paths like '../assets/use-control.png' in your js code.
Add the img in your dom and reference it from your js code.
Add a data-imgpath="${asset.assetPath(src: 'use-control.png')}" attribute on an appropriate element in your dom and use this link.
As an alternative you can use HTML5's data-* Attribute.
I've explained a bit further here:
load images from javascript

How to disable the JavaScript Minifier in CodeKit?

What's the best way to disable JavaScript minification in CodeKit? All those *-ck.js files it creates are making a mess of our repository's submodules.
Note that adding a rule to .gitignore doesn't work because its rules aren't inherited by submodules.
In CodeKit Preferences select Languages / JavaScript to edit the default settings for JavaScript handling. (These can be overridden for each file in a project.)
Change the setting for the second processing step (labelled "Then:") from "Concatenate + minifiy" to "Concatenate imported files". For any script file already in the project check whether it already has individual settings which still differ from this new default.
In this case, "*-ck.js"-files should only be created in case a source file imports another for concatenation but not for ordinary script files.
Alternatively you might specify a different output path for the generated ck-Files in CodeKit Preferences / JavaScript / Output Paths in order not to let the generated files clutter the source directory.
I believe the menu has been updated, but the answer from immo still stands. Under Javascript Language settings you can click a dropdown for output style and change it from minified to non-minified.
One workaround is to set the output path to something like codekit-ignore in Preferences > JavaScript > Output Paths, relative to the project's root folder.
Then add /codekit-ignore to .gitignore.
Easy to cleanup and feels better than find . -iregex '.*-ck\.js' -delete.
In the preferences see 'Skipped Items' under 'General' and add *.js to the list.
There are several ways to stop javascript minification in Code Kit but the easiest and simplest way to do so is simple to navigate to the javascript file you wish not to minify in the file view, and configure your Javascript Options to the right hand side.
This method provides benefits such as JSHint & JSLint without the minification and can be configured on a site by site, file by file basis giving you greater control.
Let me know if you have any further issues, i'd be happy to help.

require.js - How can I set a version on required modules as part of the URL?

I am using require.js to require JS modules in my application.
I need a way to bust client cache on new JS modules, by way of a different requested URL.
i.e., if the file hello/there.js has already been cached on the client, I can change the file name to force the browser to get the new file.
In other words, for the module hello/there, I'd like require.js to request the url hello/there___v1234___.js (the file name can look different, it's just an example), according to a version string which is accessible on the client.
What is the best way to achieve that?
I got really frustrated with the urlArgs solution and finally gave up and implemented my own fix directly into require.js. This fix implements your ideal solution, if you are willing to modify your version of the library.
You can see the patch here:
https://github.com/jbcpollak/requirejs/commit/589ee0cdfe6f719cd761eee631ce68eee09a5a67
Once added, you can do something like this in your require config:
var require = {
baseUrl: "/scripts/",
cacheSuffix: ".buildNumber"
}
Use your build system or server environment to replace buildNumber with a revision id or software version.
Using require like this:
require(["myModule"], function() {
// no-op;
});
Will cause require to request this file:
http://yourserver.com/scripts/myModule.buildNumber.js
The patch will ignore any script that specifies a protocol, and it will not affect any non-JS files.
On our server environment, we use url rewrite rules to strip out the buildNumber, and serve the correct JS file. This way we don't actually have to worry about renaming all our JS files.
This works well for my environment, but I realize some users would prefer a prefix rather than a suffix, it should be easy to modify my commit to suit your needs.
Here are some possible duplicate questions:
RequireJS and proxy caching
Prevent RequireJS from Caching Required Scripts
OK, I googled "requirejs cache bust" for you and found this existing SO answer, which says you can configure requireJS with an urlArgs parameter, which is only a partial solution, but it might be enough to meet your immediate needs.
That said, the cachebusting problem is full of challenges and many "solutions" don't actually solve the problem in its entirety. The only maintainable way to do this (IMHO as of now) is with a full-on asset management system like the Ruby on Rails asset pipeline or connect-assets or the equivalent for your server side framework of choice. Those can correct compute a checksum (usually MD5 or SHA1) of the content of each file and give you the file names you need to put as URLs in your HTML script tags. So, don't bother with manually changing filenames based on version numbers, just use checksums since they are easily automated and foolproof.
From what I can tell, out of the box requirejs can't do the cachebusting aspect for you. You might want to read this google groups thread. Otherwise, you may need to pair requirejs with an additional tool/script to get you good cachebuster checksums.
Just do it like the creator of requirejs suggests:
var load = requirejs.load;
requirejs.load = function (context, moduleId, url) {
// modify url here
url = url.substring(0, url.lastIndexOf('.')) + '.' + VERSION + url.substring(url.lastIndexOf('.'));
return load(context, moduleId, url);
};
https://github.com/jrburke/requirejs/wiki/Fine-grained-URL-control
HTML5 Boilerplate has ant-build-script that renames your files and any reference to them for this exact reason and can do alot more. It's worth checking out if you haven't already.

Categories

Resources