šŸ² Mengenal Deno šŸ¦•

DENORUNTIMEJAVASCRIPTTYPESCRIPT

tl;dr

Deno adalah runtime aman untuk JavaScript dan TypeScript.

Aman?

Secara default Deno tidak memperbolehkan akses ke jaringan, berkas ataupun environment kecuali secara eksplisit mengijinkan untuk itu.

Perbedaan dengan Node.js?

  • Deno tidak memakai npm.
  • Deno tidak mempunyai node_modules.
  • Tidak ada konfigurasi seperti package.json.
  • Mendukung TypeScript langsung sehingga tidak diperlukan transpiler dan konfigurasi yg rumit.

Kelebihan?

  • Single executable file.
  • Memakai ES Module import.
  • Mengedepankan import module dari URL.
  • Semua paket kebergantungan disimpan di cache global dan download hanya diperlukan sekali yaitu saat pertama skrip dijalankan.
  • Embeddable karena Deno dibangun memakai Rust yang tersedia melalui crate.

Apakah Deno akan menggantikan Node.js?

Menurut perkiraan saya tentu saja tidak untuk saat ini karena dibandingkan Node.js, Deno menurut saya masih dalam fase-fase awal berkembang di ekosistem JavaScript. Poin utama atau kelebihannya Deno menurut saya ada pada dukungan langsung terhadap TypeScript.


Fitur

Seperti saya tulis sebelumnya bahwa Deno adalah single executable file sehingga instalasinya sudah pasti cukup sederhana, silahkan download di Github, karena saya memakai Windows 10 maka sepanjang anda meletakkan Deno pada path environment OS maka anda bisa memakai Deno dengan mudah melalui cmd.

C:\tools>deno  --version
deno 1.0.2
v8 8.4.300
typescript 3.9.2

artinya Deno memakai v8 engine versi 8.4.300, mendukung TypeScript versi 3.9.2.

Salah satu fitur dari Deno yang saya suka adalah adanya self upgrade, fitur tersebut ada pada compiler sepeti Rust, benefitnya adalah anda bisa meng-upgrade versi Deno secara langsung dan tidak ribet.

C:\tools>deno upgrade
Checking for latest version
Version has been found
Deno is upgrading to version 1.0.2
downloading https://github.com/denoland/deno/releases/download/v1.0.2/deno-x86_64-pc-windows-msvc.zip
...

Mengedepankan Protokol URL

Salah satu keunggulan dari Deno adalah mengedepankan protokol web yaitu URL artinya segala import paket mengutamakan protokol tersebut, sebagai contoh

b.js

import { info } from "https://blog.sajen.id/s/info.js"

console.log(info())

Dependensi pada skrip diatas akan di download pertama kali dan di Deno tidak ada direktori deps seperti node_modules pada Node.js. Pada Deno deps disimpan di cache sentral sehingga sangat reusable bagi aplikasi lain serta menyederhanakan deployment aplikasi.

C:\Users\E Q U A N\AppData\Local\deno\deps

Automasi & Tooling

run

Deno dengan sangat sederhana bisa menjalankan skrip dari protokol URL melalui command run

C:\Users\E Q U A N\>deno run <skrip_url>

install

Deno memiliki fitur pemembuatan shortcut command sehingga anda bisa memanggil shortcut tersebut pada command line. Fitur ini disediakan oleh command install

C:\Users\E Q U A N\Desktop>deno install s.ts
Download https://blog.sajen.id/s/info.js
Compile file:///C:/Users/E%20Q%20U%20A%20N/Desktop/s.ts
āœ… Successfully installed s
C:\Users\E Q U A N\.deno\bin\s.cmd
ā„¹ļø  Add C:\Users\E Q U A N\.deno\bin to PATH
    set PATH=%PATH%;C:\Users\E Q U A N\.deno\bin

Kalau pada Node.js fitur ini hampir mirip dengan npm link hanya saja pada Deno jauh lebih sederhana tapi cukup efektif.

s.cmd

% generated by deno install %
@deno.exe "run" "file:///C:/Users/E%20Q%20U%20A%20N/Desktop/s.ts" %*

fmt

Deno secara default menyediakan fitur all-in-one dalam tooling seperti pemformatan source code.

bundle

Satu lagi fitur Deno yang amat sangat berguna yaitu mem-bundle atau mempaket skrip dan dependensinya menjadi satu file!.

Hal ini sangat memudahkan deployment pada kasus-kasus tertentu. Sebagai contoh bundle file b.js diatas akan menghasilkan file JavaScript dengan kode seperti berikut:

C:\Users\E Q U A N\Desktop\_tmp>deno bundle b.js
Bundling file:///C:/Users/E%20Q%20U%20A%20N/Desktop/_tmp/b.js
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.

