Learn Javascript

Javascript Modules

How to use modules in the browser and node

slides | md

TO ADD

tl;dr

https://www.thedreaming.org/2017/04/28/es6-imports-babel/

Example - import leaflet in an .astro file

Leaflet uses ECMAScript modules

Benefits

  • Organization - Explicit dependency declaration includes version number
  • Better code - <script> type imports global scope, can cause issues with your and other code. Wheras module files are encapsulated
  • Performance - Import and ship only what you need import { thing1, thing2 } from 'package'.
  • Performance - Modules declare what they depend on (import) they can share dependencies and you aren't importing the same script (latency and pollution)
<!-- old old way - still works but -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
// "CommonJS" - old
const L = require('leaflet');
<script>
// ES6 Modules
import 'leaflet/dist/leaflet.css'
//   import * as L from 'leaflet'
// this version is better 
//   import L from 'leaflet'
import 'leaflet'
  </script>

About modules

In programming, modules are self-contained units of functionality that can be shared and reused across projects. They make our lives as developers easier, as we can use them to augment our applications with functionality that we haven’t had to write ourselves. They also allow us to organize and decouple our code, leading to applications that are easier to understand, debug and maintain.

The benefits of modularity

  • Modules are a way to split an application into separate files instead of having all of your application in one file.
  • This concept is also present in other languages with minor differences in syntax and behavior, like C's include, Python's import, and so on.
  • Modular design makes your application easy to understand, scale, and reuse.

NPM packages are modules

  • NPM is a package repository service that hosts published JS modules. npm install will download and install packages from the repository.
  • The npm cli puts all the downloaded modules in a node_modules directory where you ran npm install.

Modular design in Node

  • Node.js and NPM use the CommonJS (CJS) format, require and module.exports, to define dependencies and modules.
// module.js
var exports = module.exports = {};
exports.randomNumber = (max = 1) => {
	return Math.random() * max;
};

// index.js
const modEx = require('./module');
modEx.randomNumber(); // -> 0.927759

Modular design in Javascript (the old way)

Modular design in the browser is achieved by simply including multiple files with <script>. But there are drawbacks:

  • Each new script initiates a new HTTP request (and potential lantency)
  • Dependencies must be managed manually
  • Each script is in the global scope, requiring creative design patterns to prevent contamination.
<!-- index.html -->
<script src="lib1.js"></script>
<script src="lib2.js"></script>
<script src="core.js"></script>
<script>
console.log('inline code');
</script>

ES6 Modules + Node

  • As of ES6 (ES2015), JavaScript supports a native module format.
  • It uses the export keyword to export a module’s public API and an import keyword to import it.
// lib-module.js
const hello = "Hello, World!"; // "private" var
export const sayHello = () => hello;

// main.js
import { hello } from './lib-module.js';
console.log(hello()); // -> "Hello, World!"

Private vars

  • Each module has its own scope so that vars are not exposed unless the module intentionally uses exports (node) or export (ES6) to make them accessible. (see previous slide)

Modular design in the browser

  • Note that require(), module.exports and exports are APIs of a module system that is specific to Node.js.
  • While browsers do not implement this module system, similar benefits can be achieved with the Revealing Module Pattern.

Revealing Module Pattern

  • The Revealing Module Pattern is a JS design pattern in a web browser that mimics private and public access modifiers of other languages (e.g. C# or Java).
  • All functions and variables are hidden by default within the scope of an IIFE (immediately-invoked function expression), and exposed as needed.
  • See ./demos for examples

References

Presentation comments ...