My Full JavaScript Stack
At least look at all the pretty logos!
Here’s a technical column for a change. I have been mostly a front-end software engineer for a while, doing web browser based and mobile apps. A few years ago my employer tasked me to develop a full stack application. After losing the argument that I was not qualified for the job (and that the job was impossible anyway), I thought, what the hell? If you’re willing to pay me to learn full stack, I’ll give it my best!
I am still supporting and developing new features for that app and customers are using it in production. I’m pretty happy with how it turned out. Astonished, in fact, that it turned out so well, thanks to modern software technologies, libraries, and frameworks. So yay, me. Just in case you may be interested, here’s what I wound up with for my full stack. I added all the product logos so you can skip my tiresome words and just scan the images! (A pity we cannot resize images in current Medium.)
Operating System: desktop Ubuntu Linux on x86 metal. Company’s choice, and a good one. (I wouldn’t have taken the job if they were a Windows/.net/Azure house.)
Environment: NodeJS, because I wanted to write in JavaScript. My C coding sucks. Electron was an alternative at the time, but fuck that. Node (and npmjs.com) is great. (Though the problems with npm dependencies being written about today are very scary.)
Framework: FeathersJS. Since all of this was new to me except for the front end, I wanted to use a framework that would provide a strong foundation for me. I found FeathersJS. To quote from their website:
Feathers is a lightweight web-framework for creating APIs and real-time applications using TypeScript or JavaScript.
I used their demo app feathers-chat to bootstrap my project. BTW Feathers incorporates the Express.js server for the back end.
Feathers has worked out great, I’m very happy with my choice. My only regret is that I’m on Feathers v4 and Feathers v5 has come out, but I haven’t had the chance to migrate to it. Migration would/will be a big job.
Unified Data Store: feathers-vuex. Great feathers integration, obs.
Front-end framework: VueJS. My other project with this employer uses AngularJS. I didn’t want to use that because it has been superseded by Angular, so that’s the one to use if I wanted to stay with Angular. But I thought it was overkill for this application, and besides, working with AngularJS and Angular simultaneously on two projects would be confusing as hell. (I am the sole front-end coder at this small company.) I wanted to stick with a major framework because I didn’t know enough to choose among the minor ones, so it was down to VueJS or React. I thought React was just too damn complicated and different, or maybe I was just being contrarian. Anyway I picked VueJS. It was very easy to get going with, perhaps because of its similarities to Angular. I’ve been very pleased with VueJS and would choose it again in a minute. (Of course, some interesting alternatives have become popular recently. Svelte, anyone? Ember? Next.js?)
But who needs a front-end framework, anyway? Why not just bare html/javascript/css? (Or server-rendered pages?) And why is my Web UI structured as a single-page app (SPA)? Frankly, I’m just not that sophisticated as a software engineer. I started as a script-kiddie and read a few books, but I’m completely self-taught and never worked with a more senior developer. SPA and frameworks is my hammer, so the job looked like another nail to me.
UI Library: Veutify. I knew a UI library would save a lot of work and present a prettier interface than I could design myself. (Our company has no real UI/UX designers, just me.) I chose Vuetify because it has everything I needed, it looked nice, and has great VueJS integration (again, obs). It has worked out okay but I suspect there is something out there that would have been a better choice because of certain limitations I ran into along the way. Of course, I suppose any library is going to have its plusses and minuses. If I were starting a greenfield project today, I’d be inclined to look at using ES6 reusable components.
Deployment environment: Docker containers. I knew this app was going to be complicated so I wanted to containerize it. But I had zero experience with containers. So I learned Docker. In the process, I learned about Kubernetes and was tempted to go that way. If I had been doing a multi-server deployment initially, perhaps I would have. But Kubernetes is said to be way difficult to learn. Docker looked fine for our single-server initial deployment. So I chose to do a docker-compose architecture.
Docker has been a lifesaver. Besides the 4 to N containers of the code I wrote (N because multiple copies of one particular container—line 100 or more—can be needed depending on the deployment), the app also pulls in the following third-party Open Source containers:
- nginx for a reverse proxy
- MongoDB to back the Vuex unified data store
- Elasticsearch for a statistics and logging database
- Kibana for Elasticsearch management
- Metricbeat for host server monitoring
- ElasticHQ for monitoring/management of Elasticsearch
- Grafana for statistics tables and graphs
- Portainer for monitoring Docker
- mongo-express for managing the Mongo database
- Pure-FTPd FTP server
Docker has worked great, a real life-saver. We even use Docker Hub for distribution of our containers. The company has a paid Docker Hub account and we keep our custom containers private. (Though I keep recommending to management that we make our containers public since their use is controlled by licensing anyway.)
Database: Elasticsearch. The app handles a lot of time-series statistics like network traffic statistics. We needed an industrial-strength database to hold them, and one that integrates nicely with a graphical dashboard analysis tool like Grafana. Somehow we ended up on Elasticsearch. It is the one thing in the stack I believe I got wrong. It’s a great database and it is working out fine; it’s not a disaster by any means. But what I discovered is that Elasticsearch not optimized for time-series data, which is mostly what this app handles. In addition, its integration with Grafana is limited, especially as per time-series data. I’m not sure what the better choice is, but I am sure there is one. (Perhaps Prometheus?)
Another thing about Elasticsearch is that it has been a pain to integrate. For years, “Kibana won’t start” was the bane of my life, and this appears to be a not-just-me problem. In fact, one of the reasons for using Grafana for charting was that it was so frustrating getting Kibana—which also does charting—to come up consistently. But once it is all up and running, it is very reliable.
Conclusion
So that’s my stack and I’m sticking to it! And that’s what it means to be a full-stack developer.
— Lannie Rose, January 2023
preferred pronouns: she/her/hers