- Quick start
- Summary
- Libraries
- Application structure
- Data Source
- Static resources and front-end libraries
-
Clone the repository
-
Run
npm install
-
Start the application:
node index.js
Basic project structure for a web application. It has not scaffolding and it will never have. The goal is to reduce the bootstrap time, but bootstrap occurs only once. That said, it includes:
-
Application structure
-
Configuration management with Grunt (lint, package, deploy, frontend dependencies)
-
Configuration files for different environments
-
Data source configuration and initialization
ExpressJS: handle requests
Handlebars: rendering engine
Frontend libraries: jquery, bootstrap, es5-shim, font-awesome
Domain Driven Design is the design principle behind the application structure.
It follows the one-component-per-file convention. Components files have CamelCase names, with an upper-case first letter. All multi-components files like controllers should be given camelCase names with a lower-case first letter.
The application runs wrapped within a [Node's domain](https://github.com/brianc /node-domain-middleware), so JavaScript errors will not crash the Node's process.
node-hello-world
|
|---app
|---domain
|---controllers
|---views
|---layouts
|---partials
|---helpers
|---assets
|---vendor
|---lib
|---support
|---config
app/: the web application goes here.
app/domain/: the domain layer. The domain includes the model and repositories.
app/controllers/: the application layer goes here. There must be a single file by each controller, despite how many routes it handles. Each controller must handle a single resource.
app/views/: view files go here. Views must have .html
extension and
they are rendered with handlebars.
app/views/partials/: partials are reusable components. They must have
.html
extension and they can be included in views by using the following
handlebars directive: {{> "partialName" }}
which is mapped to app/views /partials/partialName.html
app/views/layouts/: layouts can be applied by request. By default,
handlebars is configured with the main.html
layout, but it can be changed
setting the layout
property in the response model.
app/helpers/: view helpers, like handlebars helpers.
lib/: technical layer components.
support/: support files like scripts and MySQL data files.
config/: global configuration files. It uses and follows the conventions from [node-config](https://github.com/lorenwest/node-config/wiki/Configuration- Files).
The index.js
at the root directory is the application entry point. It uses
an AppContext
to initialize the application.
The AppContext
receives the global configuration and performs the
following actions at load()
:
-
If there's a configured data source, initializes it.
-
Initializes
lib/contextMiddleware
to expose the context information to the view model, and it also loads thelib/transactionMiddleware
to bind a transaction to a request if there's a defined data source. -
Loads all controllers and returns
Controllers are loaded from app/controllers/
and they receive the App Context
as parameter. The AppContext
provides access to the domain
layer and the Express.js application.
A controller is expected to handle a single resource. It must register all routes related to the same resource.
The domain layer is stateless, so repositories and related objects must be created on each request.
If there's a configured data source, the Express.js request object will have
an additional db
attribute which references a connection object ready
to operate against the database within a transaction.
You MUST NEVER operate with the data source in controllers, any operation must be delegated to a domain repository.
This project has built-in integration with MySQL. If you don't want to use a
MySQL data source, just remove the dataSource
attribute from the default
configuration file config/default.json
.
If you plan to use MySQL as your data source, first create the test database:
create database hello_world;
grant all privileges on hello_world.* to 'hello_world'@'localhost'
identified by 'hello_world';
flush privileges;
The drop
attribute in the data source configuration indicates whether the
database is re-created every time the application starts. This is the default
behaviour.
In order to re-create and initialize the database, the application reads
MySQL data files from support/mysql/
. The database structure is defined
in support/mysql/db-setup.sql
. The data files are read by priority from
the directory support/sql/db-setup.d/.
Data files can be either MySQL or JSON files. MySQL files are executed against the database once the structure is created. JSON files have the following convention:
{
"table": "items",
"data":[{
"name": "Le Chuck",
"picture_url": "http://localhost:3000/images/lechuck.png",
"site_url": "http://localhost:3000"
}]}
Each element in the data
array is a single registry in the table defined
by the table
attribute.
Static resources are managed by express, and by default the AppContext
maps the app/assets/
directory to the application root. So,
app/assets/css/main.css
is mapped to
http://localhost:3000/css/main.css
. It uses the express helper to map
static resources.
Front-end libraries are managed with npm. Why? Because both npm and grunt have good enough integration to manage front-end dependencies without adding another technical tier like bower.
It uses npmcopy grunt task to copy
front-end dependencies on the npm's
postinstall hook.
Gruntfile.client.json
file has the task configuration. The default
configuration sets the front-end libraries path to app/assets/vendor/
.
For instance, in order to add the jquery-ui dependency you should perform the following actions:
-
Add the dependency to npm:
npm install jquery-ui --save
-
Map the dependency to the npmcopy grunt task:
Gruntfile.client.json
{
"npmcopy": {
"options": {
"destPrefix": "app/assets/vendor"
},
"libs": {
"files": {
"lib/jquery-ui": "jquery-ui"
}
}
}
}
It will cause directory node_modules/jquery-ui
be copied
to app/assets/vendor/lib/jquery-ui
.
- Run
grunt npmcopy
to force copying the directory. Now you can reference jquery-ui components from views. For instance:
http://localhost:3000/vendor/lib/jquery-ui/core.js