25. Januar 2016

Compile on Save for Typescript in Visual Studio with Gulp

The standard way to develop with Typescript in Visual Studio 2015 (ASP.NET 5, MVC6) is to create a so called "virtual project" in a folder. That's a typescript project inside a Web-C# project.

The better way is to let gulp do the compilation. But let's start with the standard way (the few steps you do here are required later anyway).

Setup the virtual Typescript project:

  • Add a folder for Typescript scripts to the Web project, e.g. "./Scripts"

  • Put a tsconfig.json file into the folder (it contains "outFile": "../wwwroot/js/ts/scripts.js") which bundles all generated Javascript in a single file scripts.js in the "wwwroot/js/ts" folder.

  • Add a folder "ts" in "wwwroot/js". This is the Typescript compiler destination folder. Compiling into a sub folder of "wwwroot/js" has the advantage that generated Javascript will be minimized like all other Javascript inside "wwwroot/js" by the the Visual Studio build step. This is nice for Release builds. For our debug session we use the non-minimized "wwwroot/js/ts/scripts.js" in the HTML.

  • Add your *.ts files to the "./Scripts" folder

  • A Visual Studio build will generate "scripts.js" and "scripts.js.map" (.map for debugging Typescript source code in IE or at least watching Typescript in Chrome).

  • Add a reference to "scripts.js" in your HTML like this: <script src="/js/ts/scripts.js"></script>.

The *.ts files are only compiled and bundled when the project is built. No edit/save/reload-browser cycle. The debug session must be stopped to make new Typescript code available for browser reload.

There is a solution.

Let gulp do the Typescript compilation and trigger the compilation with a gulp file watcher.

Here is the code: https://gist.github.com/wolfspelz/d494bd8a1ba56ff81c91

Here are the steps:
  • Add a Scripts folder for Typescript files (as before for the virtual project).

  • Add a file "_tsconfig.json" to the Scripts folder (can be any name, but the name appears in "gulpfile.js"). I just renamed my existing "tsconfig.json" to "_tsconfig.json" to hide it from Visual Studio and re-use it with gulp-typescript.

  • Add gulp modules by editing "package.json". Visual Studio should download lots of node packages.

  • Add gulp tasks by editing "gulpfile.js" in three places:
  • 1. Add gulp requires at the top.

  • 2. Add the Typescript source path further down.

  • 3. Add two tasks.

  • Saving "gulpfile.js" should show two new tasks in the Task Runner Explorer: "compile-ts" and "watch".

  • Check that the "compile-ts" task works. Double click "compile-ts" in the Task Runner Explorer. It should compile and combine all Typescript into "scripts.js" in the same place as before with the virtual project.

  • Once "compile-ts" works, we can automate the Typescript compilation with the new "watch" task. In the Task Runner Explorer, bind the "watch" task to the "Project Open" event. Right-click "watch"  => Bindings => Project Open. Result:

  • You might check if the "watch"/"compile-ts" workflow works by starting "watch" and editing/saving a Typescript file in the Scripts folder.
  • Close/Open the project/solution or just stop/start Visual Studio. The "watch" task should be running after starting Visual Studio settles down.

  • Delete the "scripts.js" file from earlier "compile-ts" runs.

  • Edit/save a Typescript file. The "watch" task should start "compile-ts":

  • Check if the "scripts.js" is generated along with it's "scripts.js.map".

  • Start a debug session. 
  • Change Typescript code. Reload browser.
  • Voilà
  • The default behavior of Visual Studio for Typescript without a virtual project (and a proper "tsconfig.json") seems to be compile-on-save.It generates a Javascript for each Typescript in the "Scripts" folder. We can just ignore them. Maybe nice to check the generated Javascript code.


PS: There could be a clean-ts task

Thanks to

11. Dezember 2015

Wordpress Rant

One quarter of the web runs on Wordpress. Millions of flies can not be wrong
...so I thought.

That was wrong...
  • disappointingly, 
  • irritatingly, 
  • gaspingly, 
  • outrageously 

I was setting up a new web site. OK, let's use Wordpress. Everyone is using Wordpress, There are so many cool Wordpress driven sites. And countless plugins. You can do everything with Wordpress.

Yes, you can, but only if you are a Wordpress expert and if you want to pay real money. Wordpress is not for you if you want to host a cheap (cost free) open source content management system on your own (virtual) server.

