1.14. Working with important Gulp recipes

We learned task execution order management in preceding recipe and this knowledge, we will use to implement following few important Gulp tasks:

  • Assert coding convections adherence
  • Documentation
  • Compile and Bundle a TypeScript solution
  • Preparing a TypeScript solution for a release
  • TypeScript and Babel

Getting ready

Before getting started you must install Babel using npm for Typescript and Babel Gulp task above. $ npm install babelify –save-dev

How to do it

The first tasks that we are going to implement will be in charge of the validation of the adherence of our TypeScript code to some code convections.

  1. Assert coding convections adherence
    gulp.task('lint', function () {
     const input = ['src/**/**.ts'];
     return gulp.src(input)
         .pipe(tslint({ formatter: 'verbose' }))
         .pipe(tslint.report());
    });
    
  2. Documentation
    If you are working on a TypeScript library that will be consumed by other developers, it is recommended to write as much documentation as possible to avoid an avalanche of issues caused by the lack of documentation. Fortunately, there is a tool known as TypeDoc, which can be used to generated documentation for TypeScript projects. We can auto-generate the documentation of a TypeScript library using the following Gulp task:
    gulp.task('document', function () {
     const input = 'src/main.ts';
     const output = 'docs';
     return gulp.src(input)
         .pipe(typedoc({
             target: 'ES5',
             module: 'commonjs',
             includeDeclarations: false,
             out: output,
             name: settings.projectName,
             version: true
         }));
    });
    
  3. Compile and Bundle a TypeScript solution
    The following tasks as input all the TypeScript files under the source folder as input and compiles them into JavaScript. The following Gulp task transforms some TypeScript code into JavaScript code using tsify. Once we have JavaScript code, it is passed to Browserify to create one unique JavaScript file.
    gulp.task("bundle", function() {
      const mainTsFilePath = "src/main.ts";
      const outputFolder   = "bundle/src/";
      const outputFileName = settings.projectName + ".min.js";
      const bundler = browserify({
     debug: true,
     standalone : settings.projectName
      });
      // TS compiler options are in tsconfig.json file
      return bundler.add(mainTsFilePath)
                 .plugin(tsify)
                 .bundle()
                 .pipe(source(outputFileName))
                 .pipe(buffer())
                 .pipe(gulp.dest(outputFolder));
    });
    
  4. Preparing a TypeScript solution for a release
    Before deploying an application to production or releasing a library we should optimize it to be as just as possible and add a license to it and we can use Gulp to automate those tasks. We are going to modify the bundle tasks and add a few new steps. The new steps will take a stream, which contains the output of the previous step and process it to generate a new output stream as result.
    gulp.task('bundle', function () {
     const mainTsFilePath = 'src/main.ts';
     const outputFolder = 'bundle/src/';
     const outputFileName = settings.projectName + '.min.js';
     const pkg = require('./package.json');
     const banner = [
         '/**',
         ' * <%= pkg.name %> v.<%= pkg.version %> - <%= pkg.description %>',
         ' * Copyright (c) 2017 <%= pkg.author %>',
         ' * <%= pkg.license %>',
         ' */', ''
     ].join('\n');
     const bundler = browserify({
         debug: true,
         standalone: settings.projectName
     });
     // TS compiler options are in tsconfig.json file
     return bundler.add(mainTsFilePath)
         .plugin(tsify)
         .bundle()
         .pipe(source(outputFileName))
         .pipe(buffer())
         .pipe(sourcemaps.init({ loadMaps: true }))
         .pipe(uglify())
         .pipe(header(banner, { pkg: pkg }))
         .pipe(sourcemaps.write('./'))
         .pipe(gulp.dest(outputFolder));
    });
    
  5. TypeScript and Babel
    Babel is a tool that can be used to compile ES6 JavaScript into ES5 JavaScript. It is sometimes compared with TypeScript because both compilers allow us to use the JavaScript of tomorrow (ES6) in the browsers from the past (ES5). Babel is not strongly typed and has some weak points when compared against TypeScript, however Babel has better support for ES6 compatibility than TypeScript. The good news is that we can use both TypeScript and Babel at the same time so we can combine the best of both tools. We are going to return to the bundle task previously explained in this chapter to add one step more:
    gulp.task("bundle", function() {
      // ...
      const babelifyConfig = { extensions: ['.js','.jsx','.ts','.tsx'] 
      // TS compiler options are in tsconfig.json file
      return bundler.plugin(tsify)
                 // Added this line and target es6
                 .transform(babelify.configure(babelifyConfig)) 
                 .add(mainTsFilePath)
                 .bundle()
                 .pipe(source(outputFileName))
                 .pipe(buffer())
                 .pipe(sourcemaps.init({ loadMaps: true }))
                 .pipe(uglify())
                 .pipe(header(banner, { pkg : pkg } ))
                 .pipe(sourcemaps.write("."))
                 .pipe(gulp.dest(outputFolder));
    });
    

How it works

The above Gulp tasks are important for you to understand for TypeScript development documentation and release.

  1. As you can see, the task ‘Assert coding conventions adherence’ takes all the TypeScript files under the source folder as input and used the tslint plugging to ensure that our code adheres to the best coding conventions.
  2. The task ‘Documentation’ takes the main TypeScript file in the entire applications and the TypeScript compiler options as input and returns the documentation as output. The documentation is stored in the docs folder and uses HTML as its format.

Fig.1

  1. The task "Compile and Bundle a TypeScript solution" takes the root module in the application and uses it to trace a dependency tree. Once the dependency tree has been traced, Browserify is able to compile and bundle all the dependencies into one single file using. The TypeScript compilation is provided by a Browserify plugin known as tsify.
    The output files use a format known as universal module definition or UMD, which can be executed in both Node.js and web browsers.
  2. The Gulp task Preparing a TypeScript solution for a release is an extension of the bundle tasks that we explored in earlier step. In this new task, we are taking the output of the Browserify’s bundle method and generates a compressed version of it. The task also adds a copyright header to the file and generates source maps. Source maps are a kind of mapping file which allow us to link the final result (minified ES5 code) with the original input (the TypeScript code). Some web browsers will display TypeScript code instead of JavaScript code if source maps are available, which can be invaluable if we are trying to debug an issue.
  3. The task TypeScript and Babel above has added an additional step to our build. The additional step uses Babel to transform ES6 code into ES5 so it can be executed in old browsers. You must configure your tsconfig.json file to ensure that the TypeScript compiler targets ES6.
    "target": "es6"
    

    The ES6 code generated by TypeScript is then transformed into ES5 code by Babel. It is important to compile the TypeScript before the ES6 code is compiled.
    After generating the ES5 code, we use Browserify to bundle the application and uglify to compress it just like we did in the previous examples.

See also


Shiv Kushwaha

Author/Programmer