When I was looking for a cool starter kit / seed / boilerplate or whatever you want to call it for the MEAN stack fully written in typescript, I found nothing really useful. So I started to create this seed myself. Here are my first impressions on this stack. The current result is hosted on github, free to use and reuse!
M — Mongo
I started out with the backend, since this had much more unknown factors for me. Using Angular 2 you’re backed by a lot of tutorials and Google supporting the framework, but with a TS Mongo-Express-Node backend, you’re a bit on your own. The questions I had were along the lines of “what is the tooling like?”, “can I run my unit tests with IntelliJ like I’m used to from JUnit?”, “for how many npm packages are there typings?” and “how reliable are those packages?”.
I started with the database layer, for which I found a Mongo Connector with typings. For unit tests I decided to go with Mocha and Chai. I placed the test files in the same directory as the source files and was able to run them from the command line like:
mocha --reporter spec --compilers ts:ts-node/register '**/*.test.ts
Of course, when project gets bigger you want to be able to run individual unit tests. This is possible with grep , which is somewhat cumbersome. However, after some hours I managed to get IntelliJ to run individual unit tests directly from the editor. Since then the development experience has improved drastically.
During the development of the database layer, I didn’t run into any major problems. I’m not the biggest advocate of MongoDB by the way, but the MEAN stack was an existing “brand” I could build upon. In any case, I would prefer an SQL database for any real web projects based my past experiences with Mongo. Here are my reasons why. In case you share this view, I also abused the “M” in MEAN to create a MySQL branch of the stack. I designed the database access interface in a way, such that the rest of the application doesn’t need to know whether it’s Mongo or MySQL backed. Modular design ftw. In any case, I’m going to maintain both branches in the future.
E — Express
The next part in the application was the “E”, the ExpressJS / ExpressTS. I set up some simple routings and a generic “CRUD router” that would allow you to create/read/update/delete any data using the url /api/v1/:resource/:id . Next I added a user model and authentication layer. A side note on the models: I first shared the models between frontend and backend, but this was too annoying since I always had to npm publish on every change and there wasn’t that much benefit since the models differed anyways. For example, the backend user also has a password stored and so on. For authentication I used PassportJS. I found it a bit confusing at first, how it’s directly used in the routing layer. I also used something called connector-flash related to passportJS until I noticed how hopefully outdated it was… I had a similar experience with the password hashing library. I first installed bcrypt and later had to switch to bcrypt-nodejs since bcrypt threw crazy errors on install. Luckily, I hadn’t used the bcrypt library directly in my code, but wrapped it with a small layer. Like this I could switch out the implementation (the library) easily and be proud of myself how masterfully I had programmed against an interface. But seriously, with all the package churn I would heavily recommend you this for your NodeJS project: Unless it’s a professionally maintained library, better wrap it so you can switch it out easily! Of course there are cases when it doesn’t make any sense, e.g. example you can’t just wrap the Angular interface, but Angular 1 -> Angular 2 is actually a good example of how f****d you are when your heavily-used-library-you-trusted becomes deprecated…
A — Angular
For the frontend itself, originally I didn’t plan to do anything, since it’s mainly the backend that was lacking typescript boilerplate, while Angular 2 has a nice CLI for scaffolding. But then I though, “well, you should at least demonstrate how your cool backend api is used”. And I set out to create a small frontend. I have to say I really love to work with the CLI since I’m a person who generates quite small components (“one for every button”) and this just makes it a whole lot easier. I had my shell scripts in Angular 1 that did this for me, but with the AngularCli it’s an even neater experience. Also, when it comes to bundling a production build it’s unbeatable. Simply being able to run ng build –prod is just amazing. I like Angular2 a lot in general. The only thing that I’m still not 100% happy with is the state management since everyone does it a bit differently and there aren’t really any best practices, but apart from that, there’s not so much I found to nag about so far. Well , there are a few pitfalls, but mostly stuff works as I’d expect it to do.
N — Node
Finally, having strapped all of those things together, a functional REST-API and a simplistic frontend I decided to host a demo of the app. It’s still constantly improving as I’m working on the project, but that’s what it is now. For deployment I chose to, again, completely separate the backend and the frontend. The frontend just consumes the backend through http://demo.tsmean.com:4242 . I think that’s a pretty cool setup, since like this you can also use the remote backend to locally develop your frontend. For example if you’re only interested in the frontend, go ahead and get the git repo of the frontend and use that REST Api to test against! The backend has to allow CORS requests that this setup works, but apart from that nothing had to be configured. The frontend itself is served by a 20-line node script (also using express).
Where does this all leave me so far? I’m still quite excited about the stack. I really love that there’s no context switching, that there is just typescript, typescript, typescript (and some html and css). There was one exception, I first tried to write my deploy script in typescript, that experience really sucked. The node-ssh package was buggy and it was just so much more complicated, so I switched back to a regular shell script. I have tried many deploy script implementations over the years (js, ts, python, java, …) and I always came back to the simple shell script. But back on topic. I like the stack so far, except that I prefer MySQL to Mongo for anything that should become a real project. But of course I can’t really say so far how this stack will behave on scale. I haven’t built a multi-million user web-app with it yet, as the “first impressions” in the title might suggest. However, I don’t see any reasons why you wouldn’t want to use this stack for your production project. I wouldn’t argue too much about performance, since your development hours will probably be worth much much much more than your server costs. I would neither choose nor discard the stack based on performance. I wouldn’t say “node is non-blocking, we have to use it!”, since you can also get non-blocking with Scala, Java and so on. And I wouldn’t say “JS is a dynamic language it’s so much slower than compiled Java”, since you could always outsource computationally heavy tasks to dedicated web services and buying an extra node server also won’t ruin you. More of my concerns come from “how’s the tooling” and “how stable are the packages”? There I’m somewhere in the middle. Of course the tooling isn’t as great as you’d get it with Java. I still find IntelliJ sometimes a bit on it’s limit with my project (it gets a bit sluggish), I don’t know why though. Also the small things, like having to import typings, which are sometimes missing some times, having to set up NodeJS & mocha support in IntelliJ etc etc cost you some time. On the other hand, managing front- and backend dependencies with npm (or yarn) is cool. It’s again this “just one system” thing that makes you more efficient and gives a clean feel to the project. Bottom line: I really like to work fullstack-typescript and will definitely continue to develop my boilerplate / seed / starter-package / whatever. I think it’s a perfect start for your application as it’s easy to get started with, but it’s also a great choice for any medium sized project. If your project is the next biggest-web-app-on-earth, it might still be too early to use the stack, but there could also be an opportunity in adopting it with the recent explosion of typescript usage.
I’m currently working on improving the modularity of the system, so there’s really a
mysql and a
mongo module, and also authentication etc. is modularized. I’m doing this using typescript npm libraries, on which I’ve written a small tutorial how to build them trough the process at how-to-write-a-typescript-library.com.
I’d love to hear your thoughts on the matter. What are your experiences with fullstack typescript?