What's wrong?
  • It says it is a content management system, but the basic installation is just a blog system. There is no way to arrange/layout your content.
  • I can use plugins to create various numbers of columns in a page, but what they do is add meta tags to the content which formats columns. You always see the meta tags while editing the content. They are part of your article text. That's ugly. There is no way you call that a CMS and a WYSIWYG editor. 
  • Worse, column plugins create columns in the content area. Nothing more. No separator, no second content part. There is just one content area on a page.
  • I could pay about € 50 for a good layout plugin, but I don't want to. I moved to Wordpress, because it is "the dominant open source CMS". But it turns out. It is a blog engine, which can be upgraded to a CMS with real money and real effort.
  • The Wordpress team/community claims, that absolute URLs in the HTML are better than relative. I am not convinced, but it can be argued. But, even if you put absolute URLs into the HTML, then you definitely do not store references to uploaded images and internal links as absolute URLs. That's plainly a wrong design. 
  • It is not possible to change the site's base URL easily, because references to uploaded images and internal links are stored as absolute URLs. All internal links and images must be fixed when the domain name (base URL) changes. There is no good reason to store absolute URLs. You'd store them relative and insert the base URL while generating the HTML.
  • Short loop about the official docker image: It does not support email. Any real web site needs email. You can not omit it and call it the official docker image. Its worthless for non-experts. Nice try. Don't tell my why this is so. I know why. I know how to fix it. I can start another container with a mail server. But the "official" image is not prepared to interface with, say a postfix image. 
  • With help of another plugin I can use the built in SMTP client. But this is not for beginners, not for everyone. It needs an expert.
  • I can add custom fields to template pages. This way I can probably other additional content elements. But, after trying one hour I still don't see them. It's not for beginners. It needs a Wordpress expert. 
  • Very popular templates have major deficiencies. I chose a template with a full with image slider at the top of the start page. But, the thing is fixed to 3 (three) images. Not 1-3, not 3 or 4 or 5, not a variable number. Just: 3, WTF. I would not dare to publish this as a public template. Maybe hack this up for my personal use, but not as a template for everyone without a bit of flexibility. 
  • This can be fixed though. I just have to upgrade to the professional version of the template for additional money
  • Speaking of money: most templates want money for responsiveness. A responsive design should really be in the base version of the template. In which decade are they living? Mobile is mainstream, not optional, enterprise level, only for paying customers.
  • Everything can be fixed with plugins. But there are many plugins. Many plugins for similar features. Some do not work with your chosen template. You will find out after paying for the professional version. A steep learning curve. I try many plugins. I read many blog posts. I have to become an expert. Otherwise this blog software won't be a content management system. There is a plugin for everything. But only experts know which ones you need.  
  • While we are at it: many plugins claim to be so great. But plugins often have hidden deficiencies, which you discover after having invested significant time. That adds to the cost. It's not just trying different plugins. The time sink is in using a plugin until you discover a not so obvious flaw, then choosing a different one and start all over. 
  • Small but symptomatic: Enter the web site contact email address and it will appear as http://-link instead of a mailto:-link. This is the base installation with default template. Does not work. Of all these developers and users, did nobody ever click on the email in the header of the default template?
  • I won't start about how often Wordpress appears on the security lists, because a plugin was unsafe. But you need plugins for everything. At least with visualization and/or containerization you do not compromise your server anymore. Still, a mess.
  • I am not halfway through...
I am an expert in so many things. I do not want to become a Wordpress expert, just to make a web page. I am quicker coding a CMS myself in whatever language you want. Heck.

Please do not tell me that nothing is for free, that people have to live, that hard work must be payed, that it would be unfair to not pay them. That's not the point. They say: "WordPress is web software you can use to create a beautiful website, blog, or app. We like to say that WordPress is both free and priceless at the same time."

It is not. It is either free or beautiful. Wordpress costs very much time or significant money to make something beautiful and useful.

And yes, I know it is my fault. I could just pay someone 800 € per day to set it up and in the meantime earn 800 € per day with what I am already good at.

All I am saying is:
  • The base system is crap.
  • It is expensive too use.
  • The official docker image is a showcase, but otherwise useless.
Sorry, but this can't be serious.

It put up a good show. It got me.


7. Dezember 2015

Avira and VirtualBox Broken

tldr: Avira face punches VirtualBox. Need other virus scanner.

I was using Avira, because it is the best free virus scanner. And I am using VirtualBox for sandboxed Windows, local Linuxes, as docker container host, etc...

...but recently they stopped working together.

Over 2 weeks VirtualBox VMs were increasingly less likely to start. I needed some time and googling to find out that Avira prevents the VM from starting. Disable Avira: still nogo. Uninstall Avira: VirtualBox works. Reinstall Avira: VirtualBox broken again.

See: https://forums.virtualbox.org/viewtopic.php?f=6&t=68869

