JS Modules
class: center, middle .title[ Front-end training # Modules in JS ] --- # What? Small units of independent, reusable code --- # Why? Because! - Pollution of global scope - Name clashes and conflicts - Implicit dependencies, need to be loaded in correct order - No separation of concerns - Hard to maintain - Hard to expand - Hard to test --- # Too many type of modules... - Object literal notation - Module pattern - AMD - CommonJS - EcmaScript 6 Module --- # Object literal ``` js var myObjectLiteral = { variableKey: variableVAlue, functionKey: function (){...} }; ``` --- # Module Pattern ```js var counter = (function () { var counter = 0; return { increment: function () { return counter++; }, reset: function () { counter = 0; } }; })(); ``` --- # Tons of files! Writing modular code will generate lots of files and that’s actually ok! ``` html ... ... ``` But browser assumes you load files in right order :(  --- # Real modules! - Module format - Loader - Build tools - Ease of development and debugging --- # AMD Designed with browser environment in mind to allow/promote asynchronous loading ``` js // define(id?, dependencies?, factory); define (['config'], function (config){ var privateVar = config.counter; // expose public API return { increase: function () {...} } }); ``` Plugins for loading something other than js ```js // [Plugin Module ID] ! [resource ID] define (['text!../templ/start.html'], function (template) { // do something with loaded html }); ``` --- # CommonJS A community driven set of proposed best practices, specs and APIs, with a goal of building up the JS ecosystem across environments. - The scope is limited to the file - “free” variables `require, module, exports` ```js // math.js export.add = function () { var sum = 0, i = 0, args = arguments, l = args.length; while (i < l){ sum += args[i++]; } return sum; }; // another.js var math = require('math'); exports.increment = function(val){ return math.add(val, 1); }; ``` --- # AMD + CommonJS ? Simplified CommonJS wrapping ```js define (function (require, exports, module){ var math = require ('math'); exports.increment = function (val) { return math.add (val, 1); } }); ``` --- # EcmaScript 6 Module ```js import { load } from 'store/customer'; import when from 'when'; export default = function (id) { return when(id).then(load); }; ``` --- # Loaders Basic example ```js function loadJS(file) { // DOM: Create the script element var jsElm = document.createElement("script"); // set the type attribute jsElm.type = "application/javascript"; // set file path jsElm.src = file; // finally insert the element to the body element in order to load the script document.body.appendChild(jsElm); } ``` Popular AMD & CommonJS loaders: [RequireJS](http://requirejs.org) [curl.js](https://github.com/cujojs/curl) --- # Loaders/RequireJS ``` html ``` ```js require.config({ baseUrl: '/some/path', // The shim config allows us to configurate dependencies // for scripts that do not call define() to register a module shim: { underscore: { exports: '_' }, backbone: { deps: ['underscore', 'jquery'], exports: 'Backbone' } }, // Require.js allows us to configurate shortcut alias paths: { jquery: '../bower_components/jquery/jquery' } }); ``` --- # Build Tools Follows the dependency chain specified in the define() and require() calls, concatenates those into one or few files. Specify which top-level modules or resources are in each file and the build tool finds the rest. - [r.js (requirejs optimizer)](http://requirejs.org/docs/optimization.html) - [browserify](https://github.com/substack/node-browserify) - [webpack](https://webpack.js.org) --- # Build tools/Webpack ```js module.exports = { entry: './js/app.js', output: { filename: 'bundle.js' } }; ``` --- # Links .litle[ How to start: https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/ Mustread: http://addyosmani.com/writing-modular-js Specs: http://wiki.commonjs.org/wiki/Modules https://github.com/amdjs/amdjs-api/blob/master/AMD.md http://wiki.ecmascript.org/doku.php?id=harmony:modules Holywars: http://unscriptable.com/2011/09/30/amd-versus-cjs-whats-the-best-format - 2011 http://blog.millermedeiros.com/amd-is-better-for-the-web-than-commonjs-modules - 2011 http://derickbailey.com/2014/06/10/browserify-my-new-choice-for-modules-in-a-browser-backbone-app - 2014 Tools: http://webpack.js.org http://requirejs.org ~7.8k stars http://browserify.org ~7.9k stars https://github.com/cujojs/curl ~1.5k stars https://github.com/google/traceur-compiler https://github.com/ModuleLoader/es6-module-loader Practice: http://code.tutsplus.com/tutorials/a-requirejs-backbone-and-bower-starter-template--net-29211 http://javascriptplayground.com/blog/2014/06/es6-modules-today/ http://mikefowler.me/2014/06/11/backbone-with-es6/ http://tagtree.tv/ecmascript-6-episode-3 ]