When using Angular with systemjs and typescript, the outFile option still includes all files separately as well

Utilizing the Typescript compiler and the outFile function, I am attempting to merge my sources into a single file and then load it as usual with systemjs.

After running the tsc command, I receive a well-structured bundle.js file containing my main code. However, upon loading it in the browser (either apache or lite server), the bundle.js is loaded first as expected. Then, systemjs takes over and begins loading all the .js files individually -- main.js, app.component.js, etc. Although there are no errors, this process works fine but ideally should not require loading the separate .js files.

I have extensively reviewed a similar post (Load combined modular typescript file with SystemJS) but cannot identify what mistake I might be making.

index.html

<!doctype html>
<html lang="en">
<head>
  <base href="/">
  <meta charset="UTF-8">
  <title>Solid Timesheet: Time-tracking made easy!</title>

  <link rel="stylesheet" href="css/main.css">

  <script type="text/javascript">
    // temporary hack for enable bootstrap 4
    window.__theme = 'bs4';
  </script>
  <script>

    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
              (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
            m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

    var localhost = document.location.href.match(/^http:\/\/localhost/);
    ga('create', 'UA-18982324-19', localhost ? 'none' : 'auto');
  </script>

  <script src="node_modules/es6-shim/es6-shim.min.js"></script>
  <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
  <script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>

  <script src="node_modules/angular2/bundles/angular2-polyfills.min.js"></script>
  <script src="node_modules/systemjs/dist/system.js"></script>
  <script src="node_modules/rxjs/bundles/Rx.min.js"></script>

  <script src="node_modules/angular2/bundles/router.min.js"></script>
  <script src="node_modules/angular2/bundles/http.min.js"></script>
  <script src="node_modules/angular2/bundles/angular2.min.js"></script>

  <script src="node_modules/ng2-bootstrap/bundles/ng2-bootstrap.min.js"></script>
  <script src="bundle.js"></script>

  <script>
    System.config({
      packages: {
        app: {
          format: 'register',
          defaultExtension: 'js'
        },
        "ng2-bootstrap": {
          "defaultExtension": "js"
        },
      },
      map: {
        'ng2-bootstrap': 'node_modules/ng2-bootstrap/bundles/',
        moment: 'node_modules/moment/moment.js',
      }
    });
    System.import('app/main')
            .then(null, console.error.bind(console));
  </script>
</head>

<!-- 3. Display the application -->
<body>
<div class="container">
  <my-app>Loading...</my-app>
</div>
</body>

</html>

tsconfig.json

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "module": "system",
    "removeComments": true,
    "sourceMap": false,
    "noImplicitAny": false,
    "outFile": "bundle.js"
  },
  "exclude": [
    "node_modules",
    "typings"
  ]
}

I'm currently utilizing typescript version 1.8.9

Answer №1

I encountered the same issue and found a solution by packaging my app into a single file with the use of outDir (instead of outFile) in my tsconfig file and utilizing SystemJS-Builder. You can check out the full source code here as well as a live example.

system.config.js

var map = {
  'app':                                'dist/js',
  'rxjs':                               'lib/js/rxjs',
  'angular2-in-memory-web-api':         'lib/js/angular2-in-memory-web-api',
  '@angular':                           'lib/js/@angular'
};

var packages = {
  'app':                                { main: 'main', defaultExtension: 'js' },
  'rxjs':                               { defaultExtension: 'js' },
  'angular2-in-memory-web-api':         { 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
});

tsconfig.json

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "system",
    "moduleResolution": "node",
    "outDir": "public/dist/js",
    "sourceMap": true,
    "target": "ES5"
  },
  "exclude": [
    "node_modules"
  ],
  "filesGlob": [
    "src/**/*.ts",
    "typings/*.d.ts"
  ]
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <base href="/">
    <title>Hello World</title>
    <meta charset="UTF-8">

    <link rel="stylesheet" href="dist/css/styles.min.css"> <!--compiled global scss styles-->

    <script src="lib/js/vendors.min.js"></script> <!--bundled dependencies-->
    <script src="dist/js/app.min.js"></script> <!--bundled source-->
</head>
<body class="container">
    <my-app>Loading...</my-app>
</body>
</html>

gulpfile.js

A collection of tasks that make use of tsc for compilation and systemjs-builder to bundle your application.

// Compile TypeScript to JS
gulp.task('compile:ts', function () {
  return gulp
    .src(tscConfig.filesGlob)
    .pipe(sourcemaps.init())
    .pipe(tsc(tscConfig.compilerOptions))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('public/dist'));
});

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

// Minify JS bundle
gulp.task('minify:js', function () {
  return gulp
    .src('public/dist/js/app.min.js')
    .pipe(uglify())
    .pipe(gulp.dest('public/dist/js'));
});

Answer №2

In order to resolve the issue at hand, it is imperative that you eliminate this specific block from your SystemJS configuration:

System.config({
  packages: {
    app: { // <-----------
      format: 'register',
      defaultExtension: 'js'
    },
    (...)
  }
});

Once you indicate an outFile property, the TypeScript compiler will produce a file wherein modules are explicitly registered by name as shown below:

