Comprehensive MEAN(Mongo, Express, Angular, and Nodejs) with Docker IV

During our web development. We spend a lot of time one some trivial things. For example, restart node service. It not mean it take long to restart to node service. I mean, you need to switch to your terminal and type node restart or some other action you need to do in order to see the result.

The all four article is

  1. Environment setting - develop MEAN with docker.
  2. Nodejs and Express.
  3. Angularjs
  4. *Continuous Development

In the fourth article of MEAN practice. I would like to introduce Continuous Development(nothing will stop you to code) to MEAN project. By doing so, it really save you a lot of time.

Front End

For the front end side, I use Gulp to build and watch(detect any change you made on the front end code and rebuild the app). Here is my gulpfile.

var gulp = require('gulp');
var plugins = require('gulp-load-plugins')();
var mainBowerFiles = require('main-bower-files');

var paths = {
    scripts: 'app/**/*.js',
    styles: ['app/**/*.{css,scss}'],
    index: 'app/index.html',
    partials: ['app/**/*.html', '!app/index.html'],
    dest: './dest'
};

var pipes = {};

pipes.cleanDest = function () {
    return gulp.src('dest/', {read: false})
        .pipe(plugins.clean());
};


pipes.builtPartialScripts = function() {
    return gulp.src(paths.partials)
        .pipe(gulp.dest(paths.dest));
};

pipes.builtAppStyles = function() {
    return gulp.src(paths.styles)
        .pipe(plugins.concat('app.css'))
        .pipe(gulp.dest(paths.dest));
};

pipes.builtVendorStyles = function() {
    return gulp.src(mainBowerFiles('**/*.css'))
        .pipe(plugins.concat('vendor.css'))
        .pipe(gulp.dest(paths.dest));
};

pipes.builtVendorScripts = function() {
    return gulp.src(mainBowerFiles('**/*.js'))
        .pipe(pipes.orderVendorScripts())
        .pipe(plugins.concat('vendor.js'))
        // .pipe(plugins.uglify())
        .pipe(gulp.dest(paths.dest));
};

//built app acripts
pipes.builtAppScripts = function() {
    return gulp.src(paths.scripts)
        .pipe(pipes.orderAppScripts())
        .pipe(plugins.concat('app.js'))
        .pipe(plugins.uglify())
        .pipe(gulp.dest(paths.dest));
};

//order vendor scripts
pipes.orderVendorScripts = function() {
    return plugins.order(['jquery.js', 'angular.js']);
};

//put index.js into first order
pipes.orderAppScripts = function() {
    return plugins.order(['app/index.js', paths.scripts]);
};

//copy bower-components into app folder
pipes.bowerFiles = function() {
    return gulp.src(mainBowerFiles())
        .pipe(gulp.dest(paths.dest + '/bower_components'));
};

pipes.builtIndex = function() {

    var vendorStyles = pipes.builtVendorStyles();
    var vendorScripts = pipes.builtVendorScripts();
    var appScripts = pipes.builtAppScripts();
    var appStyles = pipes.builtAppStyles();
    pipes.builtPartialScripts();

    return gulp.src('app/index.html')
        .pipe(gulp.dest(paths.dest))
        .pipe(plugins.inject(vendorScripts, {relative:true, name:'bowerjs'}))
        .pipe(plugins.inject(vendorStyles, {relative:true, name:'bowercss'}))
        // .pipe(plugins.inject(gulp.src(mainBowerFiles()), {relative:true, name:'bower'}))
        .pipe(plugins.inject(appScripts, {relative:true}))
        .pipe(plugins.inject(appStyles, {relative:true}))
        .pipe(gulp.dest(paths.dest));
};

gulp.task('clean-app', pipes.cleanDest);
gulp.task('build-app', ['clean-app'], pipes.builtIndex);


gulp.task('watch', ['build-app'], function() {

    gulp.watch(paths.index, function() {
        return pipes.builtIndex();
    });

    gulp.watch(paths.scripts, function() {
        return pipes.builtAppScripts();
    });

    gulp.watch(paths.styles, function() {
        return pipes.builtAppStyles();
    });

    gulp.watch(paths.partials, function() {
        return pipes.builtPartialScripts();
    });

});

Some gulp plugin is very useful. The first one would be main-bower-files. It will help you target main file from the bower packages. The second one would be gulp-load-plugins, it will help you to load all your gulp plugin. Otherwise, you will need to require all of them, and that is a lot.

You can see all the gulp plugin I have used for this project in my package.json in devDependencies.

{
  "name": "toDoList",
  "version": "0.0.0",
  "description": "todo app that combine all technique",
  "author": "Wei Ting Cheng",
  "dependencies": {
    "body-parser": "~1.5.2",
    "express": "~4.7.2",
    "method-override": "~2.1.2",
    "mongoose": "~3.6.2",
    "path": "~0.12.7"
  },
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-concat": "^2.6.0",
    "gulp-inject": "^4.0.0",
    "gulp-load-plugins": "^1.2.0",
    "gulp-order": "^1.1.1",
    "gulp-rename": "^1.2.2",
    "gulp-uglify": "^1.5.3",
    "gulp-clean": "^0.3.2",
    "main-bower-files": "^2.11.1",
    "nodemon": "^1.9.2"
  }
}

Then you can type gulp build-app to build your app or gulp watch to build and watch your code.

Back End

In the back end side, I use nodemon to watch my code.

Docker

Of course, it will works even better in docker environment. I use volumes in docker to connect your working code to docker environment.

version: '2'
services:
  memo:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - mongo
    volumes:
      - ./dest/:/app/dest/
      - ./server.js:/app/server.js
    container_name: memo
    image: memo

  mongo:
    image: mongo
    container_name: memo-mongo

Further Reading

You can find this code in my github repo MEAN pracitce.

  1. Docker volumes
  2. nodemon
  3. gulp
  4. grunt - Another popular build tool.
  5. All the gulp-plugin I have used here is worth to try.

Prev: Angularjs