// This is a specialised implementation of a System module loader.

// @ts-nocheck
/* eslint-disable */
let System, __instantiateAsync, __instantiate;

(() => {
  const r = new Map();

  System = {
    register(id, d, f) {
      r.set(id, { d, f, exp: {} });
    },
  };

  async function dI(mid, src) {
    let id = mid.replace(/\.\w+$/i, "");
    if (id.includes("./")) {
      const [o, ...ia] = id.split("/").reverse(),
        [, ...sa] = src.split("/").reverse(),
        oa = [o];
      let s = 0,
        i;
      while ((i = ia.shift())) {
        if (i === "..") s++;
        else if (i === ".") break;
        else oa.push(i);
      }
      if (s < sa.length) oa.push(...sa.slice(s));
      id = oa.reverse().join("/");
    }
    return r.has(id) ? gExpA(id) : import(mid);
  }

  function gC(id, main) {
    return {
      id,
      import: (m) => dI(m, id),
      meta: { url: id, main },
    };
  }

  function gE(exp) {
    return (id, v) => {
      v = typeof id === "string" ? { [id]: v } : id;
      for (const [id, value] of Object.entries(v)) {
        Object.defineProperty(exp, id, {
          value,
          writable: true,
          enumerable: true,
        });
      }
    };
  }

  function rF(main) {
    for (const [id, m] of r.entries()) {
      const { f, exp } = m;
      const { execute: e, setters: s } = f(gE(exp), gC(id, id === main));
      delete m.f;
      m.e = e;
      m.s = s;
    }
  }

  async function gExpA(id) {
    if (!r.has(id)) return;
    const m = r.get(id);
    if (m.s) {
      const { d, e, s } = m;
      delete m.s;
      delete m.e;
      for (let i = 0; i < s.length; i++) s[i](await gExpA(d[i]));
      const r = e();
      if (r) await r;
    }
    return m.exp;
  }

  function gExp(id) {
    if (!r.has(id)) return;
    const m = r.get(id);
    if (m.s) {
      const { d, e, s } = m;
      delete m.s;
      delete m.e;
      for (let i = 0; i < s.length; i++) s[i](gExp(d[i]));
      e();
    }
    return m.exp;
  }

  __instantiateAsync = async (m) => {
    System = __instantiateAsync = __instantiate = undefined;
    rF(m);
    return gExpA(m);
  };

  __instantiate = (m) => {
    System = __instantiateAsync = __instantiate = undefined;
    rF(m);
    return gExp(m);
  };
})();

System.register(
  "https://blog.sajen.id/s/info",
  [],
  function (exports_1, context_1) {
    "use strict";
    var version;
    var __moduleName = context_1 && context_1.id;
    function info() {
      return `blog.sajen.id v${version}`;
    }
    exports_1("info", info);
    return {
      setters: [],
      execute: function () {
        version = "1.0.0-beta.3";
      },
    };
  },
);
System.register(
  "file:///C:/Users/E%20Q%20U%20A%20N/Desktop/_tmp/b",
  ["https://blog.sajen.id/s/info"],
  function (exports_2, context_2) {
    "use strict";
    var info_js_1;
    var __moduleName = context_2 && context_2.id;
    return {
      setters: [
        function (info_js_1_1) {
          info_js_1 = info_js_1_1;
        },
      ],
      execute: function () {
        console.log(info_js_1.info());
      },
    };
  },
);

__instantiate("file:///C:/Users/E%20Q%20U%20A%20N/Desktop/_tmp/b");

Kita bisa menyimpan kode JavaScript tersebut ke satu file

C:\Users\E Q U A N\Desktop\_tmp>deno bundle b.js > r.js

Kemudian file r.js dapat denngan mudah anda bagikan dan dijalankan dengan Deno

C:\Users\E Q U A N\Desktop\_tmp>deno run r.js
blog.sajen.id v1.0.0-beta.3

atau contoh lain yaitu anda bisa membagikan skrip server file tanpa harus mendownload deps, hanya diperlukan file Deno untuk menjalankannnya, sekali lagi sangat memudahkan dalam deployment skrip

C:\Users\E Q U A N\Desktop>deno bundle https://deno.land/std/http/file_server.ts > fs.js

Ukuran file fs.js yang dihasilkan sekitar 192kB kemudian anda bisa menaruh file tersebut bersama dengan binary Deno dan direktori tempat dimana anda akan membagikan berkas-berkas melalui file server.

Deno.exe
fs.js
files

Dokumentasi

doc