Time to move on to a different virus scanner.


6. Dezember 2015

Life is Strange

Habe in den letzten Tagen Life is Strange als Letsplay geschaut. Gefällt mir super. Ist wie Fernsehen. So soll es sein. Zurücklehnen vorspielen lassen.

Aber auch selber spielen ist sehr relaxt. Der nächste Level der Casualisierung.

Es spielt sich fast von selbst. Ab und zu mal was suchen, kleine Aufgaben lösen. Nichts wo ich nicht weiterkomme. Genau mein Schwierigkeitsgrad.

Nie wieder Open World. Spielen auf Schienen. Keine schwierigen Aufgaben zu lösen, Keine Leute umzubringen, keine NPCs, die warten bis sie gemetzelt werden. Ich kann die meisten Entscheidungen revidieren. Manche aber nicht. Das Spiel führt mich in der Story weiter. Interaktives Kino mit starken Emotion und Chillfaktor.

Gibt's für PS3. PS3 habe ich seit Assassin's Creed III. Das war das einzige Spiel was ich auf der PS3 gespielt habe (und das nur halb). Also kann ich mit Life is Strange  meine Investition von 400 € pro Game auf 200 € pro Game verringern. Reichgespart.


PS: Das Game auf die PS3 zu bringen war auch schon eine Quest-Reihe. Ich sach nur Controller aktivieren, System Update, zu alter Account, problematische Payment-Optionen, mehr Updates, Downloads, mehr Downloads, Updates, Shop verlassen, wieder rein, Reboot, Update, immer wieder Auflösung Umschalten und dann viele Screens (Engine, Publisher, Developer, alle toll) bis das Game endlich startet. Unchillig das.

23. Oktober 2015

Galactic Developments ist umgezogen auf einen neuen Server als KVM

Bisher war die Galactic Developments Website ein Apache Virtual Server auf meinem alten Hetzner Rootserver. Den hatte ich vor 6 Jahren bei einer keine-Setupgebühr-Aktion gebucht (und dann 3 Monate lang nicht installiert, was die keine-Setupgebühr-Aktion für mich ad-absurdum geführt hat, für Hetzner nicht). Inzwischen ist das Betriebssystem (Debian Sarge) aber schon aus den Security-Fixes raus gelaufen.

(Ich finde Sicherheitsaktualisierungen für nur 3 Jahre etwas kurz. Naja, ist ja Open Source. Wenn es einem nicht gefällt, dann einfach nicht benutzen oder selbst fixen, wie man so schön sagt, jedenfalls nicht meckern.)

Die Rechner der Rabatt-Aktion waren damals etwas schwach auf der Brust. Das stört nicht, wenn man nicht viel Traffic hat, aber heutzutage will man virtualisieren und mehrere Server gleichzeitig laufen lassen. Dafür ist ein ganzes GB RAM nicht genug. Der neue Server ist wieder bei Hetzner, hat aber 2 TB Platte, 32 GB RAM, 8 CPUs incl. Hyperthreading. Das sollte reichen für ein paar virtuelle.

Ich kann Debian, also weiter Debian-stable, d.h. Jessie 8.2.

Zum Virtualisieren kvm und libvirt drauf. Ein 2 GB Image für das Guest-Template erstellen mit einer Debian-minimal Installation ohne alles außer sshd. Die VMs sind nur über das interne "default" Netzwerk zu erreichen. Alle VMs bekommen statische IP Adressen vom internen DHCP.

Ein VM als Reverse-Proxy, der HTTP-Requests an verschiedene virtuelle Maschinen weiterleitet. Dafür eine iptables-Konfiguration per qemu-Hook, die immer dann die 2 iptables-Regeln setzt/löscht, wenn die VM startet/stoppt. Auf dem Proxy ein nginx, der alle Anfragen für www.galactic-developments.de an die Galactic Developments VM weiterleitet.

Der Galactic Developments Server bekommt eine eigene VM. Hier mit Apache, weil ich Apache schon kann und nicht zu viele Konfiguration ändern muss, dachte ich. Tatsächlich haben sich die Apache Entwickler ein neues Sicherheitskonzept einfallen lassen und erst mal geht gar nichts, bis ich herausfinde, dass man einen neuen Befehl (Require) braucht. Zusätzlich zum Galactic Developments Apache virtual Server gibt es noch einen CatchAll virtual Server, der Adressen wie galactic-developments.de (ohne www.) und *.galactic-developments.com auf den Hauptserver umleitet (401/permanent).

