Slide 1

Slide 1 text

JavaScript module systems @rafaelrinaldi

Slide 2

Slide 2 text

@rafaelrinaldi

Slide 3

Slide 3 text

http://netshoes.com.br

Slide 4

Slide 4 text

http://sp.femug.com

Slide 5

Slide 5 text

http://zofe.com.br

Slide 6

Slide 6 text

JavaScript is both very dynamic and multi-paradigm programming language

Slide 7

Slide 7 text

That’s both awesome and awkward

Slide 8

Slide 8 text

Awesome because • You can implement whatever programming paradigm you want; • Easy to learn. Just create a bunch of functions and rock on! • Easy to run. The only requirement is a browser.

Slide 9

Slide 9 text

Awkward because • It has lots of gotchas; • The browser environment itself is very complex and unpredictable; • The community is still evolving; there’s no “right way” of doing things; • “Toy language” legacy.

Slide 10

Slide 10 text

The language itself doesn’t provide features that are considered basic in other modern languages

Slide 11

Slide 11 text

Long story short

Slide 12

Slide 12 text

JavaScript don’t provide a native module system

Slide 13

Slide 13 text

# Ruby module system require 'format' module Log def warn(message) puts format.call(message) end end

Slide 14

Slide 14 text

# Python module system from helpers.string import format def warn(message): print format(message)

Slide 15

Slide 15 text

// Go module system package log import ( "helpers/string/format", "fmt" ) func warn() { fmt.Println(format("Of course I have a module system!")) }

Slide 16

Slide 16 text

Why does it matter?

Slide 17

Slide 17 text

A module system is a key requirement when it comes to code modularization

Slide 18

Slide 18 text

Multiple script tags

Slide 19

Slide 19 text

Slide 20

Slide 20 text

Multiple script tags • Somewhat sane code organization; • Multiple file requests; • Relies on the order that scripts are defined; • Zero control over global name collision.

Slide 21

Slide 21 text

Module Pattern (and its variants)

Slide 22

Slide 22 text

AJAX came out and we started to write more JavaScript

Slide 23

Slide 23 text

Scripts → Applications

Slide 24

Slide 24 text

Larger applications demand a good code architecture

Slide 25

Slide 25 text

