© Elad Elrom 2016

Elad Elrom, Pro MEAN Stack Development, 10.1007/978-1-4842-2044-3_9

9. Build Scripts

Elad Elrom

(1)New York, USA

When working on a JavaScript project, right from the beginning, we need to be mindful of the build scripts. However, with so many tools available, it is easy to get confused about what to use and when to use it.

As you may recall from Chapter 1, I introduced you to Grunt and Gulp, and we installed them via npm. Both Grunt and Gulp, while utilizing Node.js, help us to automate our tasks. These both require that we install plugins and create a build file, and both are command line packages that can enhance the capability of your local environment as well as the deployment servers, but what is the difference between these two tools? Additionally, what other tools can we utilize to do what is necessary in order to help us manage, automate, and deploy our project?

In this chapter, we will answer these questions and provide you with options for automating your build and getting it ready for deployment.

Browserify

As you have seen, there are tens of thousands of open source Node.js modules avaliable, and during previous chapters, we have used some of these examples and even created our own npm module. However, if we build a browser-based project such as AngularJS , we can’t utilize these Node.js modules on the front-end code as is. Locating all of the modules in a project and bundling them into one file before we go to production is a common practice that reduces the end-user download time of loading large piles of JavaScript code to make our app work, as well as allowing us to prevent other developers from reverse engineering our code.

This is when Browserify can come in handy, solving our problem by bundling up all of these Node.js module dependencies, creating one bundle file that we can then use and include in all of the modules we need. Let’s take a closer look to see how it works.

Create a New Node.js Module

First, let’s create a New WebStorm Node Project. Open WebStorm and select “Create New Project” ➤ “Node.js Express App” ➤ “Create.” You can name the project whatever you’d like, or simply leave the default name “untitled.”

The project is now created. Next, we’ll create a Node.js module that will compute two numbers. To do so, create a folder named “compute” in the “node_modules” folder, and then create a file name: “index.js”. The content of “node_modules/compute/index.js” will hold the following (see Listing 9-1):

Listing 9-1. "node_modules/compute/index.js" compute Node.js module
'use strict';
module.exports = function (x, y) { return x + y; }

Our node module computes two numbers and then returns the results. We can refactor the code by referencing a function for better readability, as shown in Listing 9-2.

Listing 9-2. “node_modules/compute/index.js” compute Node.js module refactored
'use strict';

function compute(x, y) {
    return x + y;
}
module.exports = compute


Additionally, add a “node_modules/compute/package.json” file and add the following minimum package.json code:

{
  "name": "my-compute-package",
  "version": "1.0.0"
}

Next, in the “app.js” entry file, add a reference to our Node.js compute module. At the end of the files, add two numbers and show the results:

var compute = require('compute');
console.log(compute(1, 2));

Now, to run the project, click the green “play” icon in the top right corner. The app is configured to run “bin/www,” and you can see the results on the run console (see Figure 9-1).

A416092_1_En_9_Fig1_HTML.jpg
Figure 9-1. Compute module running in a Node.js project.

Install Browserify

Now that we have our compute node module created, we can bundle it to be used in any JavaScript engine. Install Browserify globally via npm in the WebStorm command line window:

$ sudo npm install -g browserify

Compile a Browserify Bundle File

Next, to bundle our module, we will point to the compute module we created and tell Browserify to create a bundle file, which we’ll name “bundle.js,” like so:

$ browserify -r ./node_modules/compute/index.js > bundle.js

You can then confirm that a “bundle.js” was created in the root of the project. Given the way we instructed Browserify to compile the file, we will need to use the module file location in the AngularJS project we'll create shortly, add the bundle.js file as a reference in the index.html file, and then place the following statement in AngularJS:

var add = require('./node_modules/compute/index.js');

This does work, but to shorten the path and make the code align better with what we have in Node.js, we can also set the target name to “compute”:

$ browserify -r ./node_modules/compute/index.js:compute ➤ bundle.js

Note

Browserify’s “–r” option flag stands for “require.” It requires that we place the module name. After doing so, we can then use the colon separator to set the target name.

Compiling with the target name will enable us to call “compute” in our AngularJS project instead of pointing to the file location:

var compute = require('compute');

Behind the scenes, Browserify compiled a “bundle.js” file for us that includes the code in Listing 9-3.

Listing 9-3. Portion content of “bundle.js”
require=(function e(t,n,r){function..............
'use strict';


function add(x, y) {
    return x + y;
}
module.exports = add
},{}]},{},[]);

Using a Node.js Module in an AngularJS Project

