Skip to content

Commit

Permalink
tweaks and rework
Browse files Browse the repository at this point in the history
  • Loading branch information
shannonmoeller committed Oct 11, 2020
1 parent a9ea2fe commit f11956a
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 58 deletions.
31 changes: 18 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![NPM version][npm-img]][npm-url] [![Downloads][downloads-img]][npm-url]

A simple static-file server with live reload support for development. The word itself derives from the French _livrée_, meaning _dispensed_ or _handed over_.
Minimal development server to watch and dispense static files.

## Install

Expand All @@ -15,42 +15,47 @@ $ npm install --global livery
## Usage

```man
Usage: livery [options] [path]
lr [options] [path]
Usage: livery [<options>] [--] [<dir>]
lr [<options>] [--] [<dir>]
Options:
-d, --delay Debounce delay for reloads. (default: 250)
-g, --glob Glob of files to watch. (default: '**/*.*')
-h, --help Output usage information.
-l, --live LiveReload server port. (default: 35729)
-p, --port HTTP server port. (default: 3000)
-s, --spa Single-page app. If string, path to html. (default: false)
-w, --watch Glob or globs of files to watch. (default: '**/*.*')
Examples:
$ lr
$ lr src
$ livery --glob 'src/**/*.*' --glob 'test/**/*.js' --spa -- dist
$ livery --delay 1000 --spa /spa.html
$ lr -p 8080 public
$ livery --watch 'src/**/*.*' --watch 'test/**/*.js' dist
$ livery --spa -- static
$ livery --spa app.html
```

## API

### `livery([options]): Object`
### `livery([dir, [options]]): Object`

- `dir` `{String}` Directory of static files. (default: `.`)
- `options` `{Object}`
- `delay` `{Number}` Debounce delay for reloads. (default: `250`)
- `glob` `{String|Array}` Glob or globs of files to watch. (default: `**/*.*`)
- `port` `{Number}` HTTP server port. (default: `3000`)
- `httpPort` `{Number}` HTTP server port. (default: `3000`)
- `livePort` `{Number}` LiveReload server port. (default: `35729`)
- `spa` `{Boolean|String}` Single-page app. If string, path to html. (default: `false`).
- `watch` `{String|Array}` Glob or globs of files to watch. (default: `**/*.*`)

Starts an HTTP server, LiveReload server, and file watcher.

```js
const livery = require('livery');
const { httpServer, liveServer, watcher } = livery({
const { httpServer, liveServer, fileWatcher } = livery({
delay: 250,
glob: '**/*.*',
port: 3000,
httpPort: 3000,
livePort: 35729,
spa: false,
watch: '**/*.*',
});
```

Expand Down
23 changes: 12 additions & 11 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,39 @@ import minimist from 'minimist';
import livery from './index.js';

const usage = `
Usage: livery [options] [path]
lr [options] [path]
Usage: livery [<options>] [--] [<dir>]
lr [<options>] [--] [<dir>]
Options:
-d, --delay Debounce delay for reloads. (default: 250)
-g, --glob Glob of files to watch. (default: '**/*.*')
-h, --help Output usage information.
-l, --live LiveReload server port. (default: 35729)
-p, --port HTTP server port. (default: 3000)
-s, --spa Single-page app. If string, path to html. (default: false)
-w, --watch Glob or globs of files to watch. (default: '**/*.*')
Examples:
$ lr
$ lr src
$ livery --glob 'src/**/*.*' --glob 'test/**/*.js' --spa -- dist
$ livery --delay 1000 --spa /spa.html
$ lr -p 8080 public
$ livery --watch 'src/**/*.*' --watch 'test/**/*.js' dist
$ livery --spa -- static
$ livery --spa app.html
`;

const args = minimist(process.argv.slice(2), {
alias: {
d: 'delay',
g: 'glob',
h: 'help',
p: 'port',
l: ['live', 'livePort'],
p: ['port', 'httpPort'],
s: 'spa',
w: 'watch',
},
boolean: ['help'],
string: ['glob'],
});

