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.jsThe 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 refreshedIn 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.