node package manager

ak-gulp

akGulp

Conservative and basic Gulp module for enterprise Angular 1 projects.

Motivation

Why should you use this rather conservative module to power your Angular 1 build process?

You shouldn't in an ideal world were you could do everything as you please and move on to webpack and so on. However in enterprise environments there are often restrictions (e.g. downloading binaries on your build server), other requirements (e.g. stability and documentation) or your colleagues are just not up to the churn.

If you look at other Gulp modules, you will find them often to be convoluted and to be showcases of what you could do if you push the limits.

This module aims to be different: Basic, conservative and documented.

  1. Basic: Only tasks which are necessary to produce a sensible distribution of the application are included.
  2. Conservative: The plugins are known to work and don't do any funky stuff like downloading binaries.
  3. Documented: Task have a concise documentation of what they do, how they should be used and what the requirements are. Further documentation can be found in the code.

This module is ideally customer-based, i.e. a customer agrees on a default stack for their common projects and the build tooling is adapted accordingly. Of course it could also be used as project-based module for one ore more Angular applications.

I used my initials as prefix in order to emphasize the high probability for you to customize the module based on your customer/company/project. So change it to your customer/project prefix and do the necessary adaptions.

A typical workflow for a fork would be to:

  1. Identify the infrastructural situation, what does it (dis-)allow? Adapt.
  2. Define the stack. Adapt.
  3. Fork it as node module or integrate it as a folder.

Stack

These are the assumptions about the stack if you just want to use the module out-of-the box.

General

Testing

The assumption and best practice is to do consumer-driven API- and E2E-tests in a separate project.

Dependencies

In alphabetical order.

Why I didn't you use...

  • ... Sass instead of Less. Unfortunately, Less is more predominant in the enterprise world. Mainly, because of Bootstrap. I hope that this will change with Bootstrap 4.
  • ... Browsersync instead of gulp-webserver. At the time of writing this library somewhere down the dependency chain of browsersync (socket.io, engine.io, and so on) there was a hardcoded URL which basically meant timeouts with a enterprise firewall. It might be fixed now, so if there's good reason, I might re-evaluate it.
  • ... gulp-imagemin or another image optimization plugin. Downloads binaries for compression which is often prohibited.
  • ... PhantomJS as a test browser. The popular headless browser has many pecularities but nevertheless it is complicated to use it without downloading the binaries. There are workarounds, you will need to choose one if you want to use it.
  • Jasmine instead of Mocha. Mocha allows for your own assertion and mocking library, handles asynchronous tests better, allows to show deep diffs in reports and is more fluent for BDD.

Integration

As a node module

This has rather huge advantages and should be preferred to the integrated folder. There are three possibilities here:

  1. In the very unlikely case you didn't need to make any adaptions and never plan to make any (beside basic ones via pull requests) you could have installed it via npm i -D akGulp which isn't recommended.
  2. You've forked akGulp and now have an adapted version in own repository. In this case you will probably need to use the repository URL in the devDependencies of your package.json. This is not recommended since installations will take time, there will be no caching and no semver. Also you would probably need an SSH connection to the repository (and therefore the server) which is often an issue for the ops.
  3. You've forked it and have a private npm registry (e.g. Nexus in which you've published your fork. Now you have everything: caching, security and semver. Good job.

config.js

Here you can overwrite the paths if your folder structure differs or specify additional and different options for the gulp plugins.

The only required entry is the moduleName which is used for the partials as Angular module name and is the same as the root module in your app.js:

module.exports = {
    moduleName: 'my'
};

The paths properties overwrite the properties in path.js and the consts properties overwrite the properties in consts.js.

gulpfile.js

You can define you own tasks or overwrite existing ones but it must at least have the following:

'use strict';
 
var akGulp = require('ak-gulp');
var gulp = require('gulp');
 
var config = require('./config');
var karma = require('./karma');
 
config.karma = karma;
 
akGulp(gulp, config);

To overwrite or create a task you define it in this file on the gulp object before you pass it.

karma.js

This is the configuration for Karma and is required to be a valid module that exports an object. There are two major differences between this custom karma configuration and the default kamra.conf.js you might know. Dependencies and browsers have to specified with a special syntax. Everything else is like the default Karma configuration.

Dependencies which would normally just be the files property in Karma must be specified with the deps property since

  • config.paths.tests
  • config.paths.app.scripts
  • config.paths.app.partials

are added automatically. Here's an example:

'use strict';
 
module.exports = {
    deps: [
        'node_modules/angular/angular.js',
        'node_modules/angular-mocks/angular-mocks.js',
        'test/setup.js'
    ]
};

Browsers which would normally just be an array of strings are separated into production for your CI and development for your local environment. Here an example:

browsers: {
    production: ['IE'],
    development: ['Chrome']
}

Possible values are Chrome, Firefox and IE.

Structure

The default minimal folder structure of the project is:

    src/
        app/
            index.html
        assets/
            images/
            fonts/
            ...
        styles/
            main.less
    test/
        **/*.spec.js

Have a look at paths.js if you want to overwrite it.

As a folder

This is the preferred approach if you don't plan on heavily modularizing your applications.

You will need to structure your project according to the previous section and make following adaptions.

  1. Clone this repository and move the lib-folder to your project folder and rename it to gulp.
  2. Reference the main file in your gulpfile.js: var akGulp = require('./lib/index');
  3. Add all dependencies from this module to the package.json's devDependencies and remove duplicates.

For an example see akSkeleton.

Tasks

This is a description of commonly used tasks during development. An extensive list and documentation can be found at the respective website. The same documentation can also be generated by npm run doc.

  • gulp (defaults to gulp dev): Launches a server hosting and watching the development files. The server reacts on changes on the development files and automatically does script injection if a new file is found or runs the preprocessor, tests and linter on changes.

  • gulp build: After successfully running the tests it builds the distribution which produces following folder structure:

    build/
        dist/
            assets/
                fonts/
                images/
                ...
            scripts/
                main-{rev}.js
                main-{rev}.js.map
                vendor-{rev}.js
                vendor-{rev}.js.map
            styles/
                main-{rev}.css
                vendor-{rev}.css
            index.html
            VERSION
        reports/
            coverage/
                ...
            unit.xml

There's also the temporary folder which is used for development and intermediary files:

    build/
        .tmp/
            assets/
                fonts/
                images/
                ...
            styles/
                main.css
            index.html
            partials.min.js

Production flag

The production flag is a environment variable which name is defined in consts.productionFlag (default: PRODUCTION) that makes pipes break on lint and plugin errors. It also enables the usage of different test browsers.

Development

Local development is done with npm link in this projects folder and then linking it via npm link ak-gulp into the implementer's project folder.

Scripts

There are three npm scripts:

  1. npm run clean: Deletes doc/, node_modules/ and npm-debug.log
  2. npm run lint: Lints lib/ with ESlint
  3. npm run doc: Generates the documentation to doc/

Structure

consts.js

Here are several constants like plugin options or the production flag.

index.js

This is the entry point of the module, everything gets set up here.

paths.js

The default path structure as shown above. Also there is an array which allows to specify unhandled assets via negative glob.