loading...
Cover image for Why the JS ecosystem is awesome !

Why the JS ecosystem is awesome !

gmartigny profile image Guillaume Martigny ・6 min read

The Javascript world is today's the most vibrant development ecosystem. It's popularity propelled it from a simple scripting gadget to the backbone of today's web. Browsers are more powerful each passing day, NPM registry grows to whooping 1 million packages and Node has long shown it's a competent back-end language.

Today, we're going to create a tiny project from scratch together and take full advantage of all that. I want to show you that you don't need years of experience to create something cool.
Buckle up, it's a long ride, but I promise you that by the end you can do it all by yourself.

Act I: the code

Let's say you have an idea you want to code. No, no, a simpler one. Something that can fit in one function. Something like creating a unique image per username, returning the hour of any timezone or return a random color.

For our purposes, we're going to create a function that give a blank image given dimensions. No big deal, just create a canvas, color it and return the data. We will called it lorem-pix.

So, I start every project the same way:

$ mkdir lorem-pix
$ cd lorem-pix
$ git init
$ npm init

Then, let's create that index.js and start coding:

const loremPix = (width, height, color) => {
    const canvas = createCanvas(width, height);
    const ctx = canvas.getContext("2d");

    ctx.fillStyle = color;
    ctx.fillRect(0, 0, width, height);

    return canvas.toDataURL("image/png");
};
module.exports = loremPix;

At this point, you should note that createCanvas is not defined. If I was in a browser, I'll just have to do document.createElement("canvas"), but I already know I don't want to stay in the browser environment and Node has no Canvas support. 😱
What could we do ?

Act II: NPM

With hundreds of thousands of packages, NPM potentially hold a solution for any of your problems. As NPM-cli comes bundled with Node, it's safe to say that it's the most influential program in Javascript.

Don't mix-up NPM and NPM-cli. The former is the public registry holding all the codes while the latter is the utility requesting from the registry.

A bit of research gives me exactly what I need. All left to do is fetching the desired dependency.

$ npm install canvas

And add a require at the top of our index.js file.

const { createCanvas } = require("canvas");

Note that Node sadly don't support the import statement as of today.

And voilà, our function is now done. We can even publish it at NPM so anyone can use it. Just make sure your package.json is correctly filled and we're good to go.

$ npm publish

Ok, this is already pretty great. We have a function that rely on someone else code and we published it so anyone can rely on us.
But why not go a little further ?

Act III: CLI

Since NPM-cli 5.2.0, a new command is available: npx. Thanks to it, you can execute code hosted on NPM with a single command line. It magically download, install what need to be and run the required binary file.

But we need to have a binary executable. Our JS function is great, but can only be called by a JS script.
Let's remedy that by creating a new file named cli.js. Running a plain text file on the operating system is not going to work. We need to tell which program have to parse the code inside it. In our case we need it to be Node (default is bash on unix or cmd.exe on windows). Fortunately, we can do so with a shebang.

#!/usr/bin/env node
const loremPix = require(".");
const { writeFileSync } = require("fs");

const inputs = process.argv.slice(2);

const dataURL = loremPix(...inputs);

writeFileSync("lorem.png", dataURL.split(",")[1], "base64");
console.log("Done creating image.");

On the first line, you can notice the shebang thing. Then we import our own library and the Node file-system utility.
Next, we gather the inputs from the command-line arguments, the first one being the program (node) and the second one the file executed (cli.js). Anything after that is treated as arguments to our function.
Finally, the script write the file using the returned data. Details don't matter, but it need a file name, some data and the encoding method.

After a chmod to add execution rights, we are now able to run this script like any program installed on your computer.

$ chmod +x cli.js
$ ./cli.js 200 150 red
> Done creating image.

Boom! A new file called lorem.png appeared right next to the cli.js and you guessed it, it's a red image of 200 by 150 pixels.

Red image

Incredible! 😮

It means that anyone with Node installed can call npx to use our fantastic library.

$ npx lorem-pix 200 150 red

So now, what if we want to make it available to user even without Node ?

Act IV: API

Historically, JS was created to be used on back-end and Node is the rightful heir of that history. If our code is deployed on a Node back-end, it can be run with a simple URL call.
I'm going to use ZEIT's now because I love it. It's so simple it hurt.

