wam.js
Wam is a small koa and next.js inspired middleware framework for node the following block of code is a quick run down on what Wam supports out of the box, following that i will try to explain the details of it all.
const Wam = ; const app = ; // on the fly(as opposed to cached) compression i.e json requestsapp; // serve static files, cached compressionapp; // component architecture v1 (directory)app; // component architecture v2 (custom mappings)app; // middlewareapp; // route for GET methods on /user/:idapp; // route for ALL methods on /user/:idapp; // start serverapp;
Application
When you execute new Wam()
a new application is created.
This application object is the main point of entry for communicating with Wam api's. The following is the shape of the object returned by new Wam()
;
use listen callback create error static compress router components statuses mimes
Use
app.use
is used to push a middleware to the stack where context is
the object exposing the request and response objects and next is a
function that is used to jump to the next middlware in the chain.
app;
Since routes are just middlwares the app.use
function
doubles as a route register when the first argument is a String/RegExp
app;
As you may have notices a method has not been specified for the request. When left blank the method resolves to handling all methods of that route but you could also be explicit about it and do the following
app;
If you wanted to be very explicit with routes you could also do the following, which is how Wam handles this under the hood.
app
Listen
Creates a server and starts listening for requests on the port 3000
app; // this is just a short hand of what is internally being handled ashttp;
Static
Creates a middleware that handles requests for static files
// the following will do a couple of thingsapp;
First it will resolve to the folder and create a tree of all the assets that residing, in the process this will also gzip any compressible assets using file type and file size as an indicator. The results of the above are cached - paths, file stats, and gzip payloads.
When a request is received the middleware will try to determine if the request is for a static asset, if it is and the resource is available, and the body has not been set it will serve the compressed asset as a stream and assign all the necessary headers.
Note that following this flow successfully will result in middlewares after the Static to be bypassed when a static file is request, found and served.
When not in a production enviroment the static files are watched for changes and updated as needed.
Components
Creates a middleware for all the components/files found in the specified directory and passing any dependencies if any the returned function is called like any other middleware when the components route is matched.
// index.jsapp; // examples/views/index.jsmodule { return { thisbody = id; }} // when a request is made to `/` the function// returned in `examples/views/index.js` will handle it.// the step of calling next is handled internally// if next is not specified as an argument of the middlware.
You could also be more specific and pass an object of the files - to - route matches to be used, for example...
app;
Compress
Creates a middleware that provides on the fly(non cached) compression
for example for json requests. If you wanted to serve static content
use Static
instead.
app;
Context
The context
object and next
function are the two arguments passed to every middlware function. We will start with context and what you can do with it, though if you've used Koa before you are probably familiar with this.
response: // methods is: types get: name set: name value remove: name // getters and setters type: getter|setter body: getter|setter length: getter|setter message: getter|setter status: getter|setter header: getter lastModified: getter|setter socket: getter writable: getter headerSent: getter etag: getter|setter request: // methods is: get: // getters and setters header: getter url: getter|setter method: getter|setter path: getter|setter query: getter|setter querystring: getter|setter search: getter|setter origin: getter href: getter ext: getter socket: getter length: getter protocol: getter secure: getter type: getter host: getter ips: getter // aliased to response remove set status message body length type lastModified etag headerSent writable // aliased to request accepts get is querystring socket search method query path url origin href protocol host hostname header secure ext ips
Next
The next
function is a central piece that connects middlewares together, though unlike Koa
the next function accepts an optional argument that is used internally but one that you could make use of when needed.
app; app; app;
Under The Hood
-
Wam checks if a stream has a _type property to determine and set the response type if it has one.
-
stores caches for the
.static
middlware in the directory provided within a.cache
folder. This cache is updated as needed i.e if an asset is removed its gzipped resource is also removed, though this syncing is only in place when not inproduction
mode. -
If your filesystem supports the
/
characters in filenames then you could potentially create a routing solution with just theapp.components()
middleware.
Intergration
Wam can be used as a general solution with the above listed api's
but really shines when coupled with Dio.js and the app.components()
api, in part inspired by next.js.
Note that the below will also work when used with any other vdom library
making use of something like renderToString/renderToStream
meaning you can do the exact following with React, Preact and Inferno
minus the renderToCache
, and stylesheet
.
// views/index.jsmodule { { return } { return ; } { return ` { color: black; border: 1px solid red; padding: 10px; } ` } { return ; } { return } ; return ctxbody = ;} // index.jsconst app = 'wamjs'; app;app;