As we are planning to use the latest technology stack for our UI app development, we will use the Node.js and npm (Node.js package manager) that provides the open-source runtime environment for developing the server side JavaScript web application.
Node.js is built on Chrome's V8 JavaScript engine and uses an event-driven, non-blocking I/O, which makes it lightweight and efficient. The default package manager of Node.js, npm, is the largest ecosystem of open source libraries. It allows installing node programs and makes it easier to specify and link dependencies.
-v
command on CLI. It should return the installed npm version in the output. We can switch to NetBeans for creating a new AngularJS JS HTML 5 project in NetBeans. At the time of writing this chapter, I have used NetBeans 8.1.Gruntfile.js
as a build tool.{ "name": "otrs-ui", "private": true, "version": "1.0.0", "description": "Online Table Reservation System", "main": "index.js", "license": "MIT", "dependencies": { "coffee-script": "^1.10.0", "gulp-AngularJS-templatecache": "^1.8.0", "del": "^1.1.1", "gulp-connect": "^3.1.0", "gulp-file-include": "^0.13.7", "gulp-sass": "^2.2.0", "gulp-util": "^3.0.7", "run-sequence": "^1.1.5" }, "devDependencies": { "coffee-script": "*", "gulp-sass": "*", "bower": "^1.3.1", "http-server": "^0.6.1", "jasmine-core": "^2.3.4", "karma": "~0.12", "karma-chrome-launcher": "^0.1.12", "karma-firefox-launcher": "^0.1.6", "karma-jasmine": "^0.3.5", "karma-junit-reporter": "^0.2.2", "protractor": "^2.1.0", "shelljs": "^0.2.6" }, "scripts": { "postinstall": "bower install", "prestart": "npm install", "start": "http-server -a localhost -p 8000 -c-1", "pretest": "npm install", "test": "karma start karma.conf.js", "test-single-run": "karma start karma.conf.js --single-run", "preupdate-webdriver": "npm install", "update-webdriver": "webdriver-manager update", "preprotractor": "npm run update-webdriver", "protractor": "protractor e2e-tests/protractor.conf.js", "update-index-async": "node -e "require('shelljs/global'); sed('-i', /\/\/@@NG_LOADER_START@@[\s\S]*\/\/@@NG_LOADER_END@@/, '//@@NG_LOADER_START@@\n' + sed(/sourceMappingURL=AngularJS-loader.min.js.map/,'sourceMappingURL=bower_components/AngularJS-loader/AngularJS-loader.min.js.map','app/bower_components/AngularJS-loader/AngularJS-loader.min.js') + '\n//@@NG_LOADER_END@@', 'app/index-async.html');"" } }
bower.json
as shown in the following:{ "name": "OTRS-UI", "description": "OTRS-UI", "version": "0.0.1", "license": "MIT", "private": true, "dependencies": { "AngularJS": "~1.5.0", "AngularJS-ui-router": "~0.2.18", "AngularJS-mocks": "~1.5.0", "AngularJS-bootstrap": "~1.2.1", "AngularJS-touch": "~1.5.0", "bootstrap-sass-official": "~3.3.6", "AngularJS-route": "~1.5.0", "AngularJS-loader": "~1.5.0", "ngstorage": "^0.3.10", "AngularJS-resource": "^1.5.0", "html5-boilerplate": "~5.2.0" } }
.bowerrc
file as shown in the following to specify the directory where bower will store the components defined in bower.json
. We'll store the bower component under the app directory.{ "directory": "app/bower_components" }
gulpfile.js
. We'll use CoffeeScript
to define the gulp tasks. Therefore, we will just define the CoffeeScript
in gulpfile.js
and the actual task will be defined in gulpfile.coffee
. Let's see the content of gulpfile.js
:require('coffee-script/register'); require('./gulpfile.coffee');
CoffeeScript
to define the gulp file. The name of the gulp
file written in CoffeeScript
is gulpfile.coffee
. The default task is defined as default_sequence
:default_sequence = ['connect', 'build', 'watch']
As per the defined default sequence task, first it will connect to the server, then build the web app, and keep a watch on the changes. The watch will help to render changes we make in the code and will be displayed immediately on the UI.
The most important parts in this script are connect
and watch
. Others are self-explanatory.
gulp-connect
: This is a gulp plugin to run the web server. It also allows live reload.gulp-watch
: This is a file watcher that uses chokidar and emits vinyl objects (objects describe the file – its path and content). In simple words, we can say that gulp-watch
watches files for changes and triggers tasks.gulpfile.coffee:
gulp = require('gulp') gutil = require('gulp-util') del = require('del'); clean = require('gulp-clean') connect = require('gulp-connect') fileinclude = require('gulp-file-include') runSequence = require('run-sequence') templateCache = require('gulp-AngularJS-templatecache') sass = require('gulp-sass') paths = scripts: src: ['app/src/scripts/**/*.js'] dest: 'public/scripts' scripts2: src: ['app/src/views/**/*.js'] dest: 'public/scripts' styles: src: ['app/src/styles/**/*.scss'] dest: 'public/styles' fonts: src: ['app/src/fonts/**/*'] dest: 'public/fonts' images: src: ['app/src/images/**/*'] dest: 'public/images' templates: src: ['app/src/views/**/*.html'] dest: 'public/scripts' html: src: ['app/src/*.html'] dest: 'public' bower: src: ['app/bower_components/**/*'] dest: 'public/bower_components' #copy bower modules to public directory gulp.task 'bower', -> gulp.src(paths.bower.src) .pipe gulp.dest(paths.bower.dest) .pipe connect.reload() #copy scripts to public directory gulp.task 'scripts', -> gulp.src(paths.scripts.src) .pipe gulp.dest(paths.scripts.dest) .pipe connect.reload() #copy scripts2 to public directory gulp.task 'scripts2', -> gulp.src(paths.scripts2.src) .pipe gulp.dest(paths.scripts2.dest) .pipe connect.reload() #copy styles to public directory gulp.task 'styles', -> gulp.src(paths.styles.src) .pipe sass() .pipe gulp.dest(paths.styles.dest) .pipe connect.reload() #copy images to public directory gulp.task 'images', -> gulp.src(paths.images.src) .pipe gulp.dest(paths.images.dest) .pipe connect.reload() #copy fonts to public directory gulp.task 'fonts', -> gulp.src(paths.fonts.src) .pipe gulp.dest(paths.fonts.dest) .pipe connect.reload() #copy html to public directory gulp.task 'html', -> gulp.src(paths.html.src) .pipe gulp.dest(paths.html.dest) .pipe connect.reload() #compile AngularJS template in a single js file gulp.task 'templates', -> gulp.src(paths.templates.src) .pipe(templateCache({standalone: true})) .pipe(gulp.dest(paths.templates.dest)) #delete contents from public directory gulp.task 'clean', (callback) -> del ['./public/**/*'], callback; #Gulp Connect task, deploys the public directory gulp.task 'connect', -> connect.server root: ['./public'] port: 1337 livereload: true gulp.task 'watch', -> gulp.watch paths.scripts.src, ['scripts'] gulp.watch paths.scripts2.src, ['scripts2'] gulp.watch paths.styles.src, ['styles'] gulp.watch paths.fonts.src, ['fonts'] gulp.watch paths.html.src, ['html'] gulp.watch paths.images.src, ['images'] gulp.watch paths.templates.src, ['templates'] gulp.task 'build', ['bower', 'scripts', 'scripts2', 'styles', 'fonts', 'images', 'templates', 'html'] default_sequence = ['connect', 'build', 'watch'] gulp.task 'default', default_sequence gutil.log 'Server started and waiting for changes'
npm install --no-optional gulp
gulp-clean
, gulp-connect
, and so on using the following command:npm install --save --no-optional gulp-util gulp-clean gulp-connect gulp-file-include run-sequence gulp-AngularJS-templatecache gulp-sass
bower.json
file using the following command:bower install --save
./public
directory) as separate directories. Therefore, the following directory structure is different from the default AngularJS seed project:+---app | +---bower_components | | +---AngularJS | | +---AngularJS-bootstrap | | +---AngularJS-loader | | +---AngularJS-mocks | | +---AngularJS-resource | | +---AngularJS-route | | +---AngularJS-touch | | +---AngularJS-ui-router | | +---bootstrap-sass-official | | +---html5-boilerplate | | +---jquery | | ---ngstorage | +---components | | ---version | +---node_modules | +---public | | ---css | ---src | +---scripts | +---styles | +---views +---e2e-tests +---nbproject | ---private +---node_modules +---public | +---bower_components | +---scripts | +---styles ---test
References to some good reads: