HMLS
Go from 0 to webapp in seconds.
HMLS gives you, with zero configuration:
- A full blown and easy-to-use web server with a ton of plugins;
hapi
- An awesome view layer via
marko
(easy-to-use taglibs, reusable custom components, et cetera) - Asset bundling (and serving) via
lasso
(complete withless
CSS pre-processing) - Bi-directional communication is as easy as writing a few callbacks with
socket.io
, and is ready to go
hapi
, marko
, lasso
, and socket.io
are extremely efficient and powerful. So HMLS
just wires all of that up for you so that you can be up and running with a webapp in two shakes of a lamb's tail.
HMLS
doesn't "dumb it down" or hide things. The individual components are easily accessed and altered, giving you all of the flexibility that you'd ever need, or at least the same flexibility that you'd have if you wired this together yourself.
HMLS
really represents the VC in MVC.
- Change Log
- Installation
- Scaffolding
- Related Plugins
- Methods, Attributes, and Options
- Events
- Structure and Architecture
- Examples
Change Log
- 2017-12-16 - As of v2.x
HMLS
is fully compatible with Hapi v17.x andasync/await
.
Installation
mkdir <project>
cd <project>
npm init
npm install --save hmls
Then make a few files:
index.js
'use strict' const HMLS = const vc = ! { await vc await vcstart console}
routes/index.js
'use strict' moduleexports = method: 'get' path: '/' { return 'Welcome to the home page!' }
Then node index.js
and visit http://localhost:8080 to see your home page.
Too lazy for that noise?
Check this out, just a one liner that installs everything and starts your project:
$ mkdir my-project && cd my-project && npm i -g hmls && npm init && npm i -S hmls && hmls --scaffold && node index.js
Scaffolding
HMLS
comes with a CLI that can be used to create all of the files and folders (along with small examples) necessary to run immediately.
First create a project and install HMLS
globally:
$ mkdir <project>
$ cd <project>
$ npm init
$ npm install --save hmls
$ npm install --global hmls
Then:
$ hmls --scaffold && node index.js
Simple as that!
Related Plugins
I've written a few hapi
-related plugins that I use all the time, mostly for authorization and authentication:
Methods, Attributes, and Options
new HMLS([options])
Instantiates a new hmls
object. options
has the following defaults:
server: host: 'localhost' port: '8080' lasso: outputDir: path plugins: 'lasso-marko' projectRoot: path routesPath: path assetsPath: path ioPath: path
server
- this object will be passed directly tohapi
's constructor. See https://hapijs.com/api for full options.lasso
- this object will be passed directly tolasso
'slasso.configure()
method.lasso.outpurDir
must be set, at a minimum, this specifies the folder wherelasso
will output bundled resources. It defaults to/static
.HMLS
will automatically useinert
to serve this folder.routesPath
-HMLS
will search this folder, or array of folders, forhapi
routes. More precisely said, it will add each file's exported object tohapi
's route table. ALL files in this folder must export an object, or an array of objects, that arehapi
routes.assetsPath
-HMLS
will serve all files in this folder at/assets
, useful for static resources like images.ioPath
-HMLS
wires upsocket.io
, any file in this folder is expected to export a function with the signaturefunction(io) {}
, whereio
is thesocket.io
instance.
async hmls.init()
Returns: Promise
Initializes everything (hapi
, lasso
, sockets
, et cetera).
If this is not called explicitly it is called in hmls.start()
.
If you want to do things to the individual components prior to starting hapi
(like manually adding routes to hapi
) this is useful.
async hmls.start()
Returns: Promise
Starts the hapi
server, will invoke hmls.init()
if it has not already been invoked.
hmls.server
The hapi
server object.
hmls.lasso
The lasso
instance.
hmls.io
The socket.io
instance.
Events
initialized
Emitted after async hmls.init()
has completed.
started
Emitted after async hmls.start()
has completed. Useful for things like rigging browser-refresh
or other things that require that all of the "initial work" has been done and the app is ready to go.
Structure and Architecture
Hapi
is fantastic at serving static content (well, really any content). Hapi
is the webserver used in HMLS
. You can directly access the hapi
instance with hmls.server
.
Marko
is fantastic at rendering dynamic content. Marko
is used as HMLS
' templating engine.
Lasso
is fantastic at bundling resources together (client JS, CSS, et cetera). You can directly access the lasso
instance with hmls.lasso
.
socket.io
is super neat and allows the client and the server to communicate via websockets.
(see where I am going here?)
All HMLS
really does is wire all of these pieces together, while exposing each piece, so you can get as hardcore with each piece as you like.
Project Structure
/routes
This folder should contain JS files that export hapi
routes. By default it is the routes
folder in your project root. Change this with options.routesPath
.
An example of a trivial route file:
'use strict' moduleexports = method: 'get' path: '/' { return 'I get rendered to the browser!' }
/static
This folder is where lasso
will output bundled resources. By default it is the static
folder in your project root. Change this with options.lasso.outputDir
.
/assets
You can put anything in here that you'd like to be served, like images or other resources. By default it is the assets
folder in your project root. Change this with options.assetsPath
.
/io
All files in this folder will be require
d. It is assumed that each file will export a single function whose one parameter is the HMLS socket.io
instance (accessible anytime via hmls.io
). Then you can do whatever you like via socket.io
. Here's an example of a file in the /io
folder:
'use strict' module { io}
Examples
marko
template
With a simple index.js
'use strict' const HMLS = const vc = vc vcvcstart
pages/slash/index.marko
The current Date is ${input.now}!
routes/slash/index.js
'use strict' moduleexports = method: 'get' path: '/' { const page = return page }
lasso
Bundling assets with You can use lasso
's manifest file (browser.json
) and its taglib in marko
files to bundle assets.
index.js
'use strict' const HMLS = const vc = vc vcvcstart
routes/slash/index.js
'use strict' moduleexports = method: 'get' path: '/' { try const page = return page catch err console return errmessage }
pages/slash/index.marko
/ The current Date is ${input.now}!
pages/slash/browser.json
pages/slash/lib1.js
console;
pages/slash/lib2.js
console;
pages/slash/style.css
Now the page source will look something like this:
/ The current Date is Sun May 14 2017 17:31:37 GMT-0400 (EDT)!
/static/slash-71d36ac2.js
will look like this:
console;console;
Notice that the two JS lib files have been combined into one resource, also notice the jQuery injection.
socket.io
socket.io
is all wired up. To add sockets to HMLS
add JS files to the /io
folder (or whichever folder) set with options.ioPath
.
A trivial file in the /io
folder:
'use strict' module { io}
Then the view (the .marko
file) should include the socket.io
client JS library (simply paste <script src="/socket.io/socket.io.js"></script>
).
For example:
pages/slash/index.marko
/ The current Date is ${input.now}!
io/slash/index.js
'use strict' module { io}
Now you can interact with the server with client JS:
pages/slash/lib.js
var socket = ; socket;
Node console:
server started at http://localhost:8080VwyAfRLa6cSJM3neAAAA connectedsending `greeting` to VwyAfRLa6cSJM3neAAAAVwyAfRLa6cSJM3neAAAA acknowledged `greeting`
Browser console:
received `greeting` from server