The end goal is to be able to use the “bundle.js” file we created in our AngularJS project . Let’s go ahead and create an AngularJS project to use the bundle.js file we’ve just created. First, ensure you stop the Node.js app, since it will be holding up the same localhost port we need to use in our AngularJS project. You can stop the Node.js project from WebStorm by clicking the “Stop” icon on the Run console. See Figure 9-2.

A416092_1_En_9_Fig2_HTML.jpg
Figure 9-2. Stop "bin/www" icon in WebStorm

I want to give you an additional handy tip to ensure that no Node.js projects are running in the background. If you have a project running and you run this command in the command line:

$ ps -ax | grep node

You will get a response showing any Node.js services running, such as:

59572 ?? 0:00.25 / WebStorm/untitled/bin/www

Now, to terminate the service, all you have to do is use the “kill” command with the service ID, which we received as a response:

$ kill -9 59572

That’s it—now we are ready to create our AngularJS project.

  1. In WebStorm, select “File” ➤ “New” ➤ “Project” ➤ “AngularJS” ➤ name the project “MyAngularProject” ➤ “Create.” Select “New Window” so you can have both projects side by side.

  2. Open the WebStorm Terminal window (bottom left corner) and run these two commands:

    1. $ npm install

    2. $ npm start

  3. To view the project, open up a browser client:

    1. open http://localhost:8000

Now that we have an AngularJS project to work with, copy the “bundle.js” file we created in the Node.js project onto the AngularJS project “app/bundle.js.” Next, reference the bundle file in our “index.html” file:

<script src="bundle.js"></script>

See Figure 9-3.

A416092_1_En_9_Fig3_HTML.jpg
Figure 9-3. Including bundle.js in index.html AngularJS project

Now we can open “app/view1/view1.js” and add our script to the “view1.js” controller (Listing 9-4).

Listing 9-4. Using compute Node.js module in view1.js AngularJS project
.controller('View1Ctrl', [function() {
  var compute = require('compute');
  console.log(compute(3, 6));
}]);

All we’re doing is adding a “require” to reference the module we’re using and then sending the result of adding two numbers together to the console. Run the project or refresh the browser if you still have it open:

$ open http://localhost:8000

Inspect the element in the browser and look at the console messages. You should see the computed results of 9. See Figure 9-4.

A416092_1_En_9_Fig4_HTML.jpg
Figure 9-4. Console message in AngularJS project where compute module is used.

As you can see, this is powerful, considering Browserify not only allows us to bundle all of our modules together, but gives us the option to use tens of thousands of modules from Node.js.

Babelify

Many criticize JavaScript as second-class citizen due to its lack of object-oriented programming syntax and other deficiencies. JavaScript is evolving and, in fact, ECMAScript 2015 is the JavaScript standard that is also known as ES2015, or ES6. It holds the most significant update of the language since ES5, which was standardized back in 2009. However, many browser engines and other JavaScript runtimes such as Node.js have been implementing these features slowly, and not all the features from ES6 are available on all engines at the time of this writing. Babelify allows us to use ES2015 features today.

Note

ES6 transpiling is compiling code down to ECMAScript from 2009 (also known as ES5) so it can be backward compatible with JavaScript engines that don't yet support ES6.

Installing Babel

In the section below, we’ll cover how to install Babel. In the same AngularJS project we created previously, install Babel CLI in the WebStorm command line and add a second window via “New Session” since we have “npm start” running, and install Babel via npm:

$ npm install babel-cli --save-dev

Next, we need to install "Babel 6 preset" for transpiling ECMAScript 6 locally, so that we can support all of the capabilities of ES2015:

$ npm install babel-preset-es2015 --save-dev

This download may take a while. Lastly, we will create “.babelrc” file in the root of the project that tells Babel that we are using ES2015:

{
  "presets": ["es2015"]
}

Setting Babel in WebStorm

Now that Babel is installed and configured, all we need to do is set a watcher so that the transpiling will happen automically via WebStorm and we won’t need to compile the files every time. Click “command + ,” to open the WebStorm preferences window and select “Tools” ➤ “File Watchers” ➤ “+” ➤ “Babel.”

In the configuration window, set the Babel program location, which we have already installed: “node_modules/.bin/babel”. See Figure 9-5.

A416092_1_En_9_Fig5_HTML.jpg
Figure 9-5. Adding Babel File Watcher to WebStorm

Notice that WebStorm, with its default settings, doesn't show ".bin" folders. You can navigate with the command line to view the contents of the folder, or check the “Show hidden files and directories” button in the “Select path” dialog box.

Writing ES6 Code

Now that we have Babel installed and configured and a watcher in place that will generate and compile files automatically for us, we are ready to do some coding; for example ES6 has a feature that will allow us to extend built-in JavaScript classes. Let's create a code that does just that. Add the code from Listing 9-5 into the " view1/view1.js" controller.

Listing 9-5. Extending Array JavaScript built in class
.controller('View1Ctrl', [function() {
    var compute = require('compute');
    console.log(compute(3, 6));


    class MyArray extends Array {
        constructor(args) {
            super(args);
        }
        speak() {
            console.log('I have ' + this.length + ' items');
        }
    }


    var arr = new MyArray();
    arr[1] = 12;
    arr.length == 2;
    arr.speak();


}]);

The code extends the built-in array and adds a method called "speak" that tells us how many items the array contains. We’ve created a basic example, but you can imagine how this feature will be useful in cases where you would want to create custom filtering and sorting of an array.

Once you save the file, you can see that WebStorm is executing the Babel task at the footer of WebStorm—see Figure 9-6.

A416092_1_En_9_Fig6_HTML.jpg
Figure 9-6. WebStorm executing Babel task

We have extended the array’s built-in class and added a method called “speak.” Once we create a new instance of the class and use the new method, we can then open http://localhost:8000 and view the messages in the console to confirm that we’re receiving the message “I have 2 items.”

As you can see, this is a powerful tool, and will allow us to utilize ES6 today. There is a PDF document online that lists all of the features in ES6: http://​www.​ecma-international.​org/​ecma-262/​6.​0/​ECMA-262.​pdf., which is the ECMA-262 6th Edition, of the ECMAScript 2015.

Grunt

We have installed and run Grunt tasks before. As you may recall, back in Chapter 8 we used Grunt to create a task that would then create a static snapshot of our pages that we then deployed to our server. Grunt is often used to automate common tasks that we need to run in order to get our code ready for production. Common operations before deployment include renaming files, uglifying (obfuscating) files, minifying files, bundling together all of our assests, and uploading all of our files to a server.

Grunt with a Babel Task

We can create a Grunt task that can be used to run our code through Browserify and Babelify, either by calling the task directly or by placing a watcher on it, so when we make changes to our files, Grunt handles what is needed behind the scenes. This saves us the headache of dealing with all of that individually on our own.

To get started, create a Grunt build file in the root of your AngularJS project, “Gruntfile.js”, and copy the code from Listing 9-6.

