5

For Angular2 project, In gulp how do I concat all my JavaScript files that were generated from typescript and add them to my index.html file.

I'm using Angular2, typescript and gulp.

Currently I'm not concatenating the javascript files it generates from the typescript files.

I'm having trouble trying to do this and add them to my index.html file.

In addtion once I've done this I need cache busting in order to get the browsers to keep request the javascript file.

This is my index.html file:

<!DOCTYPE html>
<html lang="en" prefix="og: http://ogp.me/ns#" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>My App</title>
    <base href="/"></base>
    <meta content="IE=edge, chrome=1" http-equiv="X-UA-Compatible"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=0.5, user-scalable=yes"/>

    <!-- Css libs -->
    <link rel="stylesheet" type="text/css" href="/css/styles.css" /> 

    <!-- inject:css -->    
       <!-- <link rel="stylesheet" href="/css/styles.81dd14d5.css">     -->
    <!-- endinject -->

    <!-- Js libs -->    
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.2/es6-shim.min.js"></script>    
    <script type="text/javascript" src="/safariPolyFix.js"></script>    
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.18.4/system.src.js"></script>   

    <script>
        System.config({
            transpiler: 'typescript',
            defaultJSExtensions: true,  
            typescriptOptions: {
                emitDecoratorMetadata: true,
            },          
            packages: {
                'angular2-google-maps': {
                  defaultExtension: 'js'
                }
            }
        });       
    </script>

    <script type="text/javascript" src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script>
    <script type="text/javascript" src="https://code.angularjs.org/tools/typescript.js"></script>
    <script type="text/javascript" src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>

    <script type="text/javascript" src="https://code.angularjs.org/2.0.0-beta.0/angular2.js"></script>
    <script type="text/javascript" src="https://code.angularjs.org/2.0.0-beta.0/router.js"></script>
    <script type="text/javascript" src="https://code.angularjs.org/2.0.0-beta.0/http.js"></script>  

    <script type="text/javascript" src="/firebase/firebaseNew.js"></script>   
  </head>

  <body id="container">

    <app></app>

    <script type="text/javascript">  
      System.import('/app/app.component.js');
    </script>
  </body>
</html>

This is my gulp file:

var gulp = require('gulp');
var sass = require('gulp-sass');
var inject = require('gulp-inject');
var del = require('delete');
var minifyCss = require('gulp-minify-css');
var uglify = require('gulp-uglify');

var CacheBuster = require('gulp-cachebust');
var cachebust = new CacheBuster();

//1. Delete styles.css
gulp.task('deleteStyle', function() {

    setTimeout(function () {
        del.promise(['src/css/styles.*.css'])
          .then(function() {            
                console.log("Deleted original styles.css");         
                return true;
          });      
    }, 1000);  

});

//2. Make new styles.css
gulp.task('addStyles', function() {

    setTimeout(function () {

        gulp.src('src/sass/styles.scss')
            .pipe(sass().on('error', sass.logError))
            .pipe(minifyCss({compatibility: 'ie8'}))
            .pipe(cachebust.resources())
            .pipe(gulp.dest('src/css/'))

        console.log("Added and minifyCss style.css");     

    }, 3000); 

});

//3. Inject new style.css to index.html file
gulp.task('injectStyle', function() {

    setTimeout(function () {
          var target = gulp.src('src/index.html');
          var sources = gulp.src(['src/css/styles.*.css'], {read: false});

          console.log("Injected stylesheet to index.html file");

          return target.pipe(inject(sources))
            .pipe(gulp.dest('./src'));

    }, 5000); 

});

//Use for product release.
gulp.task('default', ['deleteStyle', 'addStyles', 'injectStyle']);

This is my current attempt at concat the js with cache busting, which works fine now. I just dont know how to wire up this all.46f5af42.js file to the index.html?

Here's the gulp code for this:

gulp.task('getAllJsFiles', function() {

    setTimeout(function () {

        gulp.src('src/app/**/**/*.js')
            .pipe(concat('all.js'))
            .pipe(cachebust.resources())
            .pipe(gulp.dest('src/js'));

    }, 8000); 

});

I've also managed to get that concat js and cache busted js file into the index.html:

<!-- inject:js -->
<script src="/src/js/all.46f5af42.js"></script>
<!-- endinject -->

I'm not sure how to wire this up though to get it working?

This is my current console:

enter image description here

If someone could help me add the changes to my existing code that would be great, as I dont want to download the new angular2 seed app as it would take me ages moving my app across.

Thank you in advance.

QoP
  • 27,388
  • 16
  • 74
  • 74
AngularM
  • 15,982
  • 28
  • 94
  • 169
  • Currently I just get a blank screen and no console errors or gulp errors. Seems like I just need to wire the js file up correctly now – AngularM Apr 24 '16 at 10:52
  • You don't need to concat the .js files, check the index.html on network tab and you will see that system.js already concat all the .js files and includes only 1 file into the browser. If you want to do something different with that file cache/minify probably you need too look into system.js – Tiberiu Popescu Apr 24 '16 at 12:58
  • I just had a look and its not concat the js files its loading them individually – AngularM Apr 24 '16 at 13:08
  • Do you have any good examples of the concat using system.js and then cashe busting that js file? – AngularM Apr 24 '16 at 13:12
  • Ignore me, that's right sorry. I was not looking in the right place, yes it loads all the files. – Tiberiu Popescu Apr 24 '16 at 13:20

2 Answers2

4

In fact, you can't concat them like this because by default they correspond to anonymous modules. You need to leverage the outFile to leverage this. This way, all modules will be compiled into a single JS file and they won't be anonymous modules but registered by names.

Here is a sample. Have a look at the first parameter of the System.register function.

  • Anonymous modules

    System.register([ 'dep1', 'dep2', function(exports_1, context_1) {
      (...)
    }
    
  • Modules registered by names

    System.register('module1', [ 'dep1', 'dep2', function(exports_1, context_1) {
      (...)
    }
    
    System.register('module2', [ 'dep1', 'dep2', function(exports_1, context_1) {
      (...)
    }
    

Here is a sample of use within a gulp file:

gulp.task('app-bundle', function () {
  var tsProject = ts.createProject('tsconfig.json', {
    typescript: require('typescript'),
      outFile: 'app.js'
  });

  var tsResult = gulp.src('app/**/*.ts')
                .pipe(ts(tsProject));

  return tsResult.js
                .pipe(uglify())
                .pipe(gulp.dest('./dist'));
});

Finally you could use htmlreplace to update the script elements with created JS files. Here is sample:

gulp.task('html', function() {
  gulp.src('index.html')
    .pipe(htmlreplace({
      'vendor': 'vendors.min.js',
      'app': 'app.min.js',
      'boot': 'boot.min.js'
    }))
    .pipe(gulp.dest('dist'));
});

This question could help you:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Hi I'm really struggling to get anyones examples to work. Do you have a very small test app of this working? – AngularM May 02 '16 at 21:16
  • In short the problem in trying to solve is the angular 2 caching with my js. Currently my live website shows all the typescript files individually rather than concat – AngularM May 03 '16 at 07:44
  • Hey! I see well your problem. You mean for your application typescript files? – Thierry Templier May 03 '16 at 07:47
  • This is the website, thepoolcover.co.uk, have a look at source files. Your see all the typescript is in separate files and only the css has cache busting and concat. I need the same with my ts files – AngularM May 03 '16 at 07:48
  • Thanks Thierry, savour! – AngularM May 03 '16 at 07:49
  • 1
    @AngularM I pushed the corresponding project on github. See this link: https://github.com/templth/angular2-packaging. Before executing the `$(npm bin)/gulp html-replace`, execute `npm install`. – Thierry Templier May 03 '16 at 10:17
  • I downloaded the code and did npm install and npm start and it all seems to work. How do I create the build? – AngularM May 03 '16 at 13:33
  • Great! Simply execute gulp in the root folder of the project: `$(npm bin)/gulp html-replace` – Thierry Templier May 03 '16 at 13:34
  • whats the gulp command? I wrote gulp in git bash and command wasnt found – AngularM May 03 '16 at 13:35
  • You need to use `$(npm bin)/gulp` because gulp isn't installed globally. – Thierry Templier May 03 '16 at 13:36
  • If you want to install it globally: `npm install gulp -g` – Thierry Templier May 03 '16 at 13:36
  • I ran gulp html-replace and it made the dist folder with the 3 files. How do I check that this runs? the dist index file, as if it was going live – AngularM May 03 '16 at 13:38
  • 1
    To test this, I installed the http-server server tool (`npm install http-server -g`). Within the `dist` folder, run the command: `http-server . -c-1` (`-c-1` is to disable the cache). Access the application with the address: http://localhost:8080. – Thierry Templier May 03 '16 at 13:40
  • 1
    Thanks Thierry that worked well. I now need to add this to my live project which may cause issues when combing. Because, I'm using Firebase. I will let you know. – AngularM May 03 '16 at 13:47
  • Also, I've made a spin off question based on your code: http://stackoverflow.com/questions/37006340/gulp-does-anyone-know-how-to-cache-bust-a-js-file – AngularM May 03 '16 at 13:59
  • for the boot.ts file do I need to reference all services, models, filters etc ?# – AngularM May 03 '16 at 14:31
2

You can set the outFile option in your tsconfig.json in order TypeScript to concatenate and emit output to a single file and then reference that file in your index.html.

In the gulpfile.js:

function buildApp() {
return gulp.src('./app/app.ts')
    .pipe(tsc({
        typescript: require('typescript'), // In my package.json I have "typescript": "~1.8.0-dev.20151128"
        target: 'ES5',
        module: 'system',
        experimentalDecorators: true,
        emitDecoratorMetadata: true
        outFile: 'app.js'
    }))
    // Here in my pipe I only have app.js
    .pipe(gulp.dest('./dist'));
}

And in your index.html:

<script src="./dist/scripts/app.js"></script>

Source How to concat multiple transpiled JS files into a bundle.

Paweł Hajduk
  • 401
  • 1
  • 5
  • 14
  • I ran your code and I get a git bash error when running gulp called: "Reference Error: tsc is not defined". Do I need to pm install tsc and import it? if so whats the name of the import etc? – AngularM May 02 '16 at 19:01
  • I've managed to run that code and all it does is move all my code to a dist folder and causes lots of errors in git bash e.g. cannot find name Promise or cannot find certain modules – AngularM May 02 '16 at 19:10
  • This is my current gulp code for your example: gulp.task('test', function() { return gulp.src('./src/app/app.component.ts') .pipe(tsc({ typescript: require('typescript'), // In my package.json I have "typescript": "~1.8.0-dev.20151128" target: 'ES5', module: 'system', experimentalDecorators: true, emitDecoratorMetadata: true, outFile: "app.js" })) // Here in my pipe I only have app.js .pipe(gulp.dest('./dist')); }); – AngularM May 02 '16 at 19:15
  • Looks like it cannot find modules or names imported? not sure why this is. – AngularM May 02 '16 at 19:26