Module
Pertama mari kita belajar apa itu Module. Ketika javascript pertama kali diperkenalkan, javascript memiliki sistem yang sangat mendasar untuk memuat "module". Dengan cara menempatkan tag script dalam file html dan menentukan lokasi file javascript yang akan di-load kedalam website. Mekanisme ini kurang baik, bahkan untuk project kecil karena beberapa alasan:
- Karena semua diload dalam konteks global yang memicu tabrakan nama (name collisions) dan penimpaan (overrides).
- Banyak pekerjaan manual bagi developer untuk mengetahui dependensi dan urutan module yang diload.
Permasalahan tersebut diperburuk ketika aplikasi pada sisi client (browser) berkembang lebih besar dan lebih besar lagi sampai menjadi project yang kompleks. Untuk menyelesaikan masalah module ini, komunitas javascript mulai memperkenalkan solusinya sekitar tahun 2009 sebagai CommonJS (CJS) dan Asynchronous Module Definition (AMD).
CommonJS mendefinisikan prosess memuat modul secara Synchronous (berurutan) di lingkunagan server. NodeJS, sebagian besar, mengadopsi prosess memuat module ini dan mengimplementasikannya. Selain itu, Browserify
adalah salah satu alat pertama yang memungkinkan proses memuat module mirip CommonJS di browser. AMD mendefinisikan proses memuat module secara Asyncrhonous (tidak berutuan) yang berfokus pada memuat module di browser. Tool yang paling terkenal yang mengimplementasikannya adalah RequireJS
.
Ada juga cara definisi lain yang disebut. Universal Module Definition (UMD) pada dasarnya adalah sebuah function wrapper yang memungkinkan suatu module bisa dipkai oleh banyak module loader contohnya AMD dan CommonJS diatas. Hal bagus tentang UMD adalah kamu bisa memuatnya sebagai AMD, atau CJS, atau secara global melalui window
object. Namun, itu semua bergantung pada environment apa yang memuatnya. UMD biasanya digunakan untuk library kecil yang sering digunakan kembali (resuable).
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports', 'b'], factory);
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// CommonJS
factory(exports, require('b'));
} else {
// Browser globals
factory((root.commonJsStrict = {}), root.b);
}
}(this, function (exports, b) {
//use b in some fashion.
// attach properties to the exports object to define
// the exported module properties.
exports.action = function () {};
}));
Setelahnya, pada tahun 2015. Sistem module native akhirnya diperkenalkan dalam spesifikasi ECMAScript
. Definisi module ini umumnya dikenal sebagai ES Module atau ES6 Module Definition. Ini mendefinisikan semantik untuk mengimport dan mengexport module secara asynchronous.
Contoh pendefinisian module di javascript
ES6 Module
Ciri khusus untuk penulisan module dalam standart ECMAScript 6 (ES6) adalah adanya sintax import
dan export
. Sesuai namanya import
digunakan untuk meng-import module ke dalam kode base, sedangkan export
digunakan untuk meng-export function atau varible yang nantinya menjadi sebuah module yang dapat digunakan berulang di kode base (reuseable) atau module lain menjadi sebuah dependency (berkaitan).
values.js
// (1)
export function isNumber(data) {
return (typeof data === "number);
}
number.js
import {isNumber} from './values.js' // (2)
// (3)
export function add(a, b) {
if(isNumber(a) && isNumber(b)) {
return a + b;
}
return NaN;
}
Contoh diatas adalah script module sederhana yang dimaksudkan untuk menjumlahkan dua parameter di method add
.
- file
values.js
meng-export methodisNumber
yang dimaksudkan untuk memastikan apakah variabledata
bertipe data number. Dengan menambahkanexport
didepan syntax function akan secara otomatis functionisNumber
akan diexpose sebagai module agar dapat di pakai ketika di import di kode base atau module lain. - file
number.js
meng-import module yang sudah dibuat sebelumnya yaituvalues.js
menggunakan syntaximport
. Namun apa itu{ isNumber }
? , dalam ES6 penulisan ini disebut Destructuring assignment yang memungkinkan kita mengurai nilai dari sebuah Object dan Array kedalam variable yang berbeda. - file
number.js
juga meng-export sebuah method yang berfungsi untuk menjumlahkan parametera
danb
dengan memanfaatkan method di modulevalues.js
yaituisNumber
, yang mengkonfirmasi bahwa parameter yang dilempar bertipe datanumber
.
Dari contoh diatas kita tau bahwa Module ini saling berkaitan (dependency). module number.js
membutuhkan method pada module values.js
yang tidak menuntut kemungkinan bahwa module lain juga akan membutuhkan kedua module ini (reuseable).
CommonJS Module
const number = require('./values.js')
module.exports = {
add: function(a, b) {
if (number.isNumber(a) && number.isNumber(b)) {
return a + b;
}
return NaN;
}
}
Module: Support Browser
Penggunaan ES6 Module pada Javascript secara native bisa dilakukkan pada browser yang support dengan syntax import
dan export
, kompatibilitas browser ini menyesuikan versi dan browser apa yang didukung. Berikut adalah daftar rincian kompatibilitas browser menurut situs developer.mozilla.org
Import
Import Native ES6 Module - developer.mozilla.org
Export
Export Native ES6 Module - developer.mozilla.org
Bundler
Introduction
Seperti namanya, Bundler adalah cara dimana item-item yang terpecah digabung/dibundel menjadi satu buat item. Dalam dunia Web Development, Javascript Bundler berarti sebuah tools yang bertugas untuk membundel semua module javascript menjadi satu file javascript yang bisa dieksekusi oleh browser.
Module Bundler - dev.to
Kenapa kita butuh Bundler
Untuk memudahkan memahami apa itu javascript bundle maka kita telaah kembali kenapa ia diciptakan. Javascript Module memang keren, ia mengatasi permasalah dependency dan name collision. Namun ada permasalahan lagi, yaitu ketika kita sudah mempunyai project yang kompleks dan berskala besar, maka kita akan dihadapi dengan banyaknya module yang terpecah dan browser akan meng-import/memanggil satu per-satu file module tersebut.
<html>
<script src="/src/foo.js"></script>
<script src="/src/bar.js"></script>
<script src="/src/baz.js"></script>
<script src="/src/qux.js"></script>
<script src="/src/quux.js"></script>
</html>
Jika kita jeli untuk melihat performa web kita maka pemanggilan resource yang banyak akan membuat loading website kita terasa lamban dan bandwidth yang dipakai juga semakin banyak. Dan yang paling penting adalah waktu untuk website dimuat secara sempurna oleh browser akan sangat lama hanya karena resourse yang dibutuhkan banyak.
Karena setiap file yang diminta memerlukan HTTP Request terpisah. Sekarang kalau kita memerlukan 5 file javascript untuk digunakan pada website kita kenapa kita tidak gabung saja file tersebut menjadi satu file yang hanya memerlukan satu HTTP Request.
<html>
<script src="/dist/bundle.js"></script>
</html>
FYI: Sekarang protocol HTTP/2 mengatasi permasalah ini dengan adanya fitur bernama Server Push.
Alasan pendukung lain
- Browser tidak mendukung sistem modul, meskipun ini tidak sepenuhnya benar saat ini karena kebanyakan browser modern sudah support.
- Bundler membantu kita mengelola dependency relationship, secara otomatis bundler akan mengurutkan sendiri urutan pemanggilan module sesuai dengan relasi/hubungan antar module.
- Bundle juga membantu kita untuk memuat asset/resources dalam urutan pemanggilan yang sesuai dengan kegunaannya. Asset ini tidak hanya file javascript, bundler juga mengatur pemanggilan asset stylesheet (css), gambar, dan lain sebagainya.
Javascript Bundler Tool
Ada banyak macam-macam bundler tool, tapi yang sering dipakai oleh para Javascript Developer menurut survey State of Javascript 2019 adalah:
- Webpack - webpack.js.org
- Gulp - gulpjs.com
- Parcel - parceljs.org
- Rollup - rollupjs.org
- Browserify - browserify.org
- Fusebox - fuse-box.org
Yang dilakukkan Bundler Tool
Bundler tidak hanya membuat segalanya menjadi satu dan dipanggil secara urut, tidak. Budler memiliki tugas yang sangat penting dalam prosess pembuatan website.
Working scheme of a web bundler
Ada tiga hal yang dilakukkan oleh Bundler tool ini, yaitu:
- Collection
- Transformation
- Optimization
Sementara bundler mendeteksi dan mengumpulkan assets yang ada pada project, bundler juga akan menganalisa bagaimana module-module itu didefinisikan, bagaimana mereka ber-relasi, apakah file asset memerlukan transformasi (seperti Typescript, Sass, Stylus, atau Pug), dan bagaimana file tersebut diload kedalam file HTML. Pada fase Transformasi segala informasi tersebut di prosess dan dimanipulasi sesuai dengan konfigurasi file yang didefinisikan, contohnya file Typescript di compile sehingga menjadi file Javascript dan file Sass (.scss) di compile menjadi file CSS. Dan akhirnya fase Optimasi dilakukkan untuk meng-optimasi file asset seperti javascript, css, dan bahkan gambar juga (dikonfigurasi terlebih dahulu).
Sekian terima kasih, sampai jumpa di artikel selanjutnya ;)