
Despite notable successes,
Node.js is still a specialized technology, which mostly closes bottlenecks in systems written in a different technology stack. The reason for this situation lies in the fact that the node itself does not have many libraries that we are used to in other languages ​​and which provide rapid development of application software. For example, in order to separate handlers for different URLs in the code, give static files, organize sessions, run multiple threads, have access to the database, cache data in memory, differentiate user rights, have logs and rotate them, create a network API, render templates , configure URL-rewriting, provide fast delivery of events from the server to clients, for all of this, and many other tasks, separate libraries (modules) are used. Different modules are written by different developers, difficult to fit, conflict. In general, we decided to combine all this set of required functionality in virtually every web application into one application server and thus increase code connectivity, make the application server core monolithic and more consistent than solutions compiled from separate libraries . The
Impress project has already been
announced as a prototype , and now it provides the entire necessary arsenal for rapid application development, which has been tested on a dozen live projects. Impress differs significantly from another widely used platform, just as impressionism differs from expressionism, that is, it produces a holistic, well-thought-out aesthetic impression, as opposed to a sudden outburst of emotions. But we, without being involved in the criticism of someone else's code, proceed to the demonstration of the design features of Impress.
Some code metrics
- Impress kernel size (with maximum code connectivity) /lib/impress.js - 44Kb
- The size of the whole Impress code (with high connectivity, but not obligatory connection) / lib / * - 110Kb
- The size of external libraries (with optional loading), all that in / node_modules is 56MB
- Of these, the geoip-lite module with its database is 40MB.
- Method of loading kernel libraries: exotic (described here - JavaScript Patterns of modules in Impress for node.js and browsers ).
- Project age : 3½ months (before that, another month as a prototype, before publication in npm and github).
- Intensity of development : during this time 47 versions were released, i.e. something is done every 2-3 days.
- Dependencies (currently): async , cluster , colors , mkdirp , mongodb , mysql , memcached , nodemailer , geoip-lite , uglify-js , multiparty , iconv-lite .
Capabilities and applications
- Creating multipage web applications , that is, with a server templating engine (built into the kernel) and with page overload.
- Creation of one-page web applications with data exchange between the browser and server API using AJAX, with transfer of HTML or JSON fragments, for dynamic restructuring of the client screen from them.
- Creating hybrid solutions where one-page and multi-page approaches are mixed.
- Development of a network API for cross-server and client-server interaction, including with browsers, mobile applications for iOS, Android, etc.
- Offline HTML5 applications with cache.manifest , local storage in IndexedDB or WebSQL and the ability to work both online and offline, offline. This is not an Impress task, of course, but there is experience in applying even in such an atypical case.
- Servicing multiple domains with a single application server (including by mask), i.e. The mechanism for setting up virtualkhosta components of a single application or launching on them different applications (both on the same and on different ports).
- Call forwarding to other servers and ports (reverse-proxy) with url-rewriting support, configuring URL routing in config.js in JSON format and using templates and regular expressions. Forwarding can be combined with processing part of calls in the application server. With the help of forwarding, you can assemble one application from several languages, servers and technology stacks.
- Static feedback with in-memory caching, minification of static browser-based js files, gzip compression for compressible formats and correct HTTP 304 (Not Modified) return when receiving the “if-modified-since” header.
- There is a built -in authentication system and provider for storing users in MongoDB.
- There is a built -in session system with storing them in RAM, storing in MongoDB, restoring sessions when restarting. It is possible to do unauthenticated sessions, i.e. identify and store user status without registration.
- The ability to work in several processes with the support of several strategies for distributing tasks to processes and implementing the interaction between them through IPC (in the future we plan to use ZeroMQ for these purposes and transparent scaling to several servers). Messaging is used if you want to establish interaction between clients connected to different server processes.
- The implementation of two ways of sticking sessions to processes: “IP sticky” (sticking on IP) or “cookie sticky” (sticking on cookies, used in conjunction with an external balancer and port multiplexing). This allows all connections from the same IP or the same cookie to re-request (after authentication) again to the same process that stores their session (state).
- Logging requests with the establishment of a new file every day and the removal of old files (set a limit to the stored history).
- The work on the CMS , which is already built into the Impress core, is coming to an end and will soon get an admin interface for editing pages.
Well, and those opportunities that I will not detail, because
Already wrote about them and their better look on examples:
- URL routing based on file system (mapping URLs to directories).
- Caching server-side JavaScript and templates in RAM.
- The ability to change the application code without rebooting the main application (the process monitors the change of files on the disk.
- Several launch strategies: multiple, single, specializatio, sticky.
- Ability to change the config without completely restarting the main application (the process monitors the change of the config.js file).
- Support for SSE (Server-Sent Events) with event transmission system from the server (in the PUSH style) through an open connection to the client part without constant requests from the client (in the PULL style).
Add-on MySQL access driver:
- Convenient data access methods: queryRow, queryValue, queryArray, queryHash, queryKeyValue, count. Examples of use: https://github.com/tshemsedinov/impress/wiki/MySQL-Data-Access-Methods
- Methods of introspection of utility database structures (obtaining metadata from a database): primary, foreign, constraints, fields, databases, tables, tableInfo, indexes, processes, globalVariables, globalStatus, users. Examples of use: https://github.com/tshemsedinov/impress/wiki/MySQL-Introspection-Methods
- Methods for autogenerating SQL queries: where, select, update, insert, upsert, delete. Examples of use: https://github.com/tshemsedinov/impress/wiki/MySQL-Query-Generator-Methods
A metalanguage based on JSON syntax has also been developed, which allows us to conveniently and briefly describe the structures of relational databases and then translate these structures into SQL scripts. See examples in the / node_modules / impress / schemas / directory. For translation you can use the following code:
var schemaCore = require('./schemas/impress.core.schema.js'); var scriptCore = db.schema.mysql.generateScript(schemaCore, true).script; console.log(scriptCore);
Further, schemes can be used for scaffolding of forms, grids, and user interfaces in general, but this is a topic for a separate publication.
Examples
It is best understood with examples that are enough in Impress. Immediately after installation from the NPM repository (
npm install impress ), we can deploy the examples by copying them from the / node_modules / impress / examples / copyContentToProjectFolder folder to the project root. For launch, MongoDB is desirable for storing sessions (other session storage providers will be implemented soon). But you can run the examples without the database. If MongoDB is still there, then you need to set “session.persist” to true in config.js, uncomment “databases.impress”, in the same config, and uncomment modules in the “plugins.require” section: “db”, “ db.mongodb "," impress.security.mongodb ". After that, create the necessary collections and indexes by running:
node setup.js and then start the application server:
node server.jsAPI (RPC): STATEful and STATEless
One of the main tasks for which Impress was developed is the creation of application servers both on the STATEless principle (ie, REST servers) and on the more interesting STATEful principle. It is necessary to remind that REST, is when between the request / response pair neither on the server nor on the client, the state of the object is not saved. In contrast to the RPC, on which client-server applications are based, in which it is customary to create a model in the client and create a model in the server, linking their interfaces over the network and translating events and calls between these models. Here the node allows you to deploy a model at two ends of the wire and synchronize calls via AJAX / JSON, which of course is more convenient for application applications. REST came to the node from the Stone Age heavyweight web servers (like Apache and IIS), which each time launched external (in relation to them) applications, sending them HTTP protocol requests through CGI. Such an application generates a new process, it must initialize the working environment, i.e. establish connections with the database, deploy all your data, read something from the file system (if needed), etc. and all this only in order to complete the work in a few mil milliseconds and free up memory, disconnect from the database. Before the web, I wrote in languages ​​that adopted the STATEful API as RPC (COM, DCOM, Corba ...), and for me the concept of REST was always lacking. And finally, after the transition to the religion of the node, I was happy. Now again you can expand the data in memory and they do not disappear from the request to the request, you can store weighty sessions in RAM and do not serialize / deserialize them at the end and restart processes. And I had a vision that REST is a thing of the past with viewstate type crutches and state servers. I understood that the STATEful API is the greatest blessing granted by the Almighty to every living being who has cognized a node.
')
To make a new API-URL handler, you just need:
1. Create the folder /api/myAPI/getSomething.json/
2. Put the post.js file there and write in it:
module.exports = function(req, res, callback) { db.impress.collectionName.find({ fieldName: req.post.fieldValue }).toArray(function(err, nodes) { res.context.data = nodes; callback(); }); }
3. In the / api / myAPI directory, create the access.js file and write in it:
module.exports = { guests: false, logged: true, http: true, https: true }
Everything is ready, for https just set up in config.js and disable access.js for http for this folder. Moreover, you can create handlers to restart the server, simply create another folder and write the code in the file there. When you first access the code gets into memory, when you change the file on the screw, the code loads a new one into memory and sits there and waits for a call.
Screens from the demo application
After installing and deploying the examples, you can see these screens. The first one is a user registration form, it works when MongoDB is connected, as well as all the functionality associated with accounts and stored sessions (Create account, Sign In, Sign out).

In the left column of the buttons that run the examples, they are best viewed with Firebug enabled or another browser developer tool.

The biggest example is the universal admin panel for
MySQL and MongoDB , which I already wrote about. Here is its screenshot:

On Github:
https://github.com/tshemsedinov/impressIn npm:
https://npmjs.org/package/impress