live-directory-static
v1.0.7
Published
Use LiveDirectory to create a static file middleware that is super-fast for use with hyper-express.
Downloads
31
Maintainers
Readme
live-directory-static
Before diving in, you should read about LiveDirectory by Kartik to see why you really want to use it!
This module does two things:
- It extends LiveDirectory to be able to take an array of directory paths, because static files can be in multiple directories after all.
- It borrows from modules like serve-static to build the rest of the logic needed to serve static files via LiveDirectory.
Well tested with hyper-express but should in theory work with express too. Let me know if it doesn't.
How to use
const HyperExpress = require('hyper-express');
const webserver = new HyperExpress.Server();
const liveDirectoryStatic = require('live-directory-static');
// options you can add to your static files middleware
// example below includes all the default values
let staticOptions = {
// the default extension to server if path has no extension
defaultExtension: '.html',
// this allows any other methods other than GET to pass through without attempting to serve static files
// static files are only served via GET anyway
fallThrough: true,
// cache directory for templates
// also useful for css minification
cacheDir: path.resolve(module.parent.path, '.cache'),
// used to determine what static content optimizations we want
optimize: {
css: true,
removeUnusedCss: true,
},
// The next options are used by optimized-live-directory
// Which is used by this module to keep files highly optimized
// This option helps us control how much memory we let LiveDirectory Gobble up.
// If you have 1 million static file, you don't want all of them on memory
memory: {
// maximum memory we will allow live directory to use
maxUsed: '500mb',
// maximum size of file we load into live directory
bufferLimit: '500kb',
},
// Filters help to determine which files we accept/whitelist for Live Directory
filter: {
// because we handle css optimizations via purgecss, we don't optimize here
extensions: [
'.js',
// '.css',
'.png',
'.jpg',
'.jpeg',
'.gif',
'.svg',
'.webp',
'.html',
],
},
// Details on how various static files are minified
minify: {
// minify html
html: {
collapseWhitespace: true,
conservativeCollapse: true,
continueOnParseError: false,
keepClosingSlash: true,
removeComments: true,
removeScriptTypeAttributes: true,
sortAttributes: true,
sortClassName: true,
},
// minify css with default options
css: {},
// js is null because we do not minify javascript by default.
js: null,
// optimize svg using defaults
svg: {},
// optimize png
png: {
quality: [0.6, 0.8],
},
// optimize jpg
jpg: {},
// optimize gif
gif: {
optimizationLevel: 3,
},
},
};
// set it before any routes
webserver.use(
liveDirectoryStatic(['path/to/dir1', 'path/to/dir2'], staticOptions)
);
// Create GET route to serve 'Hello World'
webserver.get('/', (request, response) => {
response.send('Hello World');
});
// Activate webserver by calling .listen(port, callback);
webserver
.listen(80)
.then((socket) => console.log('Webserver started on port 80'))
.catch((error) => console.log('Failed to start webserver on port 80'));
The magic of using live-directory-static & live-directory-views
These two modules were built to work together with hyper-express. Used together they are able to achieve something magical in optimizing your site! As if HyperExpress wasnt fast enough already! :)
Cacheing : the two modules extensively use p-memoize to cache any long-ish operations.
css super minification : Css minification has two inportant steps:
- Removing all unused css. This is a huge problem for many
- Minifying the final css file
As you might expect, minifying is the simpler task. Removing unwanted css is much more difficult! That is because you have to account for all the pages that the css file is included or else some pages will not display properly.
By using live-directory-static & live-directory-views together and setting them to use the same
cacheDir
, you let theme achieve some magic. Here is how it works.- live-directory-views generates the views and keeps them updated via live-directory.
- But it also writes and updates actual cache files corresponding to each page rendered.
- When the page then loads it's static resources live-directory-static kicks in and starts rendering static files off live-directory.
- For each css file, it checks all the views that request that css file and then using purgecss removes all css that won't be used by any of the views/pages. That process is memoized cleverly so that should either the css file or the view files change, then it will be regenerated.
- This css is then minified.
- What is truly magical about this is that you can build your site without fearing or caring about css ballooning in size. Any newly used css selectors will be added to the css generated and that process memoized till the next change.
Using this method, I reduced some generic template file from 500kb to serving only 42kb of css!
Activating this magic!
Simply use both middleware and let them share a cache directory.
const HyperExpress = require('hyper-express');
const webserver = new HyperExpress.Server();
const path = require('path');
const os = require('os');
const liveDirectoryViews = require('live-directory-views');
const liveDirectoryStatic = require('live-directory-static');
// let us cache somewhere off the app folder
// if not set, default cacheDir is path.resolve(module.parent.path, '.cache')
// if directory is missing, an attempt to create one is made
const templateCacheDir = path.join(os.homedir(), 'templates-cache');
let staticOptions = {
//...other options
cacheDir: templateCacheDir,
};
//static files middleware
webserver.use(
liveDirectoryStatic(['path/to/dir1', 'path/to/dir2'], staticOptions)
);
//
let viewOptions = {
//...other options
cacheDir: templateCacheDir,
};
// views middleware
webserver.use(liveDirectoryViews(viewOptions));
// Render the template using .render() method
webserver.get('/', (request, response) => {
// this method is added the the middleware
// so dont go looking for it from hyper-express
response.render('user.pug', { name: 'Anthony Mugendi' });
});
// Activate webserver by calling .listen(port, callback);
webserver
.listen(80)
.then((socket) => console.log('Webserver started on port 80'))
.catch((error) => console.log('Failed to start webserver on port 80'));