A middleware generator for compiling and saving static resources. Use with Express. Resave is a low-level middleware generator, here are some derivative projects:
- Resave Browserify - A middleware for compiling and saving Browserify bundles
- Resave Sass - A middleware for compiling and saving Sass files
const express = require('express');
const resave = require('resave');
const app = express();
const resaver = resave(async ({sourcePath, options}) => {
// ... do something with the source path and options ...
return 'some content';
})
app.use(express.static('public'));
app.use(resaver({}));
app.listen(3000);
This library requires the following to run:
- Node.js 12+
Install with npm:
npm install resave
Load the library into your code with a require
call:
const resave = require('resave');
Create a resaver, this should be a function which accepts a file path and some options, and returns a Promise
. Using async functions is the easiest way to do this. The following resaver will load the bundle file, replace words inside it based on some options, and then callback with the result:
const replaceWords = resave(async ({sourcePath, options}) => {
let content = await fs.promises.readFile(sourcePath, 'utf-8');
Object.keys(options.words).forEach(word => {
const replace = options.words[word];
content = content.replace(word, replace);
});
return content;
});
Now you can use the created middleware to serve up files:
const express = require('express');
const app = express();
app.use(replaceWords({
bundles: {
'/example.txt': 'source/example.txt'
},
words: {
hello: 'ohai',
world: 'planet'
}
}));
In the example above, requests to /example.txt
will load the file /source/example.txt
, replace the configured words inside it, and serve it up.
This isn't great in production environments, your resaver function could be quite slow. In these cases you can save the output to a file which will get served by another middleware:
const express = require('express');
const app = express();
app.use(express.static('public'));
app.use(replaceWords({
bundles: {
'/example.txt': 'source/example.txt'
},
savePath: 'public'
words: {
'hello': 'ohai',
'world': 'planet'
}
}));
In the example above the first time /example.txt
is requested it will get compiled and saved into public/example.txt
. On the next request, the static
middleware will find the created file and serve it up with your configured caching etc.
Create a resaver with a passed in createBundle
function:
const renderer = resave(async bundleDetails => {
// ...
});
The createBundle
function should accept one argument which is an object. This object will have the following properties:
options (object)
: The options object passed into the middlewarerequestPath (string)
: The request path that lead to this bundle being generatedsourcePath (string)
: The full path to the source file to create a bundle fromsavePath (string)
: The full path where the file will be saved. Ornull
if no file will be saved
It must return a Promise
which resolves with a string representing the bundle contents.
The middleware functions returned by a resave
call can be used with Express, and they must be called with an options object:
app.use(renderer({
// options go here
}));
As well as the core options, your Resave middleware can use any other options that you define. You should document your own options if you build libraries with Resave.
The directory to look for bundle files in. Defaults to process.cwd()
.
A map of bundle URLs and source paths. The source paths are relative to the basePath
option. In the following example requests to /foo.css
will load, compile and serve source/foo.scss
:
app.use(resaver({
basePath: 'source'
bundles: {
'/foo.css': 'foo.scss'
}
}));
An object which implements the methods error
and info
which will be used to report errors and request information.
app.use(resaver({
log: console
}));
The directory to save bundled files to. This is optional, but is recommended in production environments. This should point to a directory which is also served by your application. Defaults to null
.
Example of saving bundles only in production:
app.use(resaver({
savePath: (process.env.NODE_ENV === 'production' ? 'public' : null)
}));
A basic resave middleware which replaces words in a text file.
node example/basic
To contribute to this library, clone this repo locally and commit your code on a separate branch. Please write unit tests for your code, and run the linter before opening a pull-request:
make test # run all tests
make verify # run all linters
Licensed under the MIT license.
Copyright © 2020, Rowan Manning