if (args.help) {
console.log(usage.trim());
} else {
livery(args);
livery(args._[0], args);
process.stdin.pipe(process.stdout);
}
3 changes: 3 additions & 0 deletions example/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<!doctype html>
<title>App</title>
<p>Spa day!</p>
2 changes: 1 addition & 1 deletion test/index.html → example/index.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!doctype html>
<title>Hello</title>
<title>Index</title>
<p>You look nice today.</p>
70 changes: 44 additions & 26 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import http from 'http';
import os from 'os';
import path from 'path';
import chokidar from 'chokidar';
import ip from 'ip';
import send from 'send';
import tiny from 'tiny-lr';

const cwd = process.cwd();
const interfaces = os.networkInterfaces();

function debounce(fn, ms) {
let timer;

Expand All @@ -14,10 +17,28 @@ function debounce(fn, ms) {
};
}

export default function livery(options) {
const { delay = 250, glob = '**/*.*', port = 3000, spa } = options || {};
const address = ip.address();
const root = path.join(process.cwd(), options._[0] || '.');
function getIpAddress() {
const values = Object.values(interfaces).flat();

for (const { address, family, internal } of values) {
if (family === 'IPv4' && !internal) {
return address;
}
}
}

export default function livery(dir = '.', options = {}) {
const {
delay = 250,
httpPort = 3000,
livePort = 35729,
spa = false,
watch = '**/*.*',
} = options;

const rootPath = path.join(cwd, dir);
const spaPath = spa === true ? 'index.html' : spa;
const address = getIpAddress();

// HTTP Server

Expand All @@ -26,25 +47,23 @@ export default function livery(options) {

function serveSpa(error) {
const isSpa =
spa &&
spaPath &&
error.statusCode === 404 &&
req.headers.accept.includes('html');

if (isSpa) {
const url = spa === true ? '/index.html' : spa;

send(req, url, { root }).pipe(res);
send(req, spaPath, { root: rootPath }).pipe(res);
} else {
res.statusCode = error.statusCode || 500;
res.end();
}
}

send(req, req.url, { root }).on('error', serveSpa).pipe(res);
send(req, req.url, { root: rootPath }).on('error', serveSpa).pipe(res);
});

httpServer.on('error', console.error);
httpServer.listen(port);
httpServer.listen(httpPort);

// LiveReload Server

Expand All @@ -54,37 +73,36 @@ export default function livery(options) {
});

liveServer.on('error', console.error);
liveServer.listen(35729);
liveServer.listen(livePort);

const reload = debounce(() => {
function reload() {
console.log('RELOAD');
Object.keys(liveServer.clients).forEach((id) => {
liveServer.clients[id].reload(['*']);
});
}, delay);

for (const client of Object.values(liveServer.clients)) {
client.reload(['*']);
}
}

// File Watcher

const watcher = chokidar.watch(glob, {
const fileWatcher = chokidar.watch(watch, {
ignored: '**/node_modules/**',
ignoreInitial: true,
persistent: true,
});

watcher.on('error', console.error);
watcher.on('add', reload);
watcher.on('change', reload);
watcher.on('unlink', reload);
fileWatcher.on('error', console.error);
fileWatcher.on('all', debounce(reload, delay));

// Report

console.log(`HTTP: http://${address}:${port}`);
console.log(`Live: http://${address}:35729`);
console.log(`Watch: ${glob}`);
console.log(`HTTP Server: http://${address}:${httpPort}`);
console.log(`Live Server: http://${address}:${livePort}`);
console.log(`File Watcher: ${watch}`);

return {
httpServer,
liveServer,
watcher,
fileWatcher,
};
}
5 changes: 0 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "livery",
"version": "3.3.0",
"description": "Minimal dev server to dispense static files.",
"description": "Minimal development server to watch and dispense static files.",
"author": "Shannon Moeller <me@shannonmoeller> (http://shannonmoeller.com)",
"repository": "shannonmoeller/livery",
"license": "MIT",
Expand All @@ -22,7 +22,6 @@
},
"dependencies": {
"chokidar": "^3.4.2",
"ip": "^1.1.5",
"minimist": "^1.2.5",
"send": "^0.17.1",
"tiny-lr": "^2.0.0"
Expand Down

0 comments on commit f11956a

Please sign in to comment.