Hi Joseph!
Sorry for such delay, I experienced some issues with login in Community.

Such error in the console usually says that it can't parse some content in the specified file. As I see in the filename, your target build is ES2015 and problem in the build process of the code of 3rd-party libraries.  What I would try to do in this case is set property "target" in tsconfig.ts file to "es5", rebuild the app and see that problem will go or not. 

Another option you can try is to find out where exactly the problem is. You can click on the error in the console and it should show you the place in the code where code parsing/execution failed. Probably, then we will able to understand what went wrong.

Hi Joseph!

At first, may I ask you why do you like to migrate your project into a CSP app? I guess you want to use builtin CSP-authentication?

Now I go to Step (2). I defined my CSP application path "/my-app". Then in my "ng build" command, specify the --output-path to that CSP application physical directory. Then I modify every occurrence of the src import in index.html with the "/my-app/" prepended.

This is exactly what my answer was about. You should not modify src imports by hand but use --base-href option instead.

But the page is not loaded. It is not a 404. It is just a blank page.

Could you share the Console/Network tabs output from your browser's Developer Tools? It will help me to better understand what happens.

Why did you rename the files to .csp?

I only use it in the case when my app's files go through CSP-Gateway. There are some differences between how .csp and .html files served through CSP-Gateway.
Here's more info: https://irisdocs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page...

.html files will be served as static files with BOM that potentially can break your files if there is no BOM in them. Or you will need to additionally configure a web server to avoid it.

Why are you using ahead of time compilation?

It compiles (Angular-like components to actual HTML/JS code) Angular application before it actually served to the client. So the client doesn't need to spend time and resources to compile it each time (https://angular.io/guide/aot-compiler).

Hello!

I can share my experience with Angular project building process with Caché/IRIS.
I will split it in two cases:

  1. The project has custom auth and can be used like non-CSP application. The only Caché part is REST API.
    In this case, you would like to use ng serve command instead of ng build during development. It will run your app on Express Server and recompile it automatically after each change (it will rebuild only necessary files). It usually runs on localhost:4200 address, so the only thing you will need to do is to specify your Caché server address with a proxy so the app will able to reach it.
    To achieve that you will need to run ng serve --proxy-config proxy.conf.json. Your proxy.conf.json should look like this:
{
    "/your_app_name": {
        "target": "http://localhost:57772",
        "secure": false
    }
}

Here is the docs from Angular CLI: https://github.com/angular/angular-cli/blob/d22e9ae73763923980fc1e59cfb2...

After your development is complete, you can use ng build and then deploy your app as usual.

  1. The project uses Caché Authentication, Session and can exist only like CSP-app.
    In this case, you will need to build your project every time you change something, which can be slower than ng serve.
    I would use ng build --output-path dist --watch command where dist is your output directory. Then you be able to build directly into the CSP-app folder from your development directory and project will be rebuilt every time you change something because of --watch

An inconvenience during this process is that the src imports in index.html need to be prepended with the web app's name.

It should not be prepended if base-href is properly specified.
This is how you could achive it:
1. Rename all the .html files in the project to .csp files (e.g. index.csp and login.csp)
2. Use --base-href option in build command:

ng build --aot --base-href=/csp/my_app/index.csp for development build
ng build --aot --base-href=/csp/my_app/index.csp --prod for production build

Where /csp/my_app/index.csp is path to your csp-app's index.csp on the Caché server (full URL in the browser will be something like localhost:57772/csp/my_app/index.csp)

/csp/my_app/ is the CSP-app where you deploy your app with index.cspin root of the folder specified as CSP Files Physical Path

During development, you would also like to set Serve Files option of CSP-app to Always value to avoid CSP Gateway Cache (it sometimes serves old cached files even if files in CSP-folder already have been updated).

Please, let me know if you will have some difficulties with the information above. Maybe it deserves a better explanation and a separate post with demo application with source code.

I would to mention that there are at least two big problems with serving images in JSON:

1. No client caching

2. No lazy-loading

These two things can be critical in SPA's with big amount of images (I suppose it's true for other static content too). No client caching also means more requests in a long term and higher load on the servers.

There are also other downsides possible.

Also, with http/2 it will become unnecessary to bundle all the resourses in one request for improving loading speed.

Hi!
You can use custom Caché Login Page as the simplest solution.
Suppose, you have React (it doesn't matter anyway) csp-application as a client and you need to authenticate single user at time.
You can create login.csp page somewhere in your project and set it as custom login page. Content could be like this (basic implementation, styles not included):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Caché Login</title>
</head>
<body>
<div id="login">
  <div>
    <div>

      <form name="Login" method="post">
        <div>

          <div>
            <div>
              <input type="text" placeholder="Login" name="CacheUserName">
            </div>
          </div>

          <div>
            <div>
              <input type="password" placeholder="Password" name="CachePassword">
            </div>
          </div>

          <button type="submit">Log in
          </button>

          #($select( ($Get(%request.Data("Error:ErrorCode",1))'="")&&($$$GETERRORCODE($Get(%request.Data("Error:ErrorCode",1)))'=$$$ERRORCODE($$$RequireAuthentication)): "<div>The user name or password is incorrect</div>", 1:"") )#
        </div>
      </form>

    </div>
  </div>
</div>
</body>
</html>

You can change the content of this page to match your application look and logic. You can include any 3rd-party scripts and styles.

Then, in your client app settings (Management Portal) set recently created login.csp page as custom login page. Also, set Allowed Authentication Methods to "Password" and Session Cookie Path to the same value for both client and rest applications.

After user will be authenticated, browser will use Cookies. You can log out from application just by redirecting user to current URL with ?CacheLogout=1 appended. You can also reload the page each %session.AppTimeout)#' + 15) * 1000 ms to automatically redirect user to login page if session is closed (don't forget to reset this counter after rest requests or/and send some sort of throttled ping after user interactions).

