This module improves productivity by enabling instant web page refreshes anytime a front-end resource is modified on the server. This module supports live reloading of CSS and JavaScript without doing a full page refresh. This module utilizes the very efficient chokidar module for watching for changes to the file system. Web sockets are used to communicate with the browser. Minimal application code changes are required to benefit from this module.
Like nodemon
, this module provides a drop-in replacement for the node
command.
Compared to nodemon, the browser-refresh
module has the following benefits:
- It starts as a web sockets server and provides a web sockets client
- It sets an environment variable for the spawned child process to let it know that it was launched using
browser-refresh
- Instead of configuring which directories/files to watch, you instead configure which directories/files to not watch using an optional
.browser-refresh-ignore
file (same format as.gitignore
and.npmignore
). - There is an optional taglib for Marko and Dust that injects the
browser-refresh
client if the application was launched usingbrowser-refresh
. Please see: browser-refresh-taglib - The
browser-refresh
process waits for the child process to tell it that it is ready to start serving traffic so that the web browser page is not refreshed too soon. This is done by the child process usingprocess.send('online')
File patterns to ignore are automatically loaded from the first file that exists in the following list:
.browser-refresh-ignore
file in the current working directory.gitignore
file in the current working directory
If no ignore file is found then the following ignore file patterns are used:
node_modules/
static/
.cache/
.*
*.marko.js
*.dust.js
*.coffee.js
NOTE:
Patterns to ignore files with a directory should have /
at the end.
For example, to ignore node_modules
directory use node_modules/
.
First, install the global command line interface for the browser-refresh
module:
npm install browser-refresh -g
Add the following code snippet to the appropriate location based on when your application is ready to start serving traffic:
if (process.send) {
process.send('online');
}
For example:
app.listen(port, function() {
console.log('Listening on port %d', port);
if (process.send) {
process.send('online');
}
});
Alternatively, pass an object that specifies a url
for browser-refresh
to launch the first time your app starts:
if (process.send) {
process.send({ event:'online', url:'http://localhost:8080/' });
}
Finally, add the following script to your page(s). Just before the closing </body>
tag is a good place.
'<script src="{process.env.BROWSER_REFRESH_URL}"></script>'
When
browser-refresh
launches your app a newBROWSER_REFRESH_URL
environment variable is added with the URL that should be used to include the client-side script. The value ofBROWSER_REFRESH_URL
will be similar tohttp://localhost:12345/browser-refresh.js
(the port is random). You should use whatever means your templating language or UI library provides to add the script to your page(s).
If you're using Marko, checkout browser-refresh-taglib
which allows you to simply drop the following tag into your template instead of using the above <script>
tag:
<browser-refresh/>
Some of the features of the browser-refresh
module can be configured by creating
a .browser-refresh
JSON configuration file at the root of your project.
To enable SSL support you must provide values sslCert
and sslKey
in your .browser-refresh
configuration file.
sslCert
: The path to a SSL certificatesslKey
: The path to a SSL key
Example:
{
"sslCert": "server.crt",
"sslKey": "server.key"
}
browser-refresh by default will refresh the active tab after 1500ms
when your Node.js server gets reloaded.
In case if you're server is taking longer time, You can optionally disable the delay
property by setting delay
to false
in the .browser-refresh
config json.
Example:
{
"delay": false
}
Or e.g. 3000 milliseconds
{
"delay": 3000
}
Note: After the server restart, the active page will get reloaded as long as you trigger the online
event on process.send
Example:
app.listen(port, () => {
process.send && process.send('online'); // Process is a child process of browser-refresh
});
You can open up a webpage on server startup by passing a url
property to process.send
Example:
app.listen(port, () => {
process.send && process.send({
event: 'online',
url: 'http://localhost:8080/'
});
});
Once you have installed browser-refresh
using the directions provided above, you can then start your application as normal, except replace node
with browser-refresh
. For example:
# Old: node server.js
# New:
browser-refresh server.js
If the main
property is configured correctly in your application's package.json
then you can simply start your application using the following command:
browser-refresh
The browser-refresh
command will pass all command line arguments to the child process. Therefore, you can pass any number of arguments to your application:
browser-refresh server.js --foo --bar
After launching your application using the browser-refresh
command, you can then load any web page as normal. If the <browser-refresh>
tag (or {@browser-refresh/}
helper) were used then any time a resoure is modified then the application will be restarted and, then, when the server is ready a message will be sent to all of the connected browsers via a web socket connection to trigger a reload of the same web page.
By default, this module does not try to be clever when handling a file modification. That is, by default, a full server restart and a full web page refresh are used whenever any type of file is modified on the server. This ensures that the server state and the client-side page state will always be correct and avoids frustrating edge cases. However, the browser-refresh
module allows for modules to register "special reload" handlers that can short-circuit a full server restart. To disable a full server restart for a particular file pattern, the child process needs to send a message to the browser-refresh
launcher process using the browser-refresh-client module.
For example, to enable special reloading, the following code can be used:
require('browser-refresh-client')
.enableSpecialReload('*.foo *.bar')
.onFileModified(function(path) {
// Handle the modification of either a *.foo file or
// a *.bar file...
});
Both the marko and lasso modules provide support for enabling special reload handlers when using the browser-refresh
module. Example usage:
require('marko/browser-refresh').enable();
require('lasso/browser-refresh').enable('*.marko *.css *.less *.styl *.scss *.sass *.png *.jpeg *.jpg *.gif *.webp *.svg');
To add your own special reload handlers for the browser-refresh
module, please use the following code as a guide:
For improved developer productivity, this module supports refreshing of CSS and images without doing a full page refresh (similar to LiveReload). This is an opt-in feature that can be enabled using code similar to the following:
var patterns = '*.css *.less *.styl *.scss *.sass *.png *.jpeg *.jpg *.gif *.webp *.svg';
require('browser-refresh-client')
.enableSpecialReload(patterns, { autoRefresh: false })
.onFileModified(function(path) {
// Code to handle the file modification goes here.
// Now trigger a refresh when we are ready:
if (isImage(path)) {
browserRefreshClient.refreshImages();
} else if (isStyle(path)) {
browserRefreshClient.refreshStyles();
} else {
browserRefreshClient.refreshPage();
}
});
If you are using require('lasso/browser-refresh').enable(patterns)
, it is doing this for you automatically. Please see: lasso/browser-refresh/index.js
Any flags (arguments that start with -
) before the script path will be passed to the node executable:
browser-refresh --debug index.js
To use Typescript, you will need to require the ts-node register:
browser-refresh --require ts-node/register ./index.ts
- Patrick Steele-Idem (Github: @patrick-steele-idem) (Twitter: @psteeleidem)
- Phillip Gates-Idem (Github: @philidem) (Twitter: @psteeleidem)
Pull requests, bug reports and feature requests welcome.
ISC