MEAN stack build system
The MEAN stack is [M]ongo, [E]xpress, [A]ngular, [N]ode.
Back end:
The server is built using
Express, which is built on top of
Node.
The database used by the server is
MongoDB.
Front end:
The client is built using
Angular.
The
less version of
Bootstrap is used for CSS.
I use
Yeoman and the
angular-fullstack generator to generate my MEAN stack scaffold.
yo angular-fullstack [app]
Development tools:
npm is used for the server dependencies; these are listed in
package.json
Bower is used for the client dependencies; these are listed in
bower.json
Grunt is used for the build system. The configuration is stored in
Gruntfile.js
The file system structure is as follows:
site/
app/ # client source code
lib/ # server source code
test/ # tests
public/ # client production build destination
Gruntfile.js # Grunt configuration
package.json # server dependencies
bower.json # client dependencies
server.js # Express server entry-point
Grunt plugins:
grunt-bower-install:
When new dependencies are added with
bower
,
grunt-bower-install will automatically inject their css and js into
index.html
.
In the
grunt.initConfig
block of
Gruntfile.js
:
'bower-install': {
app: {
html: '<%= yeoman.app %>/index.html',
ignorePath: '<%= yeoman.app %>/'
}
},
grunt-file-blocks:
When new front end components added in the source tree,
grunt-file-blocks will automatically inject the javascript into
index.html
and the less into
main.less
.
In the
grunt.initConfig
block of
Gruntfile.js
:
fileblocks: {
options: {
removeFiles: true,
templates: {
less: '@import \'${file}\';'
}
},
js: {
src: 'app/index.html',
blocks: {
components: { cwd: 'app', src: 'components/**/*.js' }
}
},
less: {
src: 'app/css/main.less',
blocks: {
components: { cwd: 'app', src: 'components/**/*.less' }
}
}
},
Development workflow:
File are monitored for changes and the front or back end are reloaded as required.
nodemon
and
LiveReload
are run concurrently:
In the
grunt.initConfig
block of
Gruntfile.js
:
concurrent: {
dev: {
tasks: ['nodemon', 'watch'],
options: {
logConcurrentOutput: true
}
}
},
Back end changes are monitored by
nodemon. If a file required by the server is changed,
node
will be relaunched, restarting the server.
In the
grunt.initConfig
block of
Gruntfile.js
:
nodemon: {
dev: {
options: {
file: 'server.js',
ignoredFiles: ['app', 'test', 'node_modules'],
watchedExtensions: ['js']
}
}
},
Front end changes are monitored by
LiveReload. If a file required by the client is changed, assets will be rebuild (eg
less
converted to
css
) and the browser will be refreshed
In the
grunt.initConfig
block of
Gruntfile.js
:
watch: {
app: {
options: { livereload: true },
files: [
'app/index.*',
'app/css/*',
'app/components/**/*.js',
'app/images/*'
]
},
less: {
tasks: ['less'],
files: ['app/css/main.less', 'app/components/**/*.less']
}
},
less: {
build: {
files: { 'app/css/main.css': 'app/css/main.less' }
}
}
This article is inspired by
Shawn Dahlen’s post on the build system
4dashes uses.