So, in typical AngularJS approach, you usually create views (aka states) of your app. One state — one controller. You need to define one big markup for this state which will contain all the elements of the state. And whole content of this state is controlled by its controller (hah). Which can be very complicated in big states with a lot of elements and logic. It's hard to maintain, it's hard to test and it's hard to change and refactor.

In component approach introduced in Angular 1.5, you usually create components instead of states. One component — one controller. In this approach each state is component, which contains other components.

<body>

    <app>

    </app>

</body>

Where <app> is component. And <app> itself is like

<header>

</header>

<form>

</form>

<footer>

</footer>

Where <header>, <form> and <footer> are also components.

And <form> could be like

<search>

<form-input>

<form-input>

<form-button>

Where <search>, <form-input>'s and <form-button> are also components.

So you will end up with a tree of components, where each component will have own logic and markup and it's rather small and isolated. Small components with isolated logic is basis of component approach. It's much easier to test, to exchange components when you need, to reuse them and to remove them.

Usually, each component stores in its own directory, with separated logic, markup and styles.

For instance:

app (main directory of app)

––components (directory to store all the components)

–––app (directory for root app component)

––––app.component.js (app component controller)

––––app.component.html (markup)

––––app.component.css (styles)

–––header (directory for header component)

––––header.component.js (controller)

––––header.component.html (markup)

––––header.component.css (styles)

This approach is becoming standard now in frontend development. WebComponents itself, Angular, React, Vue are following this approach.

I didn't use it with AngularJS (1), at some point I just desided to move to Angular (2). 

But if you try to search something like "Angular 1.5 component", you will find a lot of information about such approach in AnglularJS.

For example, here is a pretty fine introduction in components in AngularJS 1.5:
https://www.sitepoint.com/building-angular-1-5-components/

I can add something from myself.

Let's begin with AngularJS (aka Angular 1).

If you're using AngularJS, you don't really need jQuery at all. And it's absolutely different from way jQuery is usually used. You should manipulate the DOM in "Angular way", inside $digest cycle, for Angular to be aware about your DOM changes. You can call digest by yourself, but in big applications such usage will quickly lead to very poor application performance. But if you need to do something specific (for example, adapt some external component for using with angular app), there is jQuery Lite inside AngularJS, which you can use inside "link" or "compile" functions of directive (http://www.ng-newsletter.com/posts/directives.html).

There are also two approaches of building apps in AngularJS:
1) Initial "view-controller" approach

2) New "component" approach which was created for easier migration to Angular 2.

The second approach a way modular and better in terms of encapsulation and maintainability.

The first approach is hard to maintain in big applications, because you will have very big scope graph which can lead to memory leaks. You will need good JS skills to prevent wrong usage of anonymous functions (especially as callbacks), circle linking, closures. You also will need a good knowledge of Angular internal design and lifecycle, to optimize such things as event bindings and watchers.

The learning curve of Angular is steep. A lot of things that can be accidentally messed up, a lot of problems will come from two-way binding and digest loops.

This is a very good example of how big (and good) angular application looks like:

https://github.com/ProtonMail/WebClient

Angular 2 (now it calls just Angular and will have major updates every half a year)

You don't need to know nodejs to use Angular 2. You will need some tools to use it (for example: transpiler, testing tool, moduler bundler, moduler resolver), which actually works in nodejs environment, but they are usually pretty simple, handy and well-documented.

TypeScript is not a different language, it's just a super-set of JavaScript, which has a syntax, similar to new EcmaScript 6/7/8 specifications. It also has some typing enhancements such as types support, interfaces, generics etc. (which Microsoft brought from their C# experience). It can be learned in couple of days (of course, if you know JavaScript and new ES6 features) and it will eventually transpiled to the EcmaScript 5 for cross-browser support.

The first challenging thing which can probably confuse somebody is how Dependency Injection works in Angular. But after you get and research it, you will able to switch dependencies for different environments (such as Development, Testing or Production) changing only 1 line of code. For example, you can switch all the data services from HTTP-services to your own mock services to test your app with syntethic data.

Angular is pretty well designed, much better than AngularJS. It's absolutely modular out-of-the-box, has no 2-way binding by default anymore and it's not so much MVC(MVVW), but as much as component framework now, similar to React stack, but all-in-one. 

It's much faster than AngularJS. It's also much maintainable and way easier to test.

It also does not bound you to just HTML/CSS, you can write multiple views for different platforms and assemble them from one business-logic code. It supports Native components for compiling in Native apps for iOS and Android.

Angular supports Shadow DOM by default (and it can emulate Shadow DOM in browsers which don't support it), which lead to incredible level of components encapsulation and re-usage.

The API of Angular is locked, so it's pretty safe to use now in real projects. 

In the end.
I am developing small and average Angular apps with Caché backend for almost two years and AngularJS still seems complicated for me. It requires a lot of design and planning for just avoid huge problems in the future.

With new Angular things seem much orderly and maintainable. So, for new project I would recommend to use Angular 2 or, if you need or want to stay with AngularJS, use it with component approach implemented in latest versions.

I also can recommend you to at least look on React stack (and maybe Vue.js) as it has a lot of positive feedbacks. It uses more functional way than Angular (which obviously much more OOP), it's more lightweight. But I'd like to note, that React is not all-in-one framework, it just a View library, so you will also need to pick some "Model" and "Controller" framefork(s) to build an app.

Perhaps my answer may seem too confusing and unstructured. Sorry for this. If you have any questions about it, I will try to give accurate answer.