Angular.io App – Deploying is not so simple

Published / by msaladin / Leave a Comment

I tried to learn a little bit Angular.io, which has a very strange version-history which makes it cumbersome to find solutions to issues and problems in a simple manner. So in this post, I talk about the new AngularJS, currently in version 5.

I played with the tutorial (https://angular.io/guide/quickstart), and after having played around with it, I wanted to make sure that it does not only work locally with my own ng serve webserver, but with a real production webserver on which I host this website.

Unfortunately, I experienced two problems with deploying it.

1. Base HREF

First, I don’t want to have my AngularJS app as my homepage… I just wanted to have it inside a neat folder called “ng01”. When I created the deployment with:

ng build --prod

and copied the whole dist folder to the ng01 folder of my website (hosted with Apache httpd), nothing happend, and when I checked the Javascript console, I saw that the Javascript files which were created by angular-cli will not load. The problem is that the default base href is:

<base href="/">

So this means that when including JS files like this:

<script type="text/javascript" src="inline.b9fd455402f26b103f03.bundle.js"></script>

won’t work, because the JS files are inside a folder ng01, and not in the root folder.

Solution:

Use the –base-href command line parameter for the generation of the dist folder:

ng build --prod --base-href=/ng01/

2. Rewrite rules for Angular Routing

But then, this was not enough. It still did not work.

The initial routing in the tutorial worked fine when deployed on my website, but as soon as I hit the reload button, it did not work anymore. It gave me a 404 error, which is clear enough. In the Angular tutorial, they write that the URL of a detail-page can be created like this:

{ path: 'detail/:id', component: HeroDetailComponent },

This is a really cool feature… but when you think about it, it just cannot work. it cannot work because an ordinary webserver like httpd does not know anything about the URIs like /ng01/detail/33 or /ng02/detail/77…

I did not find out the real correct way how to do this (In java, you would define a context path with wildcards in your web.xml and define a Servlet for it), but at least I found a workaround. I just redirect all the 404 error messages to the index.html page, and then Router component of AngularJS seems to do the rest.

Solution:

A very nice feature of httpd is that you can have different configuration per directory, using a .htaccess file. So I created a .htaccess file for my ng01 folder where all my files are located:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# not rewrite css, js and images
RewriteCond %{REQUEST_URI} !\.(?:css|js|map|jpe?g|gif|png)$ [NC]
RewriteRule ^(.*)$ /ng01/index.html?path=$1 [NC,L,QSA]

This worked, now the NG tutorial can be deployed on my website…

Gradle UP-TO-DATE Check and exception handling

Published / by msaladin / Leave a Comment

I really feel the time I am quite old sometimes. I am now programming for about 22 years, and exception handling was always an important part of development. This seems to be no longer true.

Gradle is a great build system, it is really nice and you can script your build logic using Groovy, which is better than using XML (ANT) or using only convention (Maven). I am working with Gradle now for about 6 month, and I really like some of the concepts… but exception handling is really hard.

For example, Gradle has the concept that there is some logic which just knows whether a build task needs to be executed or not. For example, if you have a task which compiles Java, and you know all the input files, and the output files, you can compare the input/output from the last build, and the current build, and when the input/outputs did not change, then you don’t have to do the compilation again. This is quite a good idea, so normally, when you build a Gradle project you experience a lot of tasks which just say:

taskname - UP-TO-DATE

This means that the task is not really executed. Gradle has some logic to know all the inputs and outputs of the tasks, so it can compare them, and if they are the same, just ignore the task for this run and don’t execute it. This is really fine as long as it works.

I had a task which copied some JS files into a directory, it too the JS files from a node_modules folder where it downloaded the files first, and then copied them to a generated folder. This would mean that when I delete the destination folder, then the task must really be executed again, because otherwise the file is not copied. When the file is not copied, it is not part of the delivery, and we remark this only when we have successfully deployed the artifact to a system that something is wrong (runtime exception).

The problem was that Gradle always thought that the task was up-to-date… OK, clearly, there was some error in this. With gradle, you can use command-line-parameters to get more information, like -i for info and -d for debug. I tried this to find out why Gradle thinks that my Copy-task is up-to-date, but the debugging output gave me no real value. There was no hint why the task was up-to-date in the debugging output.

To make this one short: The Gradle guys had a really good idea that tasks should not be executed when the input/output match. This works great. But we as developers make errors, and when we make errors, we want that a tool provides us with a meaningful message, at least in the debugging output.

What really was the problem in my case was that I defined the tasks outputs wrongly, so the directory for the output did not exist in the previous run, and as it does not exist now, the current run does not see any difference and just says UP-TO-DATE.

My whole debugging session, the time I lost with it, could really have been decreased by providing a meaningful debugging-output… I will try to contribute my logging to the gradle GitHub project, hopefully they will include it and this will safe some time for other devs.