Deno juga memudahkan dalam pendokumentasian dari paket, dengan command doc anda bisa mengetahui dengan mudah fungsi-fungsi atau variabel apa saja yang di ekspor oleh suatu paket, sebagai contoh:

C:\Users\E Q U A N>deno doc https://blog.sajen.id/s/info.js
function info()

ya skrip pada info.js hanya menyediakan satu fungsi yaitu info().

info

Dengan command info maka Deno akan mendeteksi semua dependensi yang dipakai oleh suatu paket atau skrip

C:\Users\E Q U A N\Desktop\file-server>deno info https://deno.land/std/http/file_server.ts
local: C:\Users\E Q U A N\AppData\Local\deno\deps\https\deno.land\d8300752800fe3f0beda9505dc1c3b5388beb1ee45afd1f1e2c9fc0866df15cf
type: TypeScript
compiled: C:\Users\E Q U A N\AppData\Local\deno\gen\https\deno.land\std\http\file_server.ts.js
map: C:\Users\E Q U A N\AppData\Local\deno\gen\https\deno.land\std\http\file_server.ts.js.map
deps:
https://deno.land/std/http/file_server.ts
  ā”œā”€ā”¬ https://deno.land/std/path/mod.ts
  ā”‚ ā”œā”€ā”¬ https://deno.land/std/path/win32.ts
  ā”‚ ā”‚ ā”œā”€ā”€ https://deno.land/std/path/_constants.ts
  ā”‚ ā”‚ ā”œā”€ā”¬ https://deno.land/std/path/_util.ts
  ā”‚ ā”‚ ā”‚ ā””ā”€ā”€ https://deno.land/std/path/_constants.ts
  ā”‚ ā”‚ ā””ā”€ā”¬ https://deno.land/std/testing/asserts.ts
  ā”‚ ā”‚   ā”œā”€ā”€ https://deno.land/std/fmt/colors.ts
  ā”‚ ā”‚   ā””ā”€ā”€ https://deno.land/std/testing/diff.ts
  ā”‚ ā”œā”€ā”¬ https://deno.land/std/path/posix.ts
 ....

Sekuritas

Deno mengedepankan keamanan dalam memberikan akses-akses ke sumber daya seperti berkas, akses jaringan dll.

Berikut beberapa option yang bisa anda pakai dari dari Deno:

-A, --allow-all Mengijinkan semua. Flag ini akan men-disable semua keamanan.

--allow-env Mengijinkan akses env.

--allow-hrtime Allow high resolution time measurement. High resolution time can be used in timing attacks and fingerprinting.

--allow-net=\<allow-net> Mengijinkan akses jaringan. Domain bisa dipisahkan melalui tanda koma.

--allow-plugin Mengijinkan pemakain plugin.

--allow-read=\<allow-read> Mengijinkan akses baca berkas atau direktori, pisahkan dengan koma.

--allow-run Mengijinkan menjalankan subprocess. Catatan subprocess tidak berjalan di dalam level keamanan yg sama dengan Deno.

--allow-write=\<allow-write> Mengijinkan akses tulis berkas atau direktori, pisahkan dengan koma.

Kenapa?

Sebagaimana anda baca dalam release resmi blog dari pembuat Deno, dengan munculnya bahasa baru seperti Rust dan Go dimana sekarang anda bisa dengan mudah membangun aplikasi native maupun web melalui WebAssembly, ada kekhawatiran bahwa developer tidak akan menggunakan JavaScript sebagai bahasa utama lagi tetapi hanya untuk keperluan tertentu seperi aplikasi web saja tetapi peran JavaScript diluar web browser sebenarnya masih banyak terutama dalam lingkungan dimana diperlukan scripting yang cukup kompleks.

Deno dibuat tidak untuk menggantikan Node.js, malah Deno memberikan pilihan dan dibuat untuk memudahkan programer JavaScript dalam memakai JavaScript versi yang sudah sangat modern seperti sekarang ini dimana tidak dibutuhkan adanya transformasi ke ECMAScript ke versi yang lama dan nilai plus dari Deno menurut saya adalah dukungan langsung akan (bahasa) TypeScript.

Lalu mana yang akan anda pakai Node.js atau Deno?

Penggunaan teknologi sangatlah kontekstual dan dipengaruhi oleh banyak faktor. Node.js sudah berumur lebih dari 10 tahun sehingga sudah sangat mature sedangkan Deno masih berumur 2 tahun tetapi mendukung JavaScript modern dan TypeScript. Jadi kalau anda baru belajar TypeScript maka jangan ragu-ragu untuk memilih Deno sebagai runtime karena anda tidak lagi perlu memakai konfigurasi yg rumit atau menginstall tools tambahan untuk mengeksekusi TypeScript.

Happy Hacking!