JavaScript Differences of Back- and Frontend

K - Aug 6 '20 - - Dev Community

TL;DR Search on Kangax' compat-table if a feature is available for your runtime

So you got years of JavaScript experience, and now you want to use these skills on the backend? You're lucky because most JavaScript-based backends use Node.js, which you probably already know from the tooling you used to bundle up your frontend code.

But even if you used Node.js, maybe it's a good idea to look into the differences it brings. With Deno, there is also a new kid on the JS runtime block!

In this article, I'm going over the differences that frontend devs should expect when writing JavaScript for a backend.

ECMAScript Version

ECMAScript Versions

The first difference lies in the ECMAScript version of the JS runtime supports. ECMAScript is the standard that defines the JS features a runtime should have. While ECMAScript versions are backward compatible, you can't expect to have a runtime that supports version ES2015 to have ES2019 features.

const z = x?.y ?? 10;
            ^

SyntaxError: Unexpected token '.'
Enter fullscreen mode Exit fullscreen mode

The process here is as follows: A technical committee takes proposals for language features, they talk about it and refine it, and while that happens, the runtime creators implement the features to see if they work. If they are deemed suitable, they will be included in the next version of the standard.

On the frontend, we have to look at the stats on our servers to find out what version our clients support. On the backend, we usually have the advantage of choosing our runtime and, in turn, our ECMAScript version.

While you can usually "compile down" to a version supported by your runtime, it's nice to write code that runs without any tooling. Look at your Node.js version, and check what features it support.

An important note here: Most runtimes don't support all features of an ECMAScript version, so don't just look for a version, but a feature. Tail call optimization, for example, is an ES2015 feature, but it's only supported on Safari. Still, other browsers support many other >ES2015 features.

Of course, this is the same for all runtimes, Deno, Node.js, and the various browsers.

Browser APIs

Major Browser Logos

The next point is the browser APIs support of your runtime. The ECMAScript version defines some APIs, but not all of them. The most obvious example is the DOM API. Non-browser runtimes like Node.js and Deno don't support the DOM, because there is no UI to render it to.

const y = window.decodeURI(x);
          ^

ReferenceError: window is not defined
Enter fullscreen mode Exit fullscreen mode

The differences in Node.js and Deno are that Deno tries to use as many browser APIs as possible. This difference means that you have to use the HTTP package in Node.js to send a request, but you can use the fetch API directly in Deno.

A list of browser APIs available in Deno can be found in their docs.

If you got a list for browser APIs supported by Node.js, please comment!

Access Control

File & Network Access Images

When using a browser, you're limited to what the browser APIs allow you to do, and lately, many of them even ask the user before they are allowed to access hardware. You can only use HTTP network connections, and you can't access servers on other domains by default. Overall the browser is a harsh mistress.

// Browser
document
  .getElementById(fileInputElementId)
  .addEventListener("change", ({target}) => {
    const [file] = target.files;
    const reader = new FileReader();
    reader.onload = processContent;
    reader.readAsText(file);
  });

// Node.js
fs.readFile("config.json", processContent);
Enter fullscreen mode Exit fullscreen mode

Access control is different in the backend. If there exists a package that allows access to any hardware or you can implement such a package yourself, you can access it. You are only limited by the permissions of your operating system. Want to send UDP to a domain different from your server? No problem!

Well, at least that is true for Node.js. Deno goes a different route here and requires you to give the runtime permissions via command line parameters. If you don't allow writing files, and a package you use needs to write a file, Deno will tell you.

Module Systems

Package images

Many browser vendors finally settled down on a module system after many years and with the help of the ECMA committee. Now it's possible to load JavaScript from within JavaScript without any hacks. All major browsers support ES modules, and if you define your script tag with type="module" you can import away.

// ES module import
import value from "library";

// CommonJS module import
const value = require("library");
Enter fullscreen mode Exit fullscreen mode

Things look different on the backend, primarily for Node.js, because it couldn't wait years for the standard to be approved. Node.js defined its own module system, called CommonJS. While the current Node.js version has experimental ES-modules support, it will take a while to get things stabilized, and then all CommonJS modules have to be converted too.

Since Deno is a fresh approach to non-browser JS runtimes, it didn't have that problem. Deno supports ES modules out of the box, and you can import an URL that points to an ES module JS file, it will be downloaded and cached.

Summary

JavaScript makes the whole stack more accessible than any other language, and building a backend has never been easier.

While there are still differences that can make a package you know from the frontend unusable on the backend, these gaps are getting smaller every new version. Both Node.js and Deno try to converge with the browser runtimes more and more.

Some "Function as a Service" providers like Cloudflare even go their own way and support the Service Worker standard as their runtime, to make things feel more browser-like.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .