Monday, June 07, 2021

First impressions with Deno from building PlanetTypeScript.com

PlanetTypeScript.com is a content aggregator for all things TypeScript. It regularly polls RSS feeds for TypeScript related content, which it then list on the site, send out as a tweet via @planetypescript, and also as a weekly digest to subscribers.

Back when I used to write a lot of Java-related content on this blog, I found out that my blog ended up on www.topjavablogs.com/, which is a site that aggregates Java contents. So when I decided to play around with Deno, I thought a nice little idea would be to build something similar to topjavablogs.com, but for TypeScript. And that is how PlanetTypescript.com was born.

In this post, I will share some of my first impressions with Deno. The things I enjoyed and the bits I found inconvenient. Let's start with the cool stuff.

Native TypeScript Support

I find it super convenient that I could just write TypeScript without worrying about setting up a build chain that would take care of the transpilation to JavaScript. This is really nice and it makes TypeScript feel more like a standalone language in its own rights. This has to be one of the top-selling points of Deno for me.

Built-in utilities

The deno CLI comes with a whole lot of useful utilities and just comes in handy. For example deno info to check the dependencies. deno fmt, a code formatter,  deno bundle for bundling modules and dependencies into a single file, deno compile for creating a self-contained executable, etc.

I personally find dealing with build pipelines within the JavaScript ecosystem to be a tiring chore. Having something like deno bundle or deno compile, built-in is super useful, as it takes care of most of the heavy lifting when it comes to deployment.

Web API

Deno seeks to provide implementations of Web API, and this I found to be really handy. For PlanetTypeScript.com, I need to make HTTP requests and also run background tasks. I could use fetch and web workers for this. API's I am already familiar with coming from the Web, and no need to install third-party libraries. This is super convenient.

Good Standard Library

In the course of building PlanetTypeScript.com, I needed to have logging, base64 encoding, use hash functions, and generating UUIDs. I was able to find modules within the Deno standard library that I could use for all of these. The Deno standard library is quite decent and has a battery-included feel to it. You can peruse the available modules here.

IDE Support

I primarily use Jetbrains IDEs. When not within a full-blown IDE environment, I use Microsoft Visual Studio Code. Both of these tools have plugins that implement support for Deno and they work very well. I was able to use the visual debugger in IntelliJ, which was quite handy.

So these are some of the cool things that made a good first impression on me with Deno. Below are some of the things that were a bit of a hassle.

No Registry and Package Manager.

Deno does not have any well-known central registry from which a package manager manages dependencies. Instead, Deno works with plain URLs. This setup leads to certain consequences which I believe hamper the developer experience. 

For example, there is no central file to look into, to see all the dependencies of a project. To work around this, the convention in the Deno community is to re-import all dependencies from a file called deps.ts - basically recreating some sort of package.json.

Also, there is no easy way to quickly see if there are new versions of any of my project's dependencies. Or even better still, no command I could run from the command line that updates dependencies. 

I later learned about Trex and dmm which could be used to achieve some of these tasks. I can't comment on them now as I have not gotten around to try them out yet.

From the perspective of the developer, I am yet to see the advantage the Deno model brings to the table. Instead, it feels to me more like a philosophical design decision, rather than a pragmatic one.

Nascent Library Ecosystem.

The inability to find needed third-party libraries proved to be one of the main inconveniences.

I had issues finding a third-party library to deal with OAuth. I tried Dashport, but it has become incompatible with recent versions of Deno and Oak (the HTTP middleware library I used). I tried using Firebase-auth, but there is no support for Deno.

I use MailChimp for sending the Weekly digests. Since the content of the emails would be different weekly, I needed to build the message dynamically. This involves interacting with MailChimp via its API. Unfortunately, MailChimp does not have an API client library for Deno, so I ended up having to directly call the needed HTTP endpoints.

Deno does have a compatibility layer that makes it possible to use Node/npm modules from within Deno. There are also CDN's like Skypack that make it possible to import npm modules for use within Deno. What I quickly found out, is that these workarounds, work best for the simplest of libraries. It does not work for anything slightly complicated. For example, I could not use any of these methods to get the Node library for Firebase-auth nor Mailchimp client library to work.

This nascency is strictly not a structural issue with Deno and something to be expected, given how new Deno is. This is also the sort of thing that would improve with time.

Conclusion.

I enjoyed using Deno. Having native TypeScript support, various CLI utilities, and a battery included-standard library, makes it easy to get productive real quick. The main inconveniences I encountered can be chucked up to Deno still being relatively new, but even with that, it is still a hell of a lot usable/productive for a 3 years old project.



I am writing a book: TypeScript Beyond The Basics. Sign up here to be notified when it is ready.

1 comment:

Unknown said...

> For example, there is no central file to look into, to see all the dependencies of a project. To work around this, the convention in the Deno community is to re-import all dependencies from a file called deps.ts - basically recreating some sort of package.json.

Have you looked into import maps? https://deno.land/manual@v1.11.0/linking_to_external_code/import_maps - to me it seems like a package.json but with an added benefit of WebAPI-compliant aliasing functionality.