First, we can again add a new file called api.js and fill it according to the documentation.

const loremPix = require(".");
const { parse } = require("url");

module.exports = (request, response) => {
    const { query } = parse(request.url, true);
    const { width, height, color } = query;

    const data = loremPix(width, height, color);

    response.writeHead(200, {
        "Content-Type": "image/png",
    });
    response.write(data.split(",")[1], "base64");
    response.end();
};

Almost like cli.js: import our library, parse the URL for the right parameters and write the result to the response back to the user.

We also need a now.json file to configure now.

{
    "version": 2,
    "builds": [
        {
            "src": "api.js",
            "use": "@now/node"
        }
    ],
    "routes": [
        {
            "src": "/api/(?<width>[^/]+)/?(?<height>[^/]*)/?(?<color>[^/]*)",
            "dest": "/api.js?width=$width&height=$height&color=$color"
        }
    ]
}

First we tell now to use Node to run api.js. Kind of like the shebang for the cli.js.
The hieroglyphs by the end is a regular expression. Users are lazy and so am I. It's easier for me to parse URL like api.js?width=200&height=150, but it's more simple for users to write api/200/150. The regexp do just that by rerouting requests.

Ok, time to deploy the API.

$ npx now login
$ npx now

Once done, the program tells you which URL you can use to execute the code. In my case:
https://lorem-pix-o5fjmzam5.now.sh/api/200/150/red

The API return an image whenever someone request it. It means that any HTML page can use it without any installation.

<img src="https://lorem-pix-o5fjmzam5.now.sh/api/200/150/red" alt="placeholder"/>

Hol' up a minute !

 Act V: Webservice

Any HTML page can use it ? Why not create our own page ?
We already set now to host the JS code, we can add a static HTML page along side it. More than just a landing page to present our project, we can have user inputs with live preview of the result.
Yet another file, this time of course named index.html.

<h1>Lorem pix</h1>
<form id="form">
    ...
</form>
<img src="" alt="live preview" id="preview"/>
<script src="front/live-preview.js"></script>
<script>
const form = document.getElementById("form");
const img = document.getElementById("preview");

form.addEventListener("change", () => {
    const { width, height, color } = form;
    livePreview(img, width.value, height.value, color.value);
});
</script>

I put the CSS and JS file under the front folder just for organization's sake. Here's what our script looks like.

const API_URL = "https://lorem-pix-o5fjmzam5.now.sh/api";

const livePreview = (img, width, height, color) => {
    const url = `${API_URL}/${width}/${height}/${encodeURIComponent(color)}`;
    img.src = url;
    return url;
};

Pretty straightforward!
I just used encodeURIComponent to avoid the # charactere messing with the URL.
Finally, we need tell now to serve the static files in now.json.

"builds": [
    ...
    {
        "src": "index.html",
        "use": "@now/html-minifier"
    },
    {
        "src": "/front/*",
        "use": "@now/static"
    }
]

Let's not forget to deploy again with npx now and we are live.

Conclusion

What a ride!
Being able to access the same function as a package, a CLI, an API and a front-end webservice is still incredible for me. I highly encourage everyone reading to try and do it's own. You can access the whole code-base at Github and copy/paste from here.
With a little more creativity than just making a blank image, I'm sure all of you can offer some great product. Be sure to share them in comments below.

Peace 🙏

Posted on by:

gmartigny profile

Guillaume Martigny

@gmartigny

JavaScript spitter and video-games gatherer.

Discussion

markdown guide
 

I disagree.
The JS ecosystem is a mess but let's put in the viewpoint of a novice

Language

Javascript or is it ECMAScript?

https://uploads.disquscdn.com/images/c0f07f4561981ad3ee94557ef05bd8c98e1c756b7973c3afcca20639c34decf5.gif

There are two JavaScript, one is the old one (also called ECMAScript 5 or ES5), the one that it's used by most browsers. And the other is the new one (EcmaScript2015 or ES6) that is used by nobody (no browser) but Node.js. Node.js is focused on the new one, so JavaScript is split in two. But but eventually, every browser will support EcmaScript2015... Yes but eventually could mean 5-10 years and we couldn't wait until them.

Language (again?)

Yep, some frameworks don't work with vanilla-JavaScript (or es5 or es6) but with TypeScript or Babel (CoffeeScript kicked the bucket), they are transpilers, but in our vision (developer) they are two new languages. So we have 4 languages: javascript (or es5), ecmascript2015 (or es6), typescript and babel and we should pick at least 3.

Node.js could do everything.

Not really.

It's possible to create a single page on Node.js with only a few lines of code but what if we want something more advanced?. And when I say, "advanced", I told more than one page or a page with an image. Then, we need to add "more stuff" (libraries), and we should learn (and support) them.

For node.js, libraries such as Express, React, Angular, VueJs are not optional, they are required, and we must learn them.

So a novice must learn different technologies, it's not as simple as "add libraries" and hope for the best.

In comparison:

  • PHP is ready to the web, we don't need to add a library, we could add some libraries or framework (using composer) but they are optional.

  • C# (MVC or Webforms) is also ready to the web, we don't need to add external libraries, they are also included but we could add new libraries using NuGet.

  • Python is not ready for the web but it's easy to add the libraries for web (using PIP). Python is mainly divided on Django and Flask.

  • Java is not for the web but Java Spring Boot is, we could add libraries using Maven but the main libraries are ready to add.

It is how Spring Boot developers start a project:

https://spring.io/guides/tutorials/spring-boot-kotlin/images/initializr.png

Working pipeline

Let's say we pick react, so we need to know:

  • javascript.
  • node.js and npm
  • react and jsx (and we should kiss bye html)
  • yarn too (why?)

for a single web page!.

Plus

  • redux / react router / express
  • and some library for the database, session and many others.

SHEEESH!.

Libraries

And about the libraries, NPM is a minefield.

https://media0.giphy.com/media/gOt4VWId8TYoo/giphy.gif

 

I agree to some extent that some things about the JS ecosystem are a mess, but not these examples.

ES6 is now widely supported in every browser with Internet Explorer being the only exception; just take a look at caniuse.com/#search=es6, where's that "used by nobody but Node"?

Secondly: TypeScript is a complete optional language for those who want types in their JS experience and it's definitely not suitable for someone who's a complete JS beginner. And Babel, as you said, is a transpiler but it's just that, if anyone mistakes Babel as a language they need to check what Babel does. So we just have one language, JavaScript, and two versions. Any confusion with this is the same as saying: "Oh, well, I get confused with C# not having support for Generics in C# 1.0 but having them in C# 2.0!"

I don't understand why you consider that React, Vue or Angular are not optional. You can just make any kind of development with pure JS the same way you can do it with PHP. React, Vue or Angular are the same as Laravel, .NET MVC, Flask or Spring: libraries to make your life easier, but if you want you can go ahead and do it without them.

Maybe in React it's hard to start a project (though given that it's the most famous view framework right now I highly doubt that there's no project like Spring Initilizr for it), I don't have experience with it, but in Angular or Vue here's how hard it is to start a new project.

Angular:

ng new name-of-the-project

Vue:

vue create name-of-the-project

And voilà, you just got yourself everything you need to start developing with a nice architecture and some example files. You DON'T need to learn Node if you're developing a front-end app, you DON'T need to use Yarn (it's the same as NPM, so what's the point if you don't want?), so what's your complaint here? That you need to learn some library to use that library?

Again, I agree that some parts of the JS ecosystem are a mess, the amount of libraries that are published in NPM for such trivial things like padding a string just because the developers are lazy enough to write a few couple of lines is awful, but your complaints here seem more like a problem with not knowing the ecosystem enough rather than a problem with the ecosystem itself.

 

You could just start with nodejs itself without hassle if you will. Lib are just options 😊

If you want raw, keep it raw do with nodejs itself. They are just tooling same as spring you got your tooling right ahead with that IDE.

 

I can't create a single page on Nodejs that shows an image without writing tons of line of code, ergo a library is a must.

var http = require('http');
var fs = require('fs');
var path = require('path');