var Module = (function () { // "private" var myPrivateVariable, myPrivateMethod; myPrivateVariable = 'foo'; myPrivateMethod = function() {} // "public" return { myPublicVariable: 'bar', myPublicMethod: function () {} }; })();

Slide 26

Slide 26 text

Module Pattern • Provide a nice way of organizing modules and exposing their APIs; • Still doesn’t solve dependency organization nor dependency loading.

Slide 27

Slide 27 text

CommonJS

Slide 28

Slide 28 text

HTML5 and Node.js came out and all of sudden everything is being written in JavaScript

Slide 29

Slide 29 text

CommonJS is a community effort to define best practices with a goal of compatibility across multiple environments

Slide 30

Slide 30 text

Later adopted as the default module system for Node.js

Slide 31

Slide 31 text

// No `define()`, the file itself is a closure // Nice way to `require()` dependencies var log = require('debug/log'); var toArray = require('helpers/toArray'); var parseJSON = require('serialization/json').parse; function lorem() { log('I am a CommonJS module!'); } // Expose the public API exports.lorem = lorem; /* To use this module we've created, simple `require()` it: */ var Module = require('module'); // Calling a public method Module.lorem(); // I am a CommonJS module!

Slide 32

Slide 32 text

CommonJS • The beauty of CommonJS is its simplicity; • Perfect for server side JS; • Synchronous nature, doesn’t know nothing about the browser; • Browserify kinda solves that by compiling modules to vanilla JS.

Slide 33

Slide 33 text

AMD

Slide 34

Slide 34 text

AMD stands for Asynchronous Module Definition

Slide 35

Slide 35 text

It was born as a set of changes to the CommonJS spec

Slide 36

Slide 36 text

It’s a mechanism for defining modules and its dependencies in an asynchronous way

Slide 37

Slide 37 text

The browser is asynchronous by nature, AMD was made to play well with it

Slide 38

Slide 38 text

// Define a new module, the file name will be set as the id define( // Module dependencies ['debug/log', 'helpers/toArray', 'serialization/json/parse'], // Module implementation function(log, toArray, parseJSON) { function lorem() { log('I am an AMD module!'); } return { lorem: lorem } } );

Slide 39

Slide 39 text

/* To use this module we've created, simply define it as a dependency and use it: */ // Creating a new module that uses our previously created module define(['module'], function(Module) { console.log(Module.lorem()); // I am an AMD module! });

Slide 40

Slide 40 text

AMD • The syntax looks a bit weird at first glance (but you get used to it) • You can use whatever patterns and paradigms you want, AMD will just give you a sane module system to work with; • Easy way to spot module dependencies; • All dependencies are ready to be used on module implementation.

Slide 41

Slide 41 text

Module Loaders

Slide 42

Slide 42 text

Since AMD is just an API, you must use what’s called a module loader

Slide 43

Slide 43 text

The most popular module loader for AMD is by far RequireJS (but there are others)

Slide 44

Slide 44 text

RequireJS is also Node.js friendly

Slide 45

Slide 45 text

require.config({ // Base path for all the modules loaded baseUrl: 'assets/js', paths: { // Path aliases are awesome 'foo': 'lib/lorem/ipsum/dolor/foo', // Super easy to implement things like cache busting 'bar/baz': 'bar/baz_v0.3.2' } });

Slide 46

Slide 46 text

Goodies

Slide 47

Slide 47 text

RequireJS offers support for plugins

Slide 48

Slide 48 text

define( // Plugins always end with a bang `!` ['text!./tmplt/sliderTemplate.mustache', 'image!./img/doge.png'], function(sliderTemplate, doge) { var template = sliderTemplate; document.body.appendChild(doge); } );

Slide 49

Slide 49 text

Lazy loading support

Slide 50

Slide 50 text

define(['require'], function(require) { // List of files to be lazy loaded var files = ['vendors/analytics', 'vendors/ab_test']; // Calling it directly just so you can get the idea // But you could wait for a user interaction, for example require(files, function(analytics, ab_test) { analytics.initialize(); ab_test.initialize(); }); });

Slide 51

Slide 51 text

AMD Goodies • No build step required; • Offers an optimisation tool called r.js that makes it really easy to generate file wrappers/bundles for production.

Slide 52

Slide 52 text

Harmony modules

Slide 53

Slide 53 text

Harmony is the code-name for the 6th version of ECMAScript (ES6)

Slide 54

Slide 54 text

Lots of features were added, including a native module system!

Slide 55

Slide 55 text

// Regular import import 'file' from 'io/file'; // Import wildcard import * as helpers from 'helpers'; // Named imports import {sha2, md5} from 'crypto'; // Export a function export function warn(message) { console.warn(message); } // Export a constant export const pi = 3.14; // Default exports export default function() { console.log('I am the default module method!'); }

Slide 56

Slide 56 text

// Native support for classes as well import MyClass from 'MyClass'; let instance = new MyClass();

Slide 57

Slide 57 text

Harmony modules • The way that ES6 loads and evaluates code is very similar to AMD’s approach; • ES6 final spec is already being implemented but it’s going to take some time to be well spread across all environments; • In the meantime you can start playing with it using a transpiler such as babel (previously called 6to5) or Traceur from Google; • Doesn’t really fit into production yet because it relies on a large vendor library and even a runtime to work properly.

Slide 58

Slide 58 text

TL;DR

Slide 59

Slide 59 text

What should I use then?

Slide 60

Slide 60 text

There’s no right answer (LOL sorry)

Slide 61

Slide 61 text

If you’re writing server side JavaScript, go with CommonJS

Slide 62

Slide 62 text

If you’re writing code for the browser, AMD can be your best friend

Slide 63

Slide 63 text

Things are still evolving, ES6 is already happening and HTTP2 is coming to help us on that as well

Slide 64

Slide 64 text

@rafaelrinaldi Thanks