A better toolkit for building awesome websites and apps
A better toolkit for building awesome websites and apps
asimov.js is at its core only two simple things: a command line interface that loads and executes command scripts in your project and
node_modules folder, and a plugin interface for adding initializers and extend the app lifecycle.
On it's own, asimov.js doesn't really do much - it leaves all the heavy lifting to plugins. The two most basic ones are asimov-server and asimov-static. Together you get an awesome static site generator with extendable, chained processing and a high-performance clustered server, with express-compatible middleware.
Or you roll your own plugin in a just a few seconds.
Install asimov.js globally to use the cli
npm install -g asimov
Start your project and execute any registered initializers. This assumes your
index.js exports a member function called
start. More on that later.
And any other command, you execute the same way. Later in this guide, you'll learn to build a command that counts lines of code.
So let's create our very first asimov.js app, a tiny thing that will load an initializer that logs a message.
Every app is also a plugin, meaning you can easily compose large applications from lots of smaller pieces of functionality, or publish your app to npm and let others use it as a plugin.
Install and add asimov.js to your projects dependencies.
$ npm install --save asimov
logMessage.js should export an initializer, a function that is passed a
next function, which continues the chain.
// lib/init/logMessage.jsmoduleexports =console.log"Hello world";next;;
Then, we add some bootstrap code in
var asimov = require'asimov';var logMessage = require'./lib/init/logMessage';// This is our plugin hook, the function that other modules// can use to load our modules functionalitymoduleexports =asimovinitlogMessage;;// The "start" method should bootstrap your app// by adding the plugin hook and starting asimov.jsmoduleexportsstart =asimovusemoduleexportsstart;;// If we are not loaded as a plugin, start the appmoduleparent || moduleexportsstart;
And run it...
$ asimov> Hello world
asimov is short for
asimov start, which is actually just calling
Every asimov.js app is also a plugin, and has the same interface as our app. In our projects plugin hook, we add all the plugins we need to get the job done. If we published the project above, we could add it in our next projects
var logger = require'asimov-log-message';moduleexports =asimovuselogger;;
Plugins can configure your app, add initializers and extend the public interface of
asimov with new methods.
Development plugins that shouldn't be included when you app is loaded as a plugin are added in the bootstrap function.
var debuggerPlugin = require'asimov-some-debugger-plugin';moduleexportsstart =asimovusemoduleexportsusedebuggerPluginstart;;
Initializers come in three flavours: vanilla, pre and post. For most apps and plugins, vanilla initializers will be enough, but in some case you might need to override the entire vanilla chain.
var overrider = require'./lib/init/overrider';moduleexports =asimovpreinitoverrider;;
If you want your initializer to be executed last, register it with
var doneLogger = require'./lib/init/doneLogger';moduleexports =asimovpostinitdoneLogger;;
Remember, you can break the chain at any time by not calling
next() in your initializer, and create new, alternate chains. For example, this is how asimov-server can be used as both cluster master and worker, by having two very different chain of initializers.
Let's say we want to extend asimov.js with a new command that counts the lines of code in the
lib folder. We could later publish it to npm, and use it in other asimov.js projects as a plugin.
Create a new module structure, and add
lib/commands/loc.js - it will be loaded when you call
If you publish this on npm, any other project that installs it to their
node_modules folder will have the command
asimov loc available, unless they create
lib/commands/loc.js in their project.
You can change the behavior of plugins and configure your app with the
// Set a configuration variable. Chainable.asimovconfig'myConfigVar' true;// And get it.var myVar = asimovconfig'myConfigVar';// Or get the whole config object.var myConfig = asimovconfig;// Also supports constants, just uppercase the name.// Trying to set it again will throw an error.asimovconfig'SOMETHING_CONSTANT' true;// Use an object literal, or a JSON file. Also chainable.var production = require'./env/production.json';asimovconfigproduction;
Out of the box, asimov.js supports zero-downtime updates with "rolling restarts", using POSIX signals.
For your convience, the master process' PID is saved in
process.pid in your project root. This file is created when you start your app, removed when you stop it and can be used to send signals to asimov's master process.
To reload all code and restart your app, send SIGHUP to the master process.
$ kill -HUP $(cat process.pid)
You can register functions that will be executed when your app is being restarted or forcefully shutdown. These work exactly the same way as initializers, are executed in sequence and you can change or override the chain of side effects by not calling the
asimovshutdown// do some cleanup herenext;;
Your app or plugin could need to register methods or variables on
asimov's public interface. Chainable method.
For example, this is how asimov-pages exposes its main collection as
To get detailed logging on everything that happens in your app and plugins, set the env var
VERBOSE to true. Or take the shortcut, call
- First, fork this repo.
- Implement something awesome
- Write tests and run them with
- Submit a pull request