├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── lib └── index.js ├── package.json └── test ├── index.js └── views └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Saul Maddox 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Hapi Cache Buster 2 | ================= 3 | 4 | A Hapi cache buster for assets (css, javascript, images, etc) in your view templates. 5 | 6 | ## Goal: 7 | Have the client/browser reload new assets when there is a new version. 8 | 9 | ## How it works: 10 | It grabs the package.json version number of your application from the node process current working directory and uses that as the cache version. In your view template you can now access `version.cache`. You can place it where you are needing to update cache. 11 | 12 | Lets say your package.json is version `0.0.1`, it will print out `?v=001`. To bust the cache you just update your package.json version to a new number. 13 | 14 | 15 | Handlebars: 16 | `` 17 | 18 | Jade: 19 | `link(rel='stylesheet', href='css/styles.css#{version.cache}')` 20 | 21 | ### Options 22 | Instead of using the package.json version for the cache version, you can specify a number and pass it into the plugin options. 23 | 24 | ``` 25 | { 26 | register: require('hapi-cache-buster'), 27 | options: { 28 | version: 55 29 | } 30 | } 31 | ``` 32 | 33 | 34 | ### Other 35 | You can see this being used in the Hapi Ninja boilerplate example. [https://github.com/poeticninja/hapi-ninja](https://github.com/poeticninja/hapi-ninja) 36 | 37 | ### Troubleshooting 38 | If for some reason you are getting an error because its unable to find the package.json you can actually pass in the package.json version manually `require('./package.json').version`. This is useful if your current process working directory `process.cwd()` is different from the actual application. 39 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib'); 2 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | var Path = require('path'); 2 | 3 | exports.register = function (server, options, next) { 4 | var versionCache = options.version || null; 5 | 6 | if(!versionCache){ 7 | // Get the version of the application that loads this module from the process current working directory. 8 | var packageVersionNumber = require(Path.join(process.cwd(), './package.json')).version; 9 | 10 | // Replace all characters except numbers. 11 | versionCache = packageVersionNumber.replace(/[^0-9]/g, ""); 12 | } 13 | 14 | // Hook onto the 'onPostHandler' 15 | server.ext('onPostHandler', function (request, reply) { 16 | // Get the response object 17 | var response = request.response; 18 | 19 | // Check to see if the response is a view 20 | if (response.variety === 'view') { 21 | response.source.context = response.source.context || {}; 22 | response.source.context.version = response.source.context.version || {}; 23 | response.source.context.version.cache = '?v=' + versionCache; 24 | } 25 | return reply.continue(); 26 | }); 27 | return next(); 28 | }; 29 | 30 | exports.register.attributes = { 31 | pkg: require("../package.json") 32 | }; 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hapi-cache-buster", 3 | "version": "0.4.0", 4 | "description": "Hapi plugin to a bust the cache of browser assets.", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/poeticninja/hapi-cache-buster" 9 | }, 10 | "scripts": { 11 | "test": "./node_modules/lab/bin/lab" 12 | }, 13 | "keywords": [ 14 | "hapi", 15 | "cache", 16 | "plugin", 17 | "view", 18 | "templates", 19 | "assets" 20 | ], 21 | "author": { 22 | "name": "Saul Maddox" 23 | }, 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/poeticninja/hapi-cache-buster/issues" 27 | }, 28 | "dependencies": { 29 | "path": "~0.4.x" 30 | }, 31 | "devDependencies": { 32 | "cheerio": "~0.19.0", 33 | "code": "~1.4.0", 34 | "hapi": "~8.4.0", 35 | "lab": "~5.5.1", 36 | "swig": "~1.4.2" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dependencies. 3 | */ 4 | var Hapi = require('hapi'); 5 | var Code = require('code'); 6 | var Lab = require('lab'); 7 | var cacheBuster = require('..'); 8 | var Path = require('Path'); 9 | var Cheerio = require('cheerio'); 10 | 11 | // Test shortcuts 12 | var lab = exports.lab = Lab.script(); 13 | var describe = lab.describe; 14 | var before = lab.before; 15 | var it = lab.it; 16 | var expect = Code.expect; 17 | 18 | describe('Hapi Cache Buster', function(){ 19 | 20 | it('busts cache a custom version', function(done){ 21 | 22 | var server = new Hapi.Server(); 23 | server.connection(); 24 | 25 | // Setup the views engine and folder 26 | server.views({ 27 | engines: { 28 | html: require('swig') 29 | }, 30 | path: Path.join(__dirname, './views') 31 | }); 32 | 33 | server.route({ 34 | method: 'GET', 35 | path: '/test', 36 | config: { 37 | handler: function (request, reply) { 38 | reply.view('index'); 39 | } 40 | } 41 | }); 42 | 43 | server.register([ 44 | { 45 | register: cacheBuster, 46 | options: { 47 | version: 55 48 | } 49 | }, 50 | ], function(err){ 51 | expect(err).to.not.exist(); 52 | 53 | server.inject({method: 'GET', url: '/test'}, function(response){ 54 | var $ = Cheerio.load(response.payload); 55 | expect($('h1').text()).to.equal('?v=55'); 56 | done(); 57 | }); 58 | 59 | 60 | }); 61 | 62 | }); 63 | 64 | it('busts cache with package.json version number in the node process current working directory', function(done){ 65 | 66 | var server = new Hapi.Server(); 67 | server.connection(); 68 | 69 | // Setup the views engine and folder 70 | server.views({ 71 | engines: { 72 | html: require('swig') 73 | }, 74 | path: Path.join(__dirname, './views') 75 | }); 76 | 77 | server.route({ 78 | method: 'GET', 79 | path: '/test', 80 | config: { 81 | handler: function (request, reply) { 82 | reply.view('index'); 83 | } 84 | } 85 | }); 86 | 87 | server.register([ 88 | { 89 | register: cacheBuster 90 | }, 91 | ], function(err){ 92 | expect(err).to.not.exist(); 93 | 94 | server.inject({method: 'GET', url: '/test'}, function(response){ 95 | var $ = Cheerio.load(response.payload); 96 | expect($('h1').text()).to.equal('?v=040'); 97 | done(); 98 | }); 99 | 100 | }); 101 | 102 | }); 103 | 104 | }); 105 | -------------------------------------------------------------------------------- /test/views/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |