ack-reload
Automatically refresh and reload your code in your browser when your code changes. No browser plugins required.
Why?
Restarting your HTTP server and refreshing your browser is annoying.
Table of Contents
- How does it work?
- Benefits of ack-reload over original reload package
- Installation
- Examples
- API
- Commands
- Credits
- License
How does it work?
ack-reload works in three different ways depending on if you're using it:
- Run ack-reload in NodeJs process with full API control using config options
- Use ack-reload middleware to "attach" ack-reload to a existing server route
- As a command line tool which starts its own Server to monitor the file(s) you're editing for changes and to serve
reload-client.js
to the browser.
Once reload-server and reload-client are connected, the client side code opens a WebSocket to the server and waits for the WebSocket to close, once it closes, ack-reload waits for the server to come back up (waiting for a socket on open event), once the socket opens we reload the page.
Benefits of ack-reload over original reload package
ack-reload is a fork of the npm package reload
- Html5Mode
- ack-reload has the option to make all requests root bound
- Original reload package does not play well with html5 routing apps
- onReload option
- Everytime a websocket reload is issued a callback function can be called
- Port already in use prompt aka EADDRINUSE prompt
- Added EADDRINUSE catcher that starts a cli-prompt when desired port is in use. Another port can be supplied to start server on another open port.
- Native Promises
- When starting an ack-reload server via the API, a native promise is returned AFTER all services have been started
- Watching Files
- Watching files is more intuitive and actually available outside of just the CLI
- The original reload package does not auto watch files
- ack-reload does NOT have a name conflict on Ubuntu like reload does
- Better Logging
- Better verbose logging where an outside library can mandate how logging occurs
- Better Client Script Inclusion
- ack-reload package auto appends client script to all html requests
Express app for ack-reload
var reload = require('ack-reload')
var app = express()
var publicDir = path.join(__dirname, 'public')
//Only host reload software. Create websocket to http attachment. File watching
app.use( reload.middleware(publicDir, server) )
http.createServer(app).listen(3000)
Express app for OLD reload
The following code is how the OLD reload app worked
var reload = require('reload')
var app = express()
var publicDir = path.join(__dirname, 'public')
app.get('/', function (req, res) {
res.sendFile(path.join(publicDir, 'index.html'))
})
var server = http.createServer(app)
reload(server, app)
server.listen(3000)
Installation
npm install [-g] [--save-dev] ack-reload
Typical Package Installation
npm install --save-dev ack-reload
Typical Global Installation
npm install -g ack-reload
Examples
Three ways to use ack-reload
There are three different ways to use ack-reload.
- As a server, allowing ack-reload to host your whole project
- As middleware, allowing your exsting server project to utilize ack-reload
- As a command line application to serve up static HTML files and be able to reload when the code is altered
Using ack-reload in Express
When used with Express ack-reload creates a new Express route for reload. When you restart the server, the client will detect the server being restarted and automatically refresh the page.
ack-reload can be used in conjunction with tools that allow for automatically restarting the server such as supervisor (recommended), nodemon, forever, etc.
Stand-Alone Example
Serve and watch a folder all in one
server.js
:
var reload = require('ack-reload')
var publicDir = path.join(__dirname, 'public')
reload(publicDir,{port:3000})
Express Example
Serve and watch a folder on an existing server
server.js
:
var express = require('express')
var http = require('http')
var path = require('path')
var reload = require('ack-reload')
var bodyParser = require('body-parser')
var logger = require('morgan')
var app = express()
var publicDir = path.join(__dirname, 'public')
app.set('port', process.env.PORT || 3000)
app.use(logger('dev'))
app.use(bodyParser.json()) //parses json, multi-part (file), url-encoded
var server = http.createServer(app)
// Reload code only on www url-path from public folder path
app.use("/www" reload.middleware(publicDir, server) )
// Another Reload code here only on admin url-path to admin folder path
var adminPath = path.join(__dirname,'admin')
app.use("/admin", reload.middleware(adminPath, server))
server.listen(app.get('port'), function(){
console.log("Web server listening on port " + app.get('port'));
});
A demo template that has a change with every reload
public/index.html
:
<!doctype html>
<html>
<head>
<title>Reload Express Sample App</title>
</head>
<body>
<h1>Reload Express Sample App</h1>
<br />
<div>Current Time: <script>document.write(Date.now())</script></div>
<br />
<div>Script Time: <script src="www/outputTime.js"></script></div>
</body>
</html>
Manually Reloading
Two ways to approach:
- Manually call returned reload function after starting a ack-reload server
- Integrate the reload function into running middleware
Manually Reloading Application
var publicDir = path.join(__dirname, 'public')
var reload = require('ack-reload')
var options = {
onReload:function(){
console.log('reload occurred at '+new Date().toString())
}
}
reload(publicDir, options)
.then(config=>{
//force reload every 10 seconds of all browser websocket connections
setInterval(config.reload, 10000);
//stop reload services after 30 seconds
setTimeout(function(){
config.httpServer.close()
}, 30000)
})
.catch(function(e){
console.error(e)
})
Manually Reloading With MiddleWare
var publicDir = path.join(__dirname, 'public')
var reload = require('ack-reload')
var server = http.createServer(function(){
midware(req,res)
})
var midware = reload.middleware(publicDir,server)
//force reload every 10 seconds of all browser websocket connections
setInterval(midware.reload, 10000);
//stop reload services after 30 seconds
setTimeout(function(){
server.close()
}, 30000)
Advanced Full Featured Example
require('ack-reload')(__dirname,{
port:8080,
log:console.log.bind(console),
open:true,
message:'reload',
hostname:'127.0.0.1',
filter:function(pathTo, stat){
return stat.isDirectory() || pathTo.search(/\.(js|css|html)$/)>=0
},
startPage:'index2.html'
})
.then(function(config){
//force reload every 10 seconds of all browser websocket connections
setInterval(config.reload, 10000);
//stop reload services after 30 seconds
setTimeout(function(){
config.httpServer.close()
}, 30000)
})
.catch(function(e){
console.error(e)
})
Integrate with Existing App
The following example takes and existing app, builds a new app, and server both together with ack-reload
Preexisting app.js
const express = require('express');
const app = express();
// LOTS AND LOTS OF MIDDLEWARE HERE...
// server is not created since in this module.
app.use((err, req, res, next) => {
// final error handler
});
module.exports = app;
serve.js
const app = require('./app');
const http = require('http');
const reload = require('ack-reload');
//tell ack-reload folder to put watch on
const pathToWwwFiles = require('path').join(__dirname,'www');
//Our server that hosts app and reload code
const server = http.createServer(function(req,res){
if( reload.isRequestForReload(req) ){
midware(req, res)//html or reload.js request
}else{
app(req,res)
}
});
//watch files, create websocket. Return function to process requests
const midware = reload.middleware(pathToWwwFiles, server)
// at this point we have server and app and reload code
server.listen(8888, () => { console.log('started!') });
API
Middlware
var reload = require('ack-reload')
var midware = reload.middleware(pathTo)
require('http').createServer(function(req,res){
midware(req,res)
})
.listen(8080,function(){
if(err){
console.log(err)
}else{
console.log('server started')
}
})
Arguments
-
pathTo
: Folder to watch and serve. Defaults to current dir -
options
:-
port
Number = 8080 - The port to bind to. Can be set with PORT env variable as well. -
log
Function = console.log -
open
Boolean = true - open a browser window -
message
String - when port is in use, tailor prompt messages label -
hostname
String = localhost - This allows for custom hostnames. Defaults to localhost. -
filter
Function - function(pathTo,stat) when function returns true, file will be watched. -
startPage
String - Specify a start page. Defaults to index.html. -
log
Function = console.log - Method to process logging info. -
watch
Boolean = true - Enable/disable watching files. Manual reload will be required -
html5Mode
Boolean = false - Enable/disable always returning root index.html for all html 404 requests -
onReload
Function - Everytime a websocket reload is issued, have a function called
-
Commands
Using ack-reload as a command line application
There are two ways to use the command line application.
- In a directory serving blank static HTML files or
- In a project with a
package.json
file
Each will require different modes of installing.
In case one you should install ack-reload globally with npm install ack-reload -g
. Also with ack-reload installed globally you can go to any directory with an HTML file and use the command reload to constantly watch it and reload it while you make changes.
In case two you should install locally with npm install --save-dev
, since this tool is to aid in development you should install it as a dev dependency.
Navigate to your html directory:
ack-reload -b
This will open your index.html
file in the browser. Any changes that you make will now reload in the browser. You don't need to modify your HTML at all.
Usage for Command Line Application
Example
"scripts": {
"watch:js": "ack-reload --dir ./dist --html5Mode",
}
Usage: ack-reload [options]
Options:
-h, --help Output usage information
-V, --version Output the version number
-b, --browser Open in the browser automatically.
-n, --hostname If -b flag is being used, this allows for custom hostnames. Defaults to localhost.
-d, --dir [dir] The directory to serve up. Defaults to current dir.
-e, --exts [extensions] Extensions separated by commas or pipes. Defaults to html,js,css.
-p, --port [port] The port to bind to. Can be set with PORT env variable as well. Defaults to 8080
-s, --start-page [start-page] Specify a start page. Defaults to index.html.
-v, --verbose Turns on logging on the server and client side. Defaults to true.
--html5Mode Boolean = false - Enable/disable always returning root index.html for all html 404 requests
Credits
This package was originally a fork and pull-request of reload. My pull request turned out to be too large for the reload team to adopt. My pull request is now it's own package published on NPM.
License
(MIT License)
Copyright 2016, JP Richardson jprichardson@gmail.com