Listing 9-6. Gruntfile.js Babel task
module.exports = function(grunt) {

    require('load-grunt-tasks')(grunt);

    grunt.initConfig({
        babel: {
            options: {
                sourceMap: true,
                presets: ['es2015']
            },
            dist: {
                files: {
                    'dist/app/view1/view1.js': 'app/view1/view1.js'
                }
            }
        }
    });


    grunt.registerTask(run-babel', ['babel']);
};

As you may recall, the “Gruntfile.js” file consists of loading the plugins we’ll be using, setting the project configurations, and creating tasks.

In the code above, we are setting a task to compile the “app/view1/view1.js” file into the “dist/app/view1/view1.js” location while using the “babel” plugin.

Install Grunt Babel Plugins

Next, we need to install Grunt locally, as well as the plugins we will be using:

$ npm install grunt load-grunt-tasks grunt-babel --save-dev

Note that, depending on your Internet connection, this may take a while to download. Additionally, you’ll need the “present es-2015” plugin to be installed, which I covered previously .

Run Grunt Babel Task

Now that we have our Grunt file ready and we’ve installed all of the plugins we need, all we have to do is run the root of the project the task we want in the command line:

$ grunt run-babel

The task will compile our "view.js" file. If you open up “/dist/app/view1/view.js,” you can see the following ES6 code we’ve created:

  class MyArray extends Array {
    constructor(args) {
      super(args);
    }
    speak() {
      console.log('I have ' + this.length + ' items');
    }
  }

…is replaced with the following code that will work on all ES5 JavaScript engines:

  var MyArray = function (_Array) {
    _inherits(MyArray, _Array);


    function MyArray(args) {
      _classCallCheck(this, MyArray);


      return _possibleConstructorReturn(this, (MyArray.__proto__ || Object.getPrototypeOf(MyArray)).call(this, args));
    }


    _createClass(MyArray, [{
      key: 'speak',
      value: function speak() {
        console.log('I have ' + this.length + ' items');
      }
    }]);


    return MyArray;
  }(Array);

Grunt Babelify & Browserify Task

Similarly, we can run a task that will Babelify and Browserify our code and watch for changes in the file. This can be achieved by utiltizing the following Grunt plugins:

$ npm install babelify grunt-browserify grunt-contrib-watch --save-dev

These plugins include “grunt-browserify” to compile the Node.js modules, the “babelify” module to write our ES6 code, and “grunt-contrib-watch” so that Grunt can watch for changes, just as WebStorm is doing.

The task will replace the command line we’ve created in order to build the “bundle.js” file and will then compile the ES6 code so that we can actually code ES6 in our Node.js module. See Listing 9-7.

Listing 9-7. Browserify, babelify , and watch for changes Grunt task
        browserify: {
            dist: {
                options: {
                    transform: ["babelify"]
                },
                files: {
                    "./dist/bundle.js": ["./node_modules/compute/index.js"]
                }
            }
        },
        watch: {
            scripts: {
                files: ["./modules/*.js"],
                tasks: ["browserify"]
            }
        }

The complete Grunt file code is below (see Listing 9-8).

Listing 9-8. Complete GruntJS code to run babel, browserify, babelify, and watch for changes
module.exports = function(grunt) {

    require('load-grunt-tasks')(grunt);

    grunt.initConfig({
        babel: {
            options: {
                sourceMap: true,
                presets: ['es2015']
            },
            dist: {
                files: {
                    'dist/app/view1/view1.js': 'app/view1/view1.js'
                }
            }
        },
        browserify: {
            dist: {
                options: {
                    transform: ["babelify"]
                },
                files: {
                    "./dist/bundle.js": ["./node_modules/compute/index.js"]
                }
            }
        },
        watch: {
            scripts: {
                files: ["./modules/*.js"],
                tasks: ["browserify"]
            }
        }
    });


    grunt.loadNpmTasks("grunt-browserify");
    grunt.loadNpmTasks("grunt-contrib-watch");


    grunt.registerTask("default", ["watch"]);
    grunt.registerTask("build", ["browserify"]);
    grunt.registerTask('run-babel', ['babel']);
};

Before you run the task , add the following files we created in the Node.js project, inside of our AngularJS project: “/node_modules/compute/index.js.” As you may recall, all the Node.js module does is include a code that computes two numbers:

'use strict';
module.exports = function (x, y) { return x + y; }

Now we can build the “bundle.js” file using the build task:

$ grunt build

We can see the results in the command line, confirming that the task has been completed successfully.

Running "browserify:dist" (browserify) task
>> Bundle ./dist/bundle.js created.


Done.

Grunt Watch

As you have seen previously, we’ve utilized a “grunt-contrib-watch” plugin in the Grunt file:

        watch: {
            scripts: {
                files: ["./modules/*.js"],
                tasks: ["browserify"]
            }
        }

This task is used to watch for changes. It can replace the action of WebStorm, or we can use the built-in feature in WebStorm when we develop locally and then use Grunt for deployment.

In the Grunt file, we set the default task to utilize the watcher:

grunt.registerTask("default", ["watch"]);

To see the code in action, run the default GruntJS task in the command line:

$ grunt

In the command line, we can confirm that the watcher is in progress:
Running "watch" task
Waiting...

To cancel the watch task, click “command + c”. Additionally, you can open the “dist/bundle.js” file and see the code that has been generated by Grunt for us automatically.

Gulp

Gulp is a rival task runner of Grunt. Let’s take a look at the differences between the two, as well as another choice for you to use while creating tasks.

Differences Between Grunt and Gulp

  1. Coding: Grunt is similar to Ant or Maven (if you’ve ever used these tools). It is configuring tasks, while Gulp is writing a JavaScript code that utilize plugins.

  2. Streaming: Gulp offers streaming, so you end up with one simple file instead of dealing with multiple folders and files. Remember that we created a watch task in Grunt—it’s not needed in Gulp, since it’s a core functionality.

  3. Plugins: Plugins in Gulp are more loosely coupled and aimed at solving a single task, whereas Grunt connects plugins to create a shared functionality, making Grunt more like a composition.

Note

In a nutshell, Gulp is a better tool, but Grunt has about 6,000 plugins (at the time of this writing) while Gulp only has about 2,700. Grunt having been around longer gives it a big edge.

In the end, it’s more about your own preferences. If you have not used other automating tasks such as Ant or Maven, Gulp is probably a better choice, since it’s just programming as opposed to configuring tasks. However, if you are already using Grunt, it may not be worth your effort to move to Gulp.

Installing Gulp

Although we installed Gulp back in Chapter 1, we haven’t used it in this book yet, so let’s see how the same tasks of Browserify, Babelify, and watching the file for changes will look in Gulp.

Previously, we installed a version of Gulp globally, so you can run it at any time:

$ sudo npm rm --global gulp

To ensure the old version of Gulp doesn't collide with "gulp-cli," let's install the latest "gulp-cli":

$ sudo npm install --global gulp-cli

Next, install Gulp locally and add a reference in package.json, devDependencies:

$ npm install gulp --save-dev

Creating a Gulp Task

Now that we have Gulp installed, we can create "gulpfile.js" at the root of our project. Gulpfile is the equivalent to Gruntfile. Both are written in JavaScript, but rather than configuring tasks, Gulp prefers code over settings configuration. See Listing 9-9.

Listing 9-9. Gulpfile talks to Browserify , Babelify and watch for changes
var gulp = require('gulp');
var browserify = require('browserify');
var watchify = require('watchify');
var babel = require('babelify');
var sourcemaps = require('gulp-sourcemaps');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');


function compile(watch) {
    var bundler = watchify(browserify('./node_modules/compute/index.js', { debug: true }).transform(babel));


    function rebundle() {
        bundler.bundle()
            .on('error', function(err) { console.error(err); this.emit('end'); })
            .pipe(source('build.js'))
            .pipe(buffer())
            .pipe(sourcemaps.init({ loadMaps: true }))
            .pipe(sourcemaps.write('./'))
            .pipe(gulp.dest('./build'));
    }
    if (watch) {
        bundler.on('update', function() {
            console.log('bundling');
            rebundle();
        });
    }
    rebundle();
}


function watch() {
    return compile(true);
};


gulp.task('build', function() { return compile(); });
gulp.task('watch', function() { return watch(); });
gulp.task('default', ['watch']);

The Gulpfile consists of setting references to all of the plugins we will be using, compiling our scripts, streaming, and watching for changes. Lastly, we will create a Gulp task to build and watch.

Installing Gulp Plugins

We have referenced Gulp plugins, but we haven't yet installed them, so let's go ahead and install all of the Gulp plugins we will be using, via npm:

$ npm install browserify gulp-sourcemaps vinyl-source-stream vinyl-buffer watchify babelify --save-dev

Running Gulp Tasks

Now that we have the Gulp file and all of the plugins created, we can run the Gulp task. We will be using the default task, which is set up to watch for changes:

$ gulp

We can then confirm that everything is working. Take a look at a typical output result:

[15:47:54] Using gulpfile ∼/Documents/WebStorm/[project name]/gulpfile.js
[15:47:54] Starting 'watch'...
[15:47:54] Finished 'watch' after 19 ms
[15:47:54] Starting 'default'...
[15:47:54] Finished 'default' after 4.78 ms

As you can see, streaming and watching is much simpler than with Grunt, and the coding was simply that of JavaScript, rather than a clumsy configuration file.

Note

To conceptually understand streaming in Gulp, think of our files passing through a pipe. At one or more points along that pipe, a task is done—for example, renaming files.

Webpack

We took a look at Grunt and saw the simplicity of Gulp, and we configured these tools to bundle our modules and allow us to do other tasks such as writing ES6 JavaScript code, but there are additional tools worth mentioning. Webpack and Browserify do pretty much the same thing, which is bundling our JavaScript modules to be used in a browser environment. Webpack does this more easily, since it doesn't need Grunt and Gulp or knowelge of Node.js. In fact, Webpack was built taking into account the deficiencies of Grunt/Gulp and Browserify. It's more “set it and forget it” when it comes to watchers. Let's take a look.

Installing Webpack

First, we must install Webpak globally via npm, just as we've done with the other tools:

$ sudo npm install webpack -g

Then, in the command line, pack the bundle the same way we did with Browserify:

$ webpack ./node_modules/compute/index.js bundle.js

The syntax was entry and output. We should get an output in the command line that looks like this:

Hash: be87e8b8b39b72caef48
Version: webpack 1.13.2
Time: 53ms
      Asset     Size  Chunks             Chunk Names
./bundle.js  1.45 kB       0  [emitted]  main
    + 1 hidden modules

As you can see, although both tools do practically the same thing, Browserify uses Grunt and Gulp with the help of installed plugins to get the job done, while Webpack includes all that you need, straight out of the box. In the end, deciding to use Webpack or the Browserify Grunt/Gulp combo boils down to personal preference and team experience. Teams that are unfamiliar with Node.js may find that it's better and easier to use Webpack.

Creating Webpack Config File

As mentioned previously, Webpack offers out-of-the-box features without the need to install anything else. For instance, Webpack acknowledges that assets such as CSS and images are dependencies of your project and treats them as such. As the deployment script becomes more complex, we will need a config file and will need to add loaders. Loaders are the preprocess files as you require() or “load” them and can add a task, or as Webpack calls it, “transform” them to a different language, such as CoffeeScript to Javascript. You can even create a pipeline and pass the files through that pipeline as you apply multiple transformation. That is similar to the tasks we saw in Gulp.

The config file is somewhat similar to the Grunt and Gulp file and is configured similarly to Grunt. In the root directory of the project, create a “webpack.config.js” file.

A basic “webpack.config.js” file holds the entry and output destination. See Listing 9-10.

Listing 9-10. Webpack minimalist config file
module.exports = {
    entry: './node_modules/compute/index.js',
    output: {
        filename: './bundle.js'
    }
};

The minimalist config file includes an entry file location and an output to help build our bundle file. Now, run the Webpack command and you’ll receive the same results as we did in the previous command, where we included the entry and output location.

$ webpack

Webpack Watcher

Next, remember how we set the config file in order to watch for changes in Browserify. In Webpack, it’s built out of the box, so all we have to do is set the watch flag:

$ webpack --watch

Or, in short, "w":

$ webpack --w

To cancel, just type “command + c”. Alternatively, we can set the watch flag "watch: true" in the “webpack.config.js” configuration file—see Listing 9-11:

Listing 9-11. Adding watch flag to webpack.config.js
module.exports = {
    entry: './node_modules/compute/index.js',
    output: {
        filename: './bundle.js'
    },
    watch: true
};

Webpack Transpiling ES6 Code

Just as we used the “Babelify” module to write ES6 in Grunt and Gulp, we can do the same in Webpack. All we have to do is create a loader that will let Webpack know how to handle the ES6 code.

As you may recall, in “app/view1/view1.js,” we coded our ES6 code:

  class MyArray extends Array {
    constructor(args) {
      super(args);
    }
    speak() {
      console.log('I have ' + this.length + ' items');
    }
  }


  var arr = new MyArray();
  arr[1] = 12;
  arr.length == 2;
  arr.speak();

Next, we need to install the Webpack loader and Babel through npm:

$ npm install babel-loader babel-core --save-dev

You have to have Babel installed. As you recall, we installed it previously:
$ npm babel-preset-es2015 --save-dev

Lastly, we need to config Webpack’s “webpack.config.js” file in the root of the project, which needs to be set to use the loader, and configure the entry and output file location. See Listing 9-12:

Listing 9-12. Configure webpack.config.js to compile ES6 code
module.exports = {
    module: {
        loaders: [
            {
                test: /.js$/,
                exclude: /node_modules/,
                loader: 'babel',
                query: {
                    presets: ['es2015']
                }
            }
        ],
    },
    entry: './app/view1/view1.js',
    output: {
        filename: './dist/app/view1/view1.js'
    }
};

Run Webpack via the command line "$ webpack" and you will see the output of Webpack in the terminal (Figure 9-7):

A416092_1_En_9_Fig7_HTML.jpg
Figure 9-7. Webpack output transpiling ES6 code

Next, open the file in “/dist/app/view1/view1.js” to view the content. As you can see, it has compiled the file to ES5 code.

Webpack CSS Loader

Next, to allow Webpack to handle CSS, we will perform the same action as we did with Babel—we will add a CSS loader. We do so by installing a CSS loader and then a Style loader, via npm:

$ npm install css-loader style-loader --save-dev

Now all we have to do is add a reference in our "view1/view1.js" code to the CSS file at the top of the document:

  require('../app.css');

Lastly, we need to add the loader to the Webpack config file. See Listing 9-13.

Listing 9-13. Configure webpack.config.js to compile ES6 code and CSS
  module.exports = {
    module: {
        loaders: [
            {
                test: /.js$/,
                exclude: /node_modules/,
                loader: 'babel',
                query: {
                    presets: ['es2015']
                }
            },
            {
                test: /.css$/,
                exclude: /node_modules/,
                loader: 'style!css'
            }
        ],
    },
    entry: './app/view1/view1.js',
    output: {
        filename: './dist/app/view1/view1.js'
    }
};

Now that we have the loader set up, all we have to do is run Webpack once again:

$ webpack

As you can see, it’s much easier to configure Webpack to handle our tasks than to set up Browserify. Webpack’s ease of use is especially significant in a team where the members are not familiar with Node.js, Grunt, and/or Gulp. In the next chapter, we’ll have a more in-depth discussion as well as examples of Gulp, Grunt, Browserify, and Webpack so you can better understand the trade-offs.

Vagrant VM

In the previous sections of this chapter, we showed you how to bundle different tools in order to use the latest JavaScript ES6 today, as well as how to bundle modules, automate tasks, and watch for changes.

Once your environment is all set up, how neat would it be to be able to just fire up a script and the same environment is reproduced anywhere and for all the team members of the project? Vagrant VM does just that. We can fire up or, as Vagrant calls it, "Vagrant up" and everything will be installed and configured.

Installing Vagrant & Virtual Machine

At the time of writing, Vagrant 1.8.5 is the latest Vagrant version; download Vagrant from the following link:

https://www.vagrantup.com/downloads.html

Vagrant also requires a virtual machine. That could be VirtualBox, VMware, AWS, or others. We'll be using VirtualBox, since it's free at the time of writing. On a Mac OS X, the latest version is "VirtualBox 5.1.6 for OS X." It can be downloaded from the following link:

https://www.virtualbox.org/wiki/Downloads

Now that we have Vagrant and VirtualBox installed, all we have to do is initialize Vagrant. In your WebStorm command line, run this command:

$ vagrant init hashicorp/precise64

Notice that Vagrant has created a Vagrantfile in the root of the project. The Vagrantfile includes a description of machines and resources needed to run and the software to be installed. Next, fire up Vagrant:

$ vagrant up

A successful output looks like Figure 9-8.

A416092_1_En_9_Fig8_HTML.jpg
Figure 9-8. Vagrant showing successfull setup of a virutal box

Now we can SSH the virtual machine:

$ vagrant ssh

Once you SSH the virtual box, you can view all of the files we’ve downloaded by typing into the command line:

$ ls /vagrant

To exit the virtual box, simply type “exit”:

$ exit

If at any time you make changes, type “reload”:

$ vagrant reload

Or to reload and provision:
Note “

Provision” in Vagrant means that you allow automatically installed software and its altered configuration of the virtual machine. When you first Vagrant up the machine, it is done automatically.

$ vagrant reload --provision                                          

Networking Access

In this section, we will set up Vagrant networking so that other authorized guests can access the box. We do so by setting up an Apache web server.

Open the Vagrantfile file and uncomment this line by removing the "#" symbol:

# config.vm.network "forwarded_port", guest: 80, host: 8080

Before the end of the script, at the section "# Enable provisioning with a shell script. Additional provisioners such as", add the following line:

config.vm.provision :shell, path: "bootstrap.sh"

Save and close the file. Next, SSH the virtual box and install Apache:

$ vagrant ssh
$ sudo apt-get update
$ sudo apt-get install -y apache2
$ exit

Set a file named "bootstrap.sh" at the root of the project with the following content:

#!/usr/bin/env bash
apt-get update
apt-get install -y apache2
if ! [ -L /var/www ]; then
  rm -rf /var/www
  ln -fs /vagrant /var/www
fi

Then reload and provision:

$ vagrant reload --provision

Now you can navigate to the following URL and see all of the files we are setting up for sharing, since we have a web server up: http://127.0.0.1:8080/ . See Figure 9-9:

A416092_1_En_9_Fig9_HTML.jpg
Figure 9-9. Vagrant networking configured and web server up

HTTP Sharing

In this section , we will share the Vagrant box. Share allow collaboration on your Vagrant environment. Vagrant currently provides three types of sharing—HTTP sharing, SSH sharing, and general sharing—through HashiCorp's Atlas account.  Since the people you’re sharing with don’t need Vagrant installed, it’s ideal to share with managers, clients, or just about anyone.

The first step of sharing is creating a free account at https://atlas.hashicorp.com/account/new .

Now that we have an account with Atlas, we need to log in to the account. In the WebStorm command line, type:

$ vagrant login

The command line will ask for your username and password and will then confirm that you are logged in correctly:

Username or Email: [your username]
Password (will be hidden): [your password]
You are now logged in!

Now we can share. Type into the WebStorm command line:

$ vagrant share

You will get a share of information via the command line output:

==> default: Creating Vagrant Share session...
    default: Share will be at: spoiled-crocodile-4501
==> default: Your Vagrant Share is running! Name: spoiled-crocodile-4501
==> default: URL: http://spoiled-crocodile-4501.vagrantshare.com

You can confirm that the share was successful by looking at your account on the Atlas website. See Figure 9-10.

A416092_1_En_9_Fig10_HTML.jpg
Figure 9-10. Vagrant site show share

To connect via the command line, type the following command into the Terminal:

$ vagrant connect spoiled-crocodile-4501

Note that this name “spoiled-crocodile-4501” will be different for you. Refer to the name in your share from Figure 9-10.

This is what a guest user will see when they connect. To end the session, just type "exit" and “ctrl+c” to stop the connection. You can also navigate to the URL provided when you share (see Figure 9-11):

A416092_1_En_9_Fig11_HTML.jpg
Figure 9-11. Vagrant share via web browser

Share with SSH Access

In this section, we will set our Vagrant box with SSH access for others to connect. This is useful for pair programming, debugging, and working with quality assurance.

Similar to the way we shared HTTP in the previous section, we can share and provide SSH access to guests. You do so by sharing with the SSH flag:

$ vagrant share --ssh

To connect, add the SSH flag:

$ vagrant connect spoiled-crocodile-4501 --ssh

When you share, Vagrant will ask you for a password that you will provide to the guest user for security reasons.

Vagrant can help you ensure that you share your whole project or only part of the project with other members of your team, and can help in the deployment process, which makes it a great tool to add to your arsenal of helpful built script tools.

You can read more about sharing from the Vagrant docs: https://www.vagrantup.com/docs/share/

Provision AngularJS Projects

We have created a basic "bootstrap.sh" file for setting up Apache and installing an entire project for learning purposes. However, for Node.js and AngularJS projects, we want to be able to set the project with the tools needed, such as Grunt, Gulp, npm, Node.js, and Git. We don't want all of our node modules and code downloaded, but we do want them to be installed on each machine. This is why we set a "package.json" file to begin with; it stores all of the modules that the project needs, so we don't need to upload all of them. To achieve this, we can use "Puppet" (not covered in this book), which Vagrant supports, or we can extend our "bootstrap.sh" file. Open the “bootstrap.sh” file we created and paste the following code:

#! /bin/bash
if [ ! -f /home/vagrant/isSettingInstalled ]
then
  echo "UPDATING APT-GET"
  apt-get -qq update
  echo "INSTALLING NODE.JS"
  apt-get -qq -y install Node.js
  echo "INSTALLING NPM"
  apt-get -qq -y install npm
  echo "INSTALLING GIT"
  apt-get -qq -y install git


  echo "CLONING CODE"
  cd /home/vagrant
  git clone https://github.com/angular/angular-seed
  cd angular-seed
  git checkout -f step-0


  echo "INSTALLING MODULES"
  sudo npm install
  echo "STARTING NPM"
  sudo npm start


  touch /home/vagrant/isSettingInstalled
  echo "COMPLETE"
else
  echo "SETTINGS ALREADY INSTALLED"
fi


With this code, we have created a flag to check whether the installation has already taken place or not. We have named the flag file “isSettingInstalled”. We have installed all of the tools we will need via “apt-get,” cloned the “angular-seed” project, installed the npm module, and run the npm start command. Instead of setting a box via the command line every time, we can simply connect to Vagrant and be up and running quickly. You can see how powerful Vagrant can be when used to set up environments quickly.

Summary

In this chapter, we focused on build scripts, created a new Node.js module, and installed Browserify and compiled a Browserify bundle file. Then, we used the bundle file, which included the Node.js module, and used that module in a new AngularJS project. We took a look at the new ES6 changes and learned how to utilize it today on any JavaScript engine using Babelify. We learned how to set up Babel in WebStorm and began writing ES6 code, then continued to learn more about Grunt and created a Grunt file with Babel task. Next, we installed Grunt plugs and ran a Babel task. We also created a Grunt task with the ability to Babelify, Browserify, and create a Grunt File Watcher.

We continued with installing Gulp and learned the differences between Grunt and Gulp. We created a Gulp task, installed Gulp plugins, and ran the Gulp tasks. We then looked at the installation of Webpack, created a Webpack config file, and learned how to use a watcher in Webpack. We learned how to use Webpack for transpiling ES6 code and also learned how to use the Webpack CSS loader.

Lastly, we reviewed how to set up a Vagrant VM, installed Vagrant, set a Virtual Machine for sharing access, and set up custom SSH scripts for AngularJS and Node.js projects. Selecting the right tools for the job is all about personal preference, as well as team knowledge and experience; it is an extremely important part of building any app.

In the next chapter we will be covering platform deployment.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.133.160