http.createServer(function (request, response) {
    console.log('request ', request.url);

    var filePath = '.' + request.url;
    if (filePath == './') {
        filePath = './index.html';
    }

    var extname = String(path.extname(filePath)).toLowerCase();
    var mimeTypes = {
        '.html': 'text/html',
        '.jpg': 'image/jpg'
    };

    var contentType = mimeTypes[extname] || 'application/octet-stream';

    fs.readFile(filePath, function(error, content) {
        if (error) {
            if(error.code == 'ENOENT') {
                fs.readFile('./404.html', function(error, content) {
                    response.writeHead(200, { 'Content-Type': contentType });
                    response.end(content, 'utf-8');
                });
            }
            else {
                response.writeHead(500);
                response.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
                response.end();
            }
        }
        else {
            response.writeHead(200, { 'Content-Type': contentType });
            response.end(content, 'utf-8');
        }
    });

}).listen(8125);
console.log('Server running at http://127.0.0.1:8125/');

Instead, in PHP we could write

<?php
echo "<img src='myimage.jpg' />";

PHP and Python are really easy because they are straight to the problem.

const http = require("http");
http.createServer((request, response) => {
    response.end("<img src='myimage.jpg'/>")
}).listen(80);

Specifically, the code is:

const http = require("http");
http.createServer((request, response) => {
    response.writeHead(200, { 'Content-Type': "text/html" }); // unless it returns a text
    response.end("<img src='myimage.jpg'/>")
}).listen(80);

But it is unable to serve the image anyway.

I think that you may continue to develop your applications using php or python if you like them. I've used php and I like it. I've considered also python and I like it. But I think my next project will be with Node. I love to use the same language full-stack. God bless

Well said. Its hard to judge without knowing the environment and core of language itself.

PHP can do like that because it mean to be run on server at the first place. But if you want to serve your PHP file and create a server without server like apache/engineX try that. And serve your image :)

Jorge you could do with your own choiches. There a lot of programming language. And they trying to solve some other problem that they may have. And as always God Bless

 

The think is that PHP run on server this makes simpler approach of serving images on server, compare it with other languange like JAVA without JAVA Spring, Or C# without ASP.Net :)

15 years ago, the ecosystem of Java was a mess with tons of vendors there and here, and we had different things to do the same. And now, we have the same situation with Javascript.

So about C# and Java, Javascript is just catching in up.

 

Well said.

+10 bonus points for being so polite

 

NPM registry grows to whooping 1 million packages

Are you joking? This is a good thing? With packages like is-odd and is-even? It's a complete and utter mess

and Node has long shown it's a competent back-end language

Node isn't a language and honestly anything can do the job, once you get used to it. Node lacks a lot of things, but simplicity attracts people, not it's features or anything related to being competent or mature or anything else as language, because it's not.

Being able to access the same function as a package, a CLI, an API and a front-end webservice

This is nice indeed, but nothing that new or amazing. We were sharing code between different platforms, operating systems, etc even in the 90s and this is only how far I remember, so probably much longer.

 

Are you joking? This is a good thing?

No I'm not. I know it's a very dividing subject and I agree is-odd and alike are a stretch. However, modules should be trusted black-boxes. If you don't want to trust others, you still have the choice to code you own.

not it's features or anything related to being competent or mature or anything else as language, because it's not.

I don't get why JS still has such a bad rap. At the same time I don't care if people like it or not. I just pick the language that allow me to do the most, and today it's JS.

nothing that new or amazing.

No one has the truth. Every word on Internet is subjective. Moreover, once again, if JS is awesome (being true or not) doesn't imply other are not.

 

NPM - we all know what happened, when the turkish guy got offended and deleted his own package: qz.com/646467/how-one-programmer-b...

So about trust - you will quickly get bored of checking who you trust if you decide to inspect a more complex package. An old joke is that JS developers compete if they can build a meaningful app with less than 100 dependencies. You add 10-15 dependencies and and that quickly escalates to over 300 folders in you node_modules. So theoretically - you can, practically - no way in hell.

I don't get why JS still has such a bad rap.

OK you MUST be joking this time. Right?

The "this" hell, funny features like parsing numbers in octal format by default, "funny" date functions, assuming months start from 0 etc. Yeah all of this helps the good reputation I guess.

And yes, we get around these parts by using TypeScript or literally anything else but plain old vanilla JS, exactly because of this.

Anyway, keep up the enthusiasm, and don't give up. Learn more and have fun :)

 

Cool guide!

I think the JS ecosystem got a lot of things really right. And it's still developing at speed. Things I like about the JS ecosystem:

  • lots of CLI tools: npm, npx etc
  • convergence wrt packaging
  • convergence wrt application configuration (package.json)
  • good package registry (npm)
  • doing local stuff like running tests is quite fast

There's definitely things not to love in the JS ecosystem, but that's a topic for another post :-)

 

There is very little JS here, you are amazed by NPM and now.sh while most code is NodeJS's libraries, JSON or HTML.
You made a good tutorial for beginners but nothing really showing how amazing javascript can be.
Because now.sh supports other langages anyone can make the same article with titles such as "PHP is incredible", "GO is the best"...

It sure is nice to see the existence of all theese tools.

 

And I would love to read those articles. The fact (being true or not) that JS is great doesn't undermine other languages.

 

Interesting article, thank you, coming from a novice JS developer.

Primarily I am a PHP developer. I prefer MPAs over SPAs. Using the right tool for the right job is important.

Personally, I don't enjoy JavaScript that much. That's just me. However I will use JS if I'm building a real-time application, or high-load HTTPS RESTful APIs. Many times JS is the perfect route to solving a problem, for me at least.

There are many places where JS excels. And places where it fails. For one, I think NPM and the libraries are a mess! So many packages. So many libraries. Some simple frameworks require 800+ packages! There are also security issues involved including SO MANY packages.

But ya know what? In the end, some of those frameworks make it beautifully easy to deploy applications, which is great. <3 (Looking at you Vue and Next.js)

Lots of upsides and downsides. Weight them out. Decide what's best for you.

I hold very strong to this opinion, that we should not be trashing tools. Programming languages are tools.

The JS ecosystem is awesome, wonderful, but bad too. Nothing is perfect. And perfection is subjective to each individual.

 

Thanks for that beautiful review. I wholeheartedly agree with everything you said.

Nothing is perfect.

Yes, absolutely and that's why I state it's awesome ... not perfect.

 
 

Wow that is so much work but that is probably because of all the garbage we have forced into the pile of garbage JavaScript already was. I am glad you have found something you like but JavaScript isn't the solution to everything infact it's really only good in a small group of use case scenarios. Why do we keep overengineering simple things?

 

You seems to have a conflicting relation with Javascript and that's alright. Of course, JS is not meant for everything, that would be bad.
The fact that JS is able to do CLI, web API and front-end scripting, all of that with the same code-base is still awesome in my opinion.
I don't know where do you see so much work. This article is quite long because it was aimed at medium to low level devs. The code is somewhere around 100 line of code, this is far from a lot of work.
What solution would you have recommended that is less over-engineering ?

 

First off just want to point out that you mention that JS was created to work on the back end but unless I am mistaken it was created to make buttons work on the front end and it wasn't until node that we could use it on the backend.

Javascript is being presented as the solution to everything these days, and not only that, but it changes so much that what is new and what you need to know at this moment is outdated and not cool anymore in about 5 minutes it seems. What this leads to is people chasing after every new thing that comes out or getting frustrated and giving up. We need to help the new people instead of scaring them off which is what all this pushing JavaScript leads to. JavaScript, language we used to say was for people who couldn't figure out programming has turned into a huge complicated mess that tries to do everything and its getting harder to the point where it rivals C++ in difficulty if it hasn't already surpassed it.

How many different languages and tools and npm packages did this require, and yet your trying to convince people this is easy and aiming at new devs, and it's no wonder we scare people off.

As far as an example of an easier way of doing things here is some c# code that I found in a quick google search on how to create an png file in unity and export it. This code has 6 lines to it. I know its a different situation but still if your looking to make a png file and export it this is easier than what you did. It used only one language, no need to find and install a bunch of packages, no config files no scripts to let your operating system work with it or anything.

//create the bitmap
Bitmap bmp = new Bitmap(50,50);
Graphics g = Graphics.FromImage(bmp);

 //paint the bitmap here with g. …
 //I just fill a recctangle here
 g.FillRectangle(Brushes.Green, 0, 0, 50, 50);

 //dispose and save the file
 g.Dispose();
 bmp.Save(@"filepath", System.Drawing.Imaging.ImageFormat.Png);
 bmp.Dispose();

if we want to help more people become developers instead of scaring people away we need to find and show simple solutions that serve a real need not scary looking things that don't really help anyone out. We need to stop promoting JavaScript for everything because learning php for example is not hard at all infact it is super easy and most anyone can pick up the majority of it in an afternoon.

Here is a python example using the Pycairo library to create a png drawing it using vector math and then exporting it which can be found at pycairo.readthedocs.io/en/latest/t...

import math
import cairo

WIDTH, HEIGHT = 256, 256

surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
ctx = cairo.Context(surface)

ctx.scale(WIDTH, HEIGHT) # Normalizing the canvas

pat = cairo.LinearGradient(0.0, 0.0, 0.0, 1.0)
pat.add_color_stop_rgba(1, 0.7, 0, 0, 0.5) # First stop, 50% opacity
pat.add_color_stop_rgba(0, 0.9, 0.7, 0.2, 1) # Last stop, 100% opacity

ctx.rectangle(0, 0, 1, 1) # Rectangle(x0, y0, x1, y1)
ctx.set_source(pat)
ctx.fill()

ctx.translate(0.1, 0.1) # Changing the current transformation matrix

ctx.move_to(0, 0)

Arc(cx, cy, radius, start_angle, stop_angle)

ctx.arc(0.2, 0.1, 0.1, -math.pi / 2, 0)
ctx.line_to(0.5, 0.1) # Line to (x,y)

Curve(x1, y1, x2, y2, x3, y3)

ctx.curve_to(0.5, 0.2, 0.5, 0.4, 0.2, 0.8)
ctx.close_path()

ctx.set_source_rgb(0.3, 0.2, 0.5) # Solid color
ctx.set_line_width(0.02)
ctx.stroke()

surface.write_to_png("example.png")

There is just a couple of quick examples. JavaScript sucks when you look at the alternatives.

Technically JavaScript has been a server side language since 1995 (source). Although I don't think it was used a lot up until we got node.js.

I disagree with a lot you're saying.

JavaScript, language we used to say was for people who couldn't figure out programming has turned into a huge complicated mess that tries to do everything and its getting harder to the point where it rivals C++ in difficulty if it hasn't already surpassed it.

OK, where do I begin?

JavaScript is a language with a lot of good features. It also has some ugly warts, definitely, and most JavaScript devs really know that this is the case. The reason why JS wasn't taken seriously is not because of the language. This had more to do with browsers not running JS fast enough, computers were slower and a couple more reasons.

JavaScript, the language, has not gotten that much new features in the last few years. The features that were added are actually quite good and very useful.

As far as an example of an easier way of doing things here is some c# code that I found in a quick google search on how to create an png file in unity and export it.
no need to find and install a bunch of packages

So your counter example uses Unity which is a video game engine. That's sort of like saying "welding a bicycle yourself is more work than buying a car". Well duh.
😄

Here is a python example using the Pycairo library...

Ah and now we come to your Python example, yum. Don't misunderstand me, I like big parts of Python.

Now please show us how, with very little work, you can make this Python script into a CLI, a package and a deployed web app.

(hint: this is quite a bit of work actually)

because learning php for example is not hard at all infact it is super easy and most anyone can pick up the majority of it in an afternoon

OK, and by now I get the feeling you're trolling. I can't take you seriously anymore.

Well played.

All languages have a reason to exists. Monopoly has never been any good anywhere. We couldn't have Javascript without the syntaxe breakthrough of Java, without the C++ V8 engine, without the Erlang CouchDB Database of NPM ...

JS maybe's not perfect, but for newcomers I'll recommend it without hesitation (I know, I'm biased).

The complaint is that JS requires libraries and configuration and your counter-example is in a compiled language that requires an SDK and uses Unity? Wow.

 

There is not a single line which tells me why node.js is so awesome.

 

Read the title again: "Why the JS ecosystem is awesome!"