-1

I am trying to get my angular application to the point where it is ready for distribution and I have managed to create 2 bundles, one for my angular application and one for my dependencies (which include the angular framework and the rxjs framework). I am using systemjs builder to do the bundling and using gulp to run the builder. Both bundles are produced and my custom bundle (which contains my code) is loaded by the front end but the vendor/dependency bundle is ignored and the dependencies are still loaded from the node_modules folder.

I'm thinking that it is an issue with my dist-system-config.js file that I use in the final distribution.

My solution is based mostly on this previous answer with a couple of exceptions like not including/inlining my html templates and adding node_modules to the exclusion path of the dependencies.

I will include everything I believe is relevant to the problem, if more is needed please let me know.

Just to reiterate, the application loads and runs OK but instead of loading the dependencies from dependencies.bundle.js they are loaded from the original location(s) in the node_modules folder. The app.bundle.js is loaded without any issues.


Index.html

<script src="/node_modules/core-js/client/shim.min.js"></script>
<script src="/node_modules/zone.js/dist/zone.min.js"></script>
<script src="/node_modules/reflect-metadata/Reflect.js"></script>
<script src="/node_modules/systemjs/dist/system.js"></script>

<script src="/bundles/dependencies.bundle.js"></script>
<script src="/bundles/app.bundle.js"></script>
<script src="/Scripts/dist-system-config.js"></script>

<script>
    System.import('app/boot').catch(function(err) {
        console.error(err);
    });
</script>

app/boot.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

Scripts/dist-system-config.js

System.config({
    baseURL: '/',
    paths: {
        'npm:': 'node_modules/'
    },
    map: {
        'app': 'dist/app',

        // angular bundles
        '@angular/core': 'npm:@angular/core/bundles/core.umd.min.js',
        '@angular/common': 'npm:@angular/common/bundles/common.umd.min.js',
        '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.min.js',
        '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.min.js',
        '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.min.js',
        '@angular/http': 'npm:@angular/http/bundles/http.umd.min.js',
        '@angular/router': 'npm:@angular/router/bundles/router.umd.min.js',
        '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.min.js',
        'rxjs': 'npm:rxjs'
    },
    packages: {
        'app': { main: './boot.js', defaultExtension: 'js' },
        'rxjs': { defaultExtension: 'js' }
    }
});

gulpfile.js

var gulp = require('gulp'),
    tsc = require('gulp-typescript'),
    Builder = require('systemjs-builder');

gulp.task('bundle', ['bundle-app', 'bundle-dependencies'], function(){});

gulp.task('app-components', function () {
    return gulp.src('Scripts/app/**/*.ts')
        .pipe(tsc({
            "target": 'es5',
            "module": 'commonjs',
            "moduleResolution": 'node',
            "lib": [ 'es2015', 'dom', 'es2015.iterable' ],
            "sourceMap": true,
            "emitDecoratorMetadata": true,
            "experimentalDecorators": true,
            "removeComments": true,
            "noImplicitAny": false
        }))
        .pipe(gulp.dest('dist/app'));
});

gulp.task('bundle-app', ['app-components'], function() {
    // optional constructor options
    // sets the baseURL and loads the configuration file
    var builder = new Builder('', 'Scripts/dist-system-config.js');

    return builder
        .bundle('dist/app/**/* - [node_modules/@angular/**/*.js] - [node_modules/rxjs/**/*.js]', 'bundles/app.bundle.js', { minify: true})
        .then(function() {
            console.log('Build complete');
        })
        .catch(function(err) {
            console.log('Build error');
            console.log(err);
        });
});

gulp.task('bundle-dependencies', ['app-components'], function() {
    // optional constructor options
    // sets the baseURL and loads the configuration file
    var builder = new Builder('', 'Scripts/dist-system-config.js');

    return builder
        .bundle('dist/app/**/*.js - [dist/app/**/*.js]', 'bundles/dependencies.bundle.js', { minify: true})
        .then(function() {
            console.log('Build complete');
        })
        .catch(function(err) {
            console.log('Build error');
            console.log(err);
        });
});

package.json (Relevant versions only)

"@angular/***": "4.2.6",
"canonical-path": "0.0.2",
"gulp": "3.9.1",
"gulp-typescript": "^3.2.0",
"rimraf": "2.6.1",
"rxjs": "5.4.2",
"systemjs": "0.20.14",
"systemjs-builder": "0.16.9",
"typescript": "2.4.1",
Igor
  • 60,821
  • 10
  • 100
  • 175
  • `'app': { main: './main.js', defaultExtension: 'js' }` in my configuration is `{ main: 'app/boot.js', defaultExtension: 'js' }` so if your boot file is named `main.js` instead of `boot.js` then it should be `{ main: 'app/main.js', defaultExtension: 'js' },`. And no need for `'main': 'dist/app/main.js',` (I guess) – Ankit Singh Jul 12 '17 at 05:10
  • @AnkitSingh - thank you, I updated the `Scripts/dist-system-config.js` based on your comment but am still encountering the same behavior. – Igor Jul 12 '17 at 10:16
  • @AnkitSingh - would referencing the `umd` bundles from angular have anything to do with it? (*instead of another .js file*) – Igor Jul 12 '17 at 10:37
  • @AnkitSingh - see the answer below by Louis, the load/script tag order matters. Thank you again for your help and previous answer on the other thread (*I did up-vote it*). – Igor Jul 12 '17 at 11:21
  • Oh I see (I was shooting in the air, hvn't used SystemJS for months now) ... You're welcome. .... Well, what can I say, Thank you very much! :) – Ankit Singh Jul 12 '17 at 11:51
  • @AnkitSingh - By the way, is the reason you have not used it in a while because you are using something else for bundling? If so might I ask what are you using now? – Igor Jul 12 '17 at 12:32
  • 1
    sure, Angular CLI, it just works without much hassle. See the accepted answer above my answer on that Other question for more info. or you can use [This Starter](https://github.com/AngularClass/angular-starter) from @AngularClass – Ankit Singh Jul 12 '17 at 12:36

1 Answers1

2

Configure SystemJS before you load any bundle.

I was able to reproduce your problem. What I found is that if the bundles are loaded before SystemJS is configured, then SystemJS ignores the bundles that have been loaded. If load the bundles after configuring SystemJS then everything is fine. So you should have your scripts in this order:

<script src="/Scripts/dist-system-config.js"></script>
<script src="/bundles/dependencies.bundle.js"></script>
<script src="/bundles/app.bundle.js"></script>

Here's a comment by SystemJS' author (Guy Bedford) explaining why:

You need to configure SystemJS first before loading bundles because bundles run through normalization, and hence need configuration present in order to normalize correctly.

Louis
  • 146,715
  • 28
  • 274
  • 320