Dateien und Daten der Galactic Developments Website sind in Subversion. Das bleibt erstmal so bis sich die Community mehr beteiligt. Dann will ich git nicht im Wege stehen. Also: Repository auschecken und Apache-config darauf zeigen lassen. Bisher waren SVN Server und Website auf dem gleichen Rechner. Ein Subversion post-commit Hook hat automatisch die Website svn update'd. Poor man's Continuous Delivery. Das geht jetzt nicht mehr, weil es verschiedene Rechner sind und später - wenn der SVN Server auch umgezogen ist - gleicher Rechner, aber getrente VMs. Deshalb muss der post-commit Hook jetzt das Deployment anders triggern. Ich mag Trigger per HTTP-Request. In diesem Fall: ein Einzeiler-PHP in der Galactic Developments Website (Name lang und geheim, quasi das Passwort im Namen, Security by Obscurity), das ein lokales Shellscript startet, das wiederum "svn update" macht. Drei Einzeiler hintereinander. Man muss noch die Benutzer-Grenze überwinden vom wwwdata-User des Apache zum Eigentümer des Repositories. Deshalb wird das Shellscript mit sudo ausgeführt. Dafür eine Zeile in /etc/sudoers. Bei jedem svn commit ruft der post-commit Hook das update PHP-Script in der Zielwebsite per wget ("-O -" nicht vergessen) auf.

Dann noch DNS für www.galactic-developments.de umbiegen von rama.wolfspelz.de auf fred.wolfspelz.de und Galactic Developments ist umgezogen.

Das hört sich alles locker flockig an, hat mich aber mehrere Tage gekostet. Es gibt fast keine Anleitungen für libvirt/kvm OHNE lokales Display und ohne VNC. Auch virt-manager usw. alles nett gemeint, aber ich will kein Desktop auf meinem Server nur zum Installieren. (Wer bis hier gelesen bekommt von mir ein nagelneues Notebook). Genauso das Netzwerk: entweder es wird nicht erwähnt, was blöd ist, wenn man die VM vom Netzwerk installieren will oder es wird bridge-Networking vorgeschlagen, was bei mir einfach nicht wollte. Dabei geht das "default" Netzwerk super. Man muss es nur anschalten. Das könnte mal irgendwo stehen. Ein qemu-Hook statt bridge-Netz sehe ich nicht als Hack an, im Gegenteil.

PS: rama.wolfspelz.de war keine Frühstücksmargerine, sondern ein 50 km langes Alien-Raumschiff.


21. September 2015

Feature Flags

(Image: bytearrays.com)
In one of my projects I just stumbled across the topic "Feature Flags".

Feature flags (aka Feature Toggle, aka Feature Switch) let you enable program/web site features selectively. This is especially important in continuous delivery environments where code is always committed and deployed even if a feature is not ready for prime time. It can be useful if you have a large user base and want to introduce the feature incrementally by enabling the feature for sub-sets of users. Feature flags are useful in anything beyond toy apps.

Feature flags are not new. They are widely known since Martin Fowler blogged about the pattern. He did not invent them. Many good developers have been using feature flags or alike for a long time. But Martin Fowler recognized feature flags as a remarkable pattern. Writing about feature flags was a good idea, because other developers who are not aware of the pattern can learn from it. That was 2010.

Guess what, in 2006 a lonely Weblin programmer added feature flags to the Weblin portal. Weblin has been using feature flags from the start.


15. September 2015

ZEIT online Relaunch - Undo

ZEIT online hat gerelauncht. Jetzt irgendwie dunkel und schmaler als vorher. Gefällt nicht. Kann man aber fixen. 

Links: ZEIT nach Relaunch, 
Rechts: gefixt: wieder weiß, ohne Rand 


Mit Tampermonkey, eine Chrome Erweiterung. Tampermonkey führt auf jeder Webseite Javascript aus.

Bei ZEIT online muss man nur ein paar CSS Anweisungen verändern: den Hintergrund vom <body>-Tag wieder in weiß und der Rahmen vom Content-<div> weg:

body { background-color: #ffffff !important; } 
.page__content { box-shadow: none; }

Man braucht noch etwas Javascript, um das CSS einzufügen. Hier das ganze Tampermonkey-Script für ZEIT online:

// ==UserScript==
// @name        ZEIT
// @namespace   http://wolfspelz.de/
// @version     0.1
// @description Restore white background
// @match       http://www.zeit.de/*
// @copyright   2015+, wolfspelz
// ==/UserScript==

function addGlobalStyle(css) {
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;

addGlobalStyle('body { background-color: #ffffff !important; } .page__content { box-shadow: none; }');


Für Firefox: Greasemonkey