System.register('app.component', [ ...

This approach differs from using anonymous modules in the past. Consequently, there is no necessity to configure SystemJS to link JS files with module names (which was previously done through the packages section).

To delve deeper into this topic, feel free to refer to the following question:

  • How do I actually deploy an Angular 2 + Typescript + systemjs app?

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

Having trouble with the SELECT functionality in Angular2/4 and SAFARI?

Having a major issue with the basic html SELECT component on SAFARI. Here is the code snippet: Initial Declaration idFamily:any = null; listProductFamily: ProductFamily[]; Loading listProductFamily this.productFamilyService.GetAll().subscribe( ...

Using TypeScript syntax to define types; utilizing the export default keyword to incorporate an external JavaScript library within an Angular2

I've been attempting to incorporate a JavaScript library known as bricks.js into my project, but unfortunately, there isn't a publicly available type definition for it. The library seems to be exporting something along these lines: export defau ...

Functions outside of the render method cannot access the props or state using this.props or this.state

Just starting out with react. I've encountered an issue where a prop used in a function outside the render is coming up as undefined, and trying to use it to set a state value isn't working either. I've researched this problem and found va ...

When utilizing the catch function callback in Angular 2 with RxJs, the binding to 'this' can trigger the HTTP request to loop repeatedly

I have developed a method to handle errors resulting from http requests. Here is an example of how it functions: public handleError(err: any, caught: Observable<any>): Observable<any> { //irrelevant code omitted this.logger.debug(err);//e ...

Guide on invoking child components' functions from the parent component in Angular 6

Main Component import { Component } from '@angular/core'; import { DisplayComponent } from './display.component'; @Component({ selector: 'my-app', template: ` <button (click)="submit()">Call Child Com ...

Using TypeScript with Watermelondb

I'm currently developing a React App and I want to implement Watermelondb for Offline Storage, but I'm unsure about using it with TypeScript. I have already set up the database and created Course and Lesson model files from the Watermelondb libra ...

Using TypeScript with React may result in an error message stating that a string cannot be assigned to a parameter of type 'keyof T'

I've encountered an issue with my sorting function that I built using TypeScript and React Hooks. The error message I'm getting is: Argument of type 'string' is not assignable to parameter of type 'keyof T'. Type 'stri ...

Collaborate on a component used in multiple modules

In my application, there are two modules: employer and landing. I have created a component in the landing module that I want to share with the employer module. To achieve this, I declared the component in the app.module.ts file of the parent module and use ...

Debugging with Typescript in Visual Studio Code

I attempted to use the solution found here: how to debug typescript files in visual studio code However, when I set a breakpoint in my .ts files, the debugger indicates that the file is not found. Oddly enough, breakpoints in the .js files are working fin ...

Guide on uploading images to a NodeJS server from an Angular 2+ application

I have a NodeJS rest-API that can handle both images and text content in the same function. Currently, I am using multer in my NodeJS server to manage image uploads along with text content. Below is an example code snippet showcasing how I am handling this ...

Problem with Angular 5: Data Binding Issue未知EncodingException

Struggling to understand... I want to make a GET request to my service to retrieve the specific hardware associated with the barcode I scanned - this part is working correctly. The hardware information is returned as an object that looks like this -> ...

Arranging Alphanumeric Characters in Angular in Ascending Order

I am trying to sort a list of characters first, followed by alphanumeric values. Here is what I have: [Austria , Germany , 123aed , 234eds] This is my current sorting attempt: obj.sort((a,b) => { if ( (isNaN(a.text) && isNaN(b.text)) || ...

Issue with Angular's reactive form: Dynamic validator fails to update control validity

When designing my form, I encountered a specific requirement where one control should only be required if another control has a value. To achieve this functionality, I implemented the following structure: profileGroup = this.fb.group({ username: ['&a ...

Utilize Typescript for managing sessions in MySQL database

I'm attempting to set up a mysql session storage in NestJS using Typescript. I've gone ahead and installed the necessary packages such as express-session, express-mysql-session, and @types/express-mysql-session. The code snippet below is compilin ...

Angular 2 failing to display background images

I have been working on an Angular 2 app with just one component. I recently tried to set a background image for the entire page using the following code: app.component.html <dashboard class="dash"></dashboard> app.component.css .dash { b ...

Utilizing a resolver for managing an entity

Currently, I am facing a challenge with my Angular application. I have a planet-data component and a planet-detail component where I receive a photo object in the planet-data component. However, when navigating to the planet-detail component, I want to use ...

Differences between Angular's form builder and form control and form groupIn the

What are the benefits of using form control and form group instead of form builder? Upon visiting this link, I discovered: The FormBuilder simplifies creating instances of a FormControl, FormGroup, or FormArray by providing shorthand notation. It helps ...

What is the process for setting up a server-side Meteor Collection without the necessity of direct interaction?

I'm just starting out with Meteor and working on a basic recipe list. In my file (/imports/api/recipes.ts), I have defined my Recipe collection: // imports/api/recipes.ts export interface Recipe { _id?: string; title: string; createdAt: Date; } ...

Encountering issues with SystemJS loading my module

Here is the configuration in systemjs.config.js: /** * System setup for Angular samples * Customize as needed for your specific application requirements. */ (function (global) { System.config({ paths: { // alias paths 'npm:' ...

What could be causing my code to not run after subscribing to the observables?

In my code, I have two methods that return two lists: one for accepted users and the other for favorite users. The first part of my code works well and returns both lists, but in the second part, I need to filter out the accepted users who are also on the ...