Guide on packaging an Angular 2 Typescript application with Gulp and SystemJS

In my Angular 2 project, I am using Typescript with SystemJS for module loading and Gulp as a task runner. Currently, the project is running on Angular RC2 but the same issue persists with RC1. I followed the steps provided in brando's answer here.

Upon bundling my application and loading the website for the first time, SystemJS throws this error:

Error: http://localhost:57462/app/app.bundle.js detected as register but didn't execute.

The application functions properly but having the error in the console is not ideal.

I tested the configuration on an empty project and encountered the same problem, indicating that the issue lies within the configuration itself.

Here is the Gulpfile:

var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var concat = require('gulp-concat');
var typescript = require('gulp-typescript');
var jspm = require('gulp-jspm-build');

gulp.task('compile:ts', function () {
    return gulp.src(['./appTS/**/*.ts'])
        .pipe(sourcemaps.init())
            .pipe(typescript({
                noEmitOnError: true,
                target: 'ES5',
                removeComments: false,
                experimentalDecorators: true,
                emitDecoratorMetadata: true,
                module: 'system',
                moduleResolution: 'node'
            }))
        .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('./app/'));
});

gulp.task('copy:vendor', function () {
    return gulp.src([
        'node_modules/systemjs/dist/system-polyfills.js',
        'node_modules/reflect-metadata/Reflect.js',
        'node_modules/core-js/client/shim.min.js',
        'node_modules/zone.js/dist/zone.min.js',
        'node_modules/systemjs/dist/system.js',
        'node_modules/rxjs/bundles/Rx.js'
    ]).pipe(gulp.dest('./assets/vendor/'));
});

gulp.task('bundle:app', ['compile:ts'], function () {
    return jspm({
        bundleOptions: {
            minify: true,
            mangle: false
        },
        bundleSfx: true,
        bundles: [
            { src: './app/main.js', dst: 'bundle.js' }
        ]
    })
    .pipe(gulp.dest('./app/'));
});

gulp.task('bundle', ['bundle:app', 'copy:vendor'], function () {
    return gulp.src([
        './assets/vendor/Reflect.js',
        './assets/vendor/shim.min.js',
        './assets/vendor/zone.min.js',
        './app/bundle.js'])
    .pipe(concat('app.bundle.js'))
    .pipe(gulp.dest('./app/'))
});

gulp.task('default', ['bundle']);

var packages = {
    app: {
        format: 'register',
        defaultExtension: 'js'
    },
    
    "symbol-observable": { main: 'index.js', defaultExtension: 'js' },
    "reflect-metadata": { main: 'Reflect.js', defaultExtension: 'js' }
};

var ngPackageNames = ['common',
                      'compiler',
                      'core',
                      'http',
                      'platform-browser',
                      'platform-browser-dynamic',
                      'router',
                      'router-deprecated',
                      'upgrade'];

ngPackageNames.forEach(function (element, index, array) {
    packages['@angular/' + element] = { main: 'bundles/' + element + '.umd.min.js', defaultExtension: 'js' };
});

System.config({
    main: 'dispel.bundle.min',
    defaultExtension: 'js',
    format: 'register',
    packages: packages,
    baseURL: "/",
    defaultJSExtensions: true,
    transpiler: false,
    paths: {
        "node_modules*": "node_modules*",
        "@angular*": "node_modules/@angular/*"
    },
    map: {
        "@angular": "node_modules/@angular",
        "symbol-observable": "node_modules/symbol-observable",
        "ng2-translate": "node_modules/ng2-translate",
        "es6-shim": "node_modules/es6-shim",
        "reflect-metadata": "node_modules/reflect-metadata",
        "rxjs": "node_modules/rxjs",
        "zone.js": "node_modules/zone.js"
    }
});

Answer №1

Have you experimented with utilizing SystemJS Builder in your bundle:app gulp task instead of jspm?

Here is a simplified approach to bundling Tour of Heroes version 2.0.0-rc.1 (source, live example).

gulpfile.js

var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var concat = require('gulp-concat');
var typescript = require('gulp-typescript');
var systemjsBuilder = require('systemjs-builder');

// Compile TypeScript app to JS
gulp.task('compile:ts', function () {
  return gulp
    .src([
        "appTS/**/*.ts",
        "typings/*.d.ts"
    ])
    .pipe(sourcemaps.init())
    .pipe(typescript({
        "module": "system",
        "moduleResolution": "node",
        "outDir": "app",
        "target": "ES5"
    }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('app'));
});

// Generate systemjs-based bundle (app/app.js)
gulp.task('bundle:app', function() {
  var builder = new systemjsBuilder('public', './system.config.js');
  return builder.buildStatic('app', 'app/app.js');
});

// Copy and bundle dependencies into one file (vendor/vendors.js)
// system.config.js can also be bundled for convenience
gulp.task('bundle:vendor', function () {
    return gulp.src([
        'node_modules/zone.js/dist/zone.js',
        'node_modules/reflect-metadata/Reflect.js',
        'node_modules/systemjs/dist/system-polyfills.js',
        'node_modules/core-js/client/shim.min.js',
        'node_modules/systemjs/dist/system.js',
        'system.config.js',
      ])
        .pipe(concat('vendors.js'))
        .pipe(gulp.dest('vendor'));
});

// Copy dependencies loaded through SystemJS into dir from node_modules
gulp.task('copy:vendor', function () {
    return gulp.src([
        'node_modules/rxjs/bundles/Rx.js',
        'node_modules/@angular/**/*'
    ])
    .pipe(gulp.dest('vendor'));
});

gulp.task('vendor', ['bundle:vendor', 'copy:vendor']);
gulp.task('app', ['compile:ts', 'bundle:app']);

// Bundle dependencies and app into one file (app.bundle.js)
gulp.task('bundle', ['vendor', 'app'], function () {
    return gulp.src([
        'app/app.js',
        'vendor/vendors.js'
        ])
    .pipe(concat('app.bundle.js'))
    .pipe(uglify())
    .pipe(gulp.dest('./app'));
});

gulp.task('default', ['bundle']);

system.config.js

var map = {
  'app':                                'app',
  'rxjs':                               'vendor/rxjs',
  'zonejs':                             'vendor/zone.js',
  'reflect-metadata':                   'vendor/reflect-metadata',
  '@angular':                           'vendor/@angular'
};

var packages = {
  'app':                                { main: 'main', defaultExtension: 'js' },
  'rxjs':                               { defaultExtension: 'js' },
  'zonejs':                             { main: 'zone', defaultExtension: 'js' },
  'reflect-metadata':                   { main: 'Reflect', defaultExtension: 'js' }
};

var packageNames = [
  '@angular/common',
  '@angular/compiler',
  '@angular/core',
  '@angular/http',
  '@angular/platform-browser',
  '@angular/platform-browser-dynamic',
  '@angular/router',
  '@angular/router-deprecated',
  '@angular/testing',
  '@angular/upgrade',
];

packageNames.forEach(function(pkgName) {
  packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});

System.config({
  map: map,
  packages: packages
});

Answer №2

Maybe this will be useful:

System.config({
  "meta": {
    "main.bundle.js": {
      "format": "esm"
    }
  }
});

Answer №3

When attempting to optimize my code for production with gulp and Angular 2.4, I encountered numerous roadblocks. Despite trying several examples and even attempting to clone working projects using git clone, I was still unable to achieve success. Eventually, I found a solution by utilizing angular2-webpack-starter and transferring my files there. This method proved to be much more straightforward in managing dependencies compared to the complexities involved while using SystemJS, where adding to system.config.js and ensuring dependency patterns were followed could be quite challenging.

Answer №4

When it comes to bundling our project, Gulp can be utilized effectively. However, I recommend using ng build or npm build for actual bundling purposes and reserving Gulp solely for task running functionalities.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue encountered when utilizing properties in a Vue.js instance with vue-class-components and TypeScript

I am looking to create a global variable for my server's URL. In my main.ts file, I added the following line: Vue.prototype.$apiUrl = "http://localhost:3000"; Then, when trying to use it in my App.vue file: console.log(this.$apiUrl) The URL is disp ...

What sets TypeScript apart from AtScript?

From what I understand, TypeScript was created by Microsoft and is used to dynamically generate JavaScript. I'm curious about the distinctions between TypeScript and AtScript. Which one would be more beneficial for a JavaScript developer to learn? ...

Tips for implementing dynamic properties in TypeScript modeling

Is there a way to avoid using ts-ignore when using object properties referenced as strings in TypeScript? For example, if I have something like: const myList = ['aaa', 'bbb', 'ccc']; const appContext = {}; for (let i=0; i< ...

The element in the iterator in next.js typescript is lacking a necessary "key" prop

Welcome to my portfolio web application! I have created various components, but I am facing an issue when running 'npm run build'. The error message indicates that a "key" prop is missing for an element in the iterator. I tried adding it, but the ...

ngFor loop is not displaying the correct values from the JSON object

Having some trouble making a REST call and displaying the results obtained. I've managed to successfully work with a simpler JSON data structure, but I'm struggling to get ngFor to properly process this particular data structure. I've tried ...

Is there a way to convert a File into a byte array and then save it in a database using Angular and ASP.Net Core?

Hey everyone, I'm fairly new to working with Angular and I've hit a roadblock when trying to implement file-upload functionality in my Angular application. The technologies I am using include Angular, ASP.Net Core, and Sqlserver. I am tasked wi ...

Implementing type inference for response.locals in Express with TypeScript

I need to define types for my response.locals in order to add data to the request-response cycle. This is what I attempted: // ./types/express/index.d.ts declare global { declare namespace Express { interface Response { locals: { ...

What is the best way to hand off this object to the concatMap mapping function?

I'm currently in the process of developing a custom Angular2 module specifically designed for caching images. Within this module, I am utilizing a provider service that returns Observables of loaded resources - either synchronously if they are already ...

Troubleshooting a dynamically loaded Angular 2 module in Chrome and VS Code

Currently, I am utilizing WebPack in conjunction with Angular 2/4 and incorporating modules that are lazy loaded. Due to this setup, the components and modules are not included in the primary .js file; instead, their code is distributed across files genera ...

I am having trouble with Angular not redirecting to the correct page and I'm not sure how to troubleshoot this issue

After creating a component named detail that is supposed to be associated with a button, I encountered an issue where it doesn't route me to the desired location. Strangely, no error messages are displayed, leaving me puzzled about how to solve this p ...

An unconventional approach to conducting runtime checks on Typescript objects

I've been working on a server application that receives input data in the form of JavaScript objects. My main task is to validate whether these data meet certain requirements, such as: having all required fields specified by an interface ensuring th ...

Trouble with styling the Ngx-org-chart in Angular

I integrated the ngx-org-chart library into my Angular project, but I'm facing issues with the styles not applying correctly. Here are the steps I followed: I first installed the package using: yarn add ngx-org-chart Then, I added the ngx-org ...

There was an issue thrown during the afterAll function: Unable to access properties of undefined

Recently, I upgraded my Angular project from version 15 to 15.1 and encountered an error while running tests. To replicate the issue, I created a new Angular 15.1 project using the CLI and generated a service with similar semantics to the one causing probl ...

TS: A shared function for objects sharing a consistent structure but with varied potential values for a specific property

In our application, we have implemented an app that consists of multiple resources such as Product, Cart, and Whatever. Each resource allows users to create activities through endpoints that have the same structure regardless of the specific resource being ...

Is it possible to stop Angular requests from being made within dynamic innerhtml?

I have a particular element in my code that looks like this: <div [innerHtml]="htmlContent | sanitiseHtml"></div> The sanitiseHtml pipe is used to sanitize the HTML content. Unfortunately, when the htmlContent includes relative images, these ...

TypeScript types for d3 version 4

I am currently working on a d3 project and to simplify the development process and reduce errors, I decided to implement TypeScript. Using d3 v4, I initially faced issues with incorrect type definitions which led to errors like d3 not having a definition ...

Modify FrameColor of Material UI Inputs when Reset button is clicked

When using Angular Material UI in the Registermenu, I am facing an issue where clicking on the reset button deletes the content but leaves the red frames unchanged. Can anyone provide assistance with this problem? Thank you. Screenshot Here is the code f ...

Creating a table with merged (colspan or rowspan) cells in HTML

Looking for assistance in creating an HTML table with a specific structure. Any help is appreciated! Thank you! https://i.stack.imgur.com/GVfhs.png Edit : [[Added the headers to table]].We need to develop this table within an Angular 9 application using T ...

Simple methods for ensuring a minimum time interval between observable emittance

My RxJS observable is set to emit values at random intervals ranging from 0 to 1000ms. Is there a way to confirm that there is always a minimum gap of 200ms between each emission without skipping or dropping any values, while ensuring they are emitted in ...

What are the best methods for visually designing a database using Entity Framework Core?

I find myself contemplating the best approach to designing my database scheme for optimal efficiency and visual appeal. Currently, I am working on an ASP.NET Core application with Angular 2, utilizing Entity Framework Core ("Microsoft.EntityFrameworkCore" ...