Skip to content

Commit

Permalink
feat: add browser-reload plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
nickreese committed Sep 2, 2020
1 parent d62bf5a commit 6479bf8
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 2 deletions.
40 changes: 40 additions & 0 deletions packages/browser-reload/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Elder.js: Browser Reload

Designed to work with the [Elder.js Template](https://github.com/Elderjs/template/) and integrate browser reloading.

It works by adding a websocket on bootstrap. It then sets up a listener to that websocket on the client.

When the server is restarted due to a code change, the browser will restart as well.

## Install

```bash
npm install --save @elderjs/browser-reload
```

## Config

Once installed, open your `elder.config.js` and configure the plugin by adding `@elderjs/browser-reload` to your plugin object.

```javascript
plugins: {
'@elderjs/browser-reload': {} // activates the plugin
}
```

## Customizing the Defaults

Below are the default settings of the plugin. You can adjust them to your needs.

```javascript
plugins: {

'@elderjs/browser-reload': {
port: 8080, // the port the websocket server should run on.
delay: 200, // the delay in ms the browser should wait after the server disappears.
preventReloadQS: 'noreload', // if 'noreload' is in the query string it won't reload that page. Good for CSS editing in the browser.
retryCount: 50, // number of tries the browser will check to see if the server is up before giving up.
},

}
```
101 changes: 101 additions & 0 deletions packages/browser-reload/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
const plugin = {
name: 'elderjs-plugin-browser-reload',
description:
'Polls a websocket to make sure a server is up. If it is down, it keeps polling and restarts once the websocket is back up. Basically reloads the webpage automatically. ',
init: (plugin) => {
// used to store the data in the plugin's closure so it is persisted between loads

const notProd = process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'PRODUCTION';

plugin.run = !plugin.settings.build && notProd;
if (plugin.run) {
plugin.ws = require('http').createServer();
plugin.io = require('socket.io')(plugin.ws);

plugin.io.on('connection', (client) => {
client.emit('hi', true);
});
plugin.ws.listen(plugin.config.port);
}

return plugin;
},
config: {
port: 8080,
delay: 200,
preventReloadQS: 'noreload',
retryCount: 50,
},
hooks: [
{
hook: 'stacks',
name: 'addWeSocketClient',
description: 'Adds websocket logic to footer.',
priority: 50,
run: ({ customJsStack, plugin }) => {
if (plugin.run) {
customJsStack.push({
name: 'socksjs',
string: `
<script>
function wait(){
return new Promise((resolve)=>{
setTimeout(() => {
resolve();
}, ${plugin.config.delay});
});
}
async function checkServer(tryCount = 0){
var up = await fetch('http://localhost:3000');
if(up.ok) return true;
if(tryCount > ${plugin.config.retryCount}){
return false;
}
await wait();
return checkServer(tryCount+1);
}
var socketio = document.createElement("script");
socketio.src = "https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js";
socketio.rel = "preload";
socketio.onload = function() {
if(document.location.search.indexOf('${plugin.config.preventReloadQS}') === -1){
var disconnected = false;
var socket = io('http://localhost:${plugin.config.port}');
socket.on('connect', async function() {
if (disconnected) {
console.log('reloading');
const serverUp = await checkServer();
if(serverUp){
window.location.reload();
disconnected = false;
} else {
console.error('Reloading failed after ${plugin.config.retryCount} retries to connect.')
}
}
});
socket.on('hi', function(data) {
// console.log('hi', data);
});
socket.on('disconnect', function() {
// console.log('disonnected');
disconnected = true;
});
}
};
document.getElementsByTagName('head')[0].appendChild(socketio);
</script>`,
});
return {
customJsStack,
};
}
},
},
],
};

module.exports = plugin;
exports.default = plugin;
32 changes: 32 additions & 0 deletions packages/browser-reload/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@elderjs/plugin-sitemap",
"version": "0.0.7",
"description": "Easily generate a sitemap for your Elder.js powered website.",
"keywords": [
"elder.js",
"elderjs",
"svelte",
"ssg",
"static",
"browser",
"reload",
"dev"
],
"author": "Nick Reese <npm@nicholasreese.com>",
"homepage": "https://elderguide.com/tech/elderjs/",
"license": "MIT",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/Elderjs/plugins.git"
},
"scripts": {
"test": "echo \"Error: run tests from root\" && exit 1"
},
"bugs": {
"url": "https://github.com/Elderjs/plugins/issues"
},
"dependencies": {
"socket.io": "^2.3.0"
}
}
2 changes: 1 addition & 1 deletion packages/critical-path-css/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const fs = require('fs-extra');
const path = require('path');

const plugin = {
name: 'elder-plugin-critical-path-css',
name: 'elderjs-plugin-critical-path-css',
description: `Easily generate critical path css for your Elder.js websites using [critical](https://github.com/addyosmani/critical).
While Svelte does a great job of scoping CSS usually you'll have a site wide css file to hold common styles.
Expand Down
2 changes: 1 addition & 1 deletion packages/sitemap/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function formatDate(date) {
const defaultSitemapDate = new Date(Date.now());

const plugin = {
name: 'elder-plugin-sitemap',
name: 'elderjs-plugin-sitemap',
description: 'Builds a sitemap for all pages on your site.',
init: (plugin) => {
// most of the bootstrap is not due to init() not being async.
Expand Down

0 comments on commit 6479bf8

Please sign in to comment.