SlideShare a Scribd company logo
Unbundling the JavaScript module bundlerUnbundling the JavaScript module bundler
Luciano Mammino (Luciano Mammino ( ))@loige@loige
DublinJS  03/07/2018
loige.link/bundle-dublinjs
1
loige.link/bundle-dublinjs 2
Webpack == PAIN!?Webpack == PAIN!?
twitter.com/search?q=webpack%20pain
@loige 3
@loige 4
@loige 5
@loige 6
@loige
❤
7
@loige 8
@loige 9
@loige 10
It's not Webpack!It's not Webpack!
Module bundling is actually complicated!Module bundling is actually complicated!
@loige 11
Luciano... whoLuciano... who
Find me online:
-  (@loige)
-  (lmammino)
-
-  (loige.co)
Twitter
GitHub
Linkedin
Blog
Solution Architect at
with @mariocasciaro
with @andreaman87
with @Podgeypoos79
12
1. Why we need modules
2. JavaScript module systems
3. How a module bundler works
4. Webpack in 2 minutes!
5. Advanced module bundling
AgendaAgenda
@loige 13
http://poo.loige.co
@loige 14
App featuresApp features
@loige 15
Dynamic DOM manipulation
React, Angular, Vue
are so... overrated!
@loige 16
Dynamic Favicon
favico.js@loige 17
Custom animated tooltips
tippy.js@loige 18
Confetti rainfall
dom-confetti@loige 19
Persist state through Local Storage + UUIDs
 +store2 uuidjs@loige 20
@loige 21
@loige 21
7 Requests only for the JS code!
@loige 21
Current scenarioCurrent scenario
zepto@1.2.0/dist/zepto.min.js 
uuidjs@4.0.3/dist/uuid.core.js 
store2@2.7.0/dist/store2.min.js 
 tippy.js@2.2.3/dist/tippy.all.min.js 
confetti@0.0.10/lib/main.js 
 favico.js@0.3.10/favico­0.3.10.min.js
@loige 22
Ideal scenarioIdeal scenario
zepto@1.2.0/dist/zepto.min.js 
uuidjs@4.0.3/dist/uuid.core.js 
store2@2.7.0/dist/store2.min.js 
 tippy.js@2.2.3/dist/tippy.all.min.js 
confetti@0.0.10/lib/main.js 
 favico.js@0.3.10/favico­0.3.10.min.js
vendors.js
+ 
+ 
+ 
+ 
+ 
=
@loige 23
How to do this?How to do this?
@loige 24
./buildVendors.sh > vendors.js
buildVendors.sh
$
@loige 25
npx lumpy build$
github.com/lmammino/lumpy
@loige 26 . 1
# lumpy.txt 
https://unpkg.com/zepto@1.2.0/dist/zepto.min.js 
https://unpkg.com/uuidjs@4.0.3/dist/uuid.core.js 
https://unpkg.com/store2@2.7.0/dist/store2.min.js 
https://unpkg.com/tippy.js@2.2.3/dist/tippy.all.min.js 
https://unpkg.com/confetti­js@0.0.11/dist/index.min.js 
https://unpkg.com/dom­confetti@0.0.10/lib/main.js 
https://unpkg.com/favico.js@0.3.10/favico­0.3.10.min.js
Lumpy allows you to define
all the vendors in a text file
@loige 26 . 2
lumpy build$
1. Downloads the files from lumpy.txt (and caches them)
2. Concatenates the content of the files
3. Minifies the resulting source code (using )
4. Saves the resulting content in vendors.js
babel-minify
@loige 26 . 3
7 requests
2 requests
@loige 27
7 requests
2 requests
@loige
Even better if you "minify" these!
27
ConcatenationConcatenation
++
MinificationMinification
@loige 28
This is good...This is good...
@loige 29
This is good...This is good...
@loige 29
This is good...This is good...
... in 2008... in 2008
waswas
@loige 29
Today...Today...
We can do better!We can do better!
@loige 30
Updating dependencies should be easyUpdating dependencies should be easy
We don't want to worry about dependencies ofWe don't want to worry about dependencies of
dependenciesdependencies
We don't have to worry about the order of importsWe don't have to worry about the order of imports
Today...Today...
@loige 31
DependencyDependency
(or coupling)
a state in which one object uses a function of
another object
— Wikipedia
@loige 32
Reusable dependencies...Reusable dependencies...
Modules!Modules!
@loige 33
ModulesModules
The bricks for structuring non-trivial applications,
but also the main mechanism to enforce information
hiding by keeping private all the functions and
variables that are not explicitly marked to be
exported
— *Node.js Design Patterns (Second Edition)
* yeah, I quite like quoting my stuff...
@loige 34
1. Why we need modules
2. JavaScript module systems
3. How a module bundler works
4. Webpack in 2 minutes!
5. Advanced module bundling
AgendaAgenda
@loige 35
Meet my friendMeet my friend I.I.F.E.I.I.F.E.
(Immediately Invoked Function Expression)
loige.link/iife
@loige 36
We generally define a function this wayWe generally define a function this way
@loige 37
We generally define a function this wayWe generally define a function this way
const sum = (a, b) => a + b
@loige 37
We generally define a function this wayWe generally define a function this way
const sum = (a, b) => a + b
oror
@loige 37
We generally define a function this wayWe generally define a function this way
const sum = (a, b) => a + b
sum(a, b) {
return a + b
}
oror
@loige 37
We generally define a function this wayWe generally define a function this way
const sum = (a, b) => a + b
sum(a, b) {
return a + b
}
oror
then, at some point, we execute it...then, at some point, we execute it...
@loige 37
We generally define a function this wayWe generally define a function this way
const sum = (a, b) => a + b
sum(a, b) {
return a + b
}
oror
then, at some point, we execute it...then, at some point, we execute it...
const four = sum(2, 2)
@loige 37
A function in JS creates an isolated scopeA function in JS creates an isolated scope
@loige 38
A function in JS creates an isolated scopeA function in JS creates an isolated scope
(a, b) => {
const secretString = "Hello"
return a + b
}
console.log(secretString) // undefined
@loige 38
A function in JS creates an isolated scopeA function in JS creates an isolated scope
(a, b) => {
const secretString = "Hello"
return a + b
}
console.log(secretString) // undefined
secretStringsecretString is not visible outside the functionis not visible outside the function
@loige 38
IIFE allows you to define an isolated scopeIIFE allows you to define an isolated scope
that executes itselfthat executes itself
(arg1, arg2) => {
// do stuff here
const iAmNotVisibleOutside = true
}
@loige 39
IIFE allows you to define an isolated scopeIIFE allows you to define an isolated scope
that executes itselfthat executes itself
(arg1, arg2) => {
// do stuff here
const iAmNotVisibleOutside = true
}
A function with its own scope
@loige 39
)(someArg1, someArg2)
IIFE allows you to define an isolated scopeIIFE allows you to define an isolated scope
that executes itselfthat executes itself
(arg1, arg2) => {
// do stuff here
const iAmNotVisibleOutside = true
}
(
@loige 39
)(someArg1, someArg2)
IIFE allows you to define an isolated scopeIIFE allows you to define an isolated scope
that executes itselfthat executes itself
(arg1, arg2) => {
// do stuff here
const iAmNotVisibleOutside = true
}
(
This wrapper executes the function immediately and passes arguments from the
outer scope
@loige 39
IIFE is a recurring pattern inIIFE is a recurring pattern in
JavaScript modulesJavaScript modules
@loige 40
Let's implement a moduleLet's implement a module
that provides:that provides:
 
Information hidingInformation hiding
exported functionalitiesexported functionalities
@loige 41
const myModule = (() => {
const privateFoo = () => { /* ... */ }
const privateBar = [ /* ... */ ]
const exported = {
publicFoo: () => { /* ... */ },
publicBar: [ /* ... */ ]
};
return exported
})()
myModule.publicFoo()
myModule.publicBar[0]
myModule.privateFoo // undefined
myModule.privateBar // undefined
privateFoo // undefined
privateBar // undefined @loige42
const myModule = (() => {
const privateFoo = () => { /* ... */ }
const privateBar = [ /* ... */ ]
const exported = {
publicFoo: () => { /* ... */ },
publicBar: [ /* ... */ ]
};
return exported
})() A module
myModule.publicFoo()
myModule.publicBar[0]
myModule.privateFoo // undefined
myModule.privateBar // undefined
privateFoo // undefined
privateBar // undefined @loige42
const myModule = (() => {
const privateFoo = () => { /* ... */ }
const privateBar = [ /* ... */ ]
const exported = {
publicFoo: () => { /* ... */ },
publicBar: [ /* ... */ ]
};
return exported
})() A module
myModule.publicFoo()
myModule.publicBar[0]
myModule.privateFoo // undefined
myModule.privateBar // undefined
privateFoo // undefined
privateBar // undefined
IIFE
Creates an isolated scope
and executes it
@loige42
const myModule = (() => {
const privateFoo = () => { /* ... */ }
const privateBar = [ /* ... */ ]
const exported = {
publicFoo: () => { /* ... */ },
publicBar: [ /* ... */ ]
};
return exported
})() A module
myModule.publicFoo()
myModule.publicBar[0]
myModule.privateFoo // undefined
myModule.privateBar // undefined
privateFoo // undefined
privateBar // undefined
information hiding
non-exposed functionality
@loige42
const myModule = (() => {
const privateFoo = () => { /* ... */ }
const privateBar = [ /* ... */ ]
const exported = {
publicFoo: () => { /* ... */ },
publicBar: [ /* ... */ ]
};
return exported
})() A module
myModule.publicFoo()
myModule.publicBar[0]
myModule.privateFoo // undefined
myModule.privateBar // undefined
privateFoo // undefined
privateBar // undefined
defines exported
functionalities
@loige42
const myModule = (() => {
const privateFoo = () => { /* ... */ }
const privateBar = [ /* ... */ ]
const exported = {
publicFoo: () => { /* ... */ },
publicBar: [ /* ... */ ]
};
return exported
})() A module
myModule.publicFoo()
myModule.publicBar[0]
myModule.privateFoo // undefined
myModule.privateBar // undefined
privateFoo // undefined
privateBar // undefined
propagates the exports
to the outer scope (assigning it to myModule)
@loige42
const myModule = (() => {
const privateFoo = () => { /* ... */ }
const privateBar = [ /* ... */ ]
const exported = {
publicFoo: () => { /* ... */ },
publicBar: [ /* ... */ ]
};
return exported
})() A module
myModule.publicFoo()
myModule.publicBar[0]
myModule.privateFoo // undefined
myModule.privateBar // undefined
privateFoo // undefined
privateBar // undefined
Can access exported
functionalities
@loige42
const myModule = (() => {
const privateFoo = () => { /* ... */ }
const privateBar = [ /* ... */ ]
const exported = {
publicFoo: () => { /* ... */ },
publicBar: [ /* ... */ ]
};
return exported
})() A module
myModule.publicFoo()
myModule.publicBar[0]
myModule.privateFoo // undefined
myModule.privateBar // undefined
privateFoo // undefined
privateBar // undefined
No visibility for the
non-exported ones
@loige42
We want modules to beWe want modules to be
  reusablereusable across different apps andacross different apps and
organisations...organisations...
...we need...we need
AA STANDARD MODULESTANDARD MODULE format!format!@loige 43
Module system featuresModule system features
Must have
Simple syntax for import / export
Information hiding
Allows to define modules in separate files
Modules can import from other modules
(nested dependencies)
@loige 44
Module system featuresModule system features
Nice to have
Ability to import module subsets
Avoid naming collision
Asynchronous module loading
Seamless support for Browsers & Server-side
@loige 45
xkcd.com/927
@loige 46
JavaScript module systemsJavaScript module systems
globals
CommonJS (Node.js)
AMD (Require.js / Dojo)
UMD
ES2015 Modules (ESM)
Many others (SystemJS, ...)
@loige 47
GlobalsGlobals
var $, jQuery
$ = jQuery = (() => {
return { /* ... */ }
})()
// ... use $ or jQuery in the global scope
$.find('.button').remove()
@loige 48
GlobalsGlobals
Might generate naming collisions
(e.g. $ overrides browser global variable)
 
Modules needs to be "fully loaded" in the right order
 
Cannot import parts of modules
@loige 49
// or import single functionality
const { concat } = require('./loDash')
concat([1], [2], [3])
// app.js
// import full module
const _ = require('./loDash')
_.concat([1], [2], [3])
// loDash.js
const loDash = {
/* ... */
}
module.exports = loDash
CommonJSCommonJS
@loige 50
// or import single functionality
const { concat } = require('./loDash')
concat([1], [2], [3])
// app.js
// import full module
const _ = require('./loDash')
_.concat([1], [2], [3])
// loDash.js
const loDash = {
/* ... */
}
module.exports = loDash
CommonJSCommonJS
module
@loige 50
// or import single functionality
const { concat } = require('./loDash')
concat([1], [2], [3])
// app.js
// import full module
const _ = require('./loDash')
_.concat([1], [2], [3])
// loDash.js
const loDash = {
/* ... */
}
module.exports = loDash
CommonJSCommonJS
module
app using module
@loige 50
// or import single functionality
const { concat } = require('./loDash')
concat([1], [2], [3])
// app.js
// import full module
const _ = require('./loDash')
_.concat([1], [2], [3])
// loDash.js
const loDash = {
/* ... */
}
module.exports = loDash
CommonJSCommonJS
module
app using module
@loige 50
// or import single functionality
const { concat } = require('./loDash')
concat([1], [2], [3])
// app.js
// import full module
const _ = require('./loDash')
_.concat([1], [2], [3])
// loDash.js
const loDash = {
/* ... */
}
module.exports = loDash
CommonJSCommonJS
module
app using module
@loige 50
CommonJSCommonJS
No naming collisions
(imported modules can be renamed)
Huge repository of modules through
 
Synchronous import only
Works natively on the server side only (Node.js)
NPM
@loige 51
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// jquery-1.9.0.js
define(
'jquery',
['sizzle', 'jqueryUI'],
function (sizzle, jqueryUI) {
// Returns the exported value
return function () {
// ...
}
}
)
@loige 52
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// jquery-1.9.0.js
define(
'jquery',
['sizzle', 'jqueryUI'],
function (sizzle, jqueryUI) {
// Returns the exported value
return function () {
// ...
}
}
)
module
@loige 52
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// jquery-1.9.0.js
define(
'jquery',
['sizzle', 'jqueryUI'],
function (sizzle, jqueryUI) {
// Returns the exported value
return function () {
// ...
}
}
)
module
module name
@loige 52
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// jquery-1.9.0.js
define(
'jquery',
['sizzle', 'jqueryUI'],
function (sizzle, jqueryUI) {
// Returns the exported value
return function () {
// ...
}
}
)
module
dependencies
@loige 52
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// jquery-1.9.0.js
define(
'jquery',
['sizzle', 'jqueryUI'],
function (sizzle, jqueryUI) {
// Returns the exported value
return function () {
// ...
}
}
)
module
factory function used to construct the
module,
receives the dependencies as arguments
@loige 52
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// jquery-1.9.0.js
define(
'jquery',
['sizzle', 'jqueryUI'],
function (sizzle, jqueryUI) {
// Returns the exported value
return function () {
// ...
}
}
)
module
exported value
@loige 52
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// app.js
// define paths
requirejs.config({
baseUrl: 'js/lib',
paths: {
jquery: 'jquery-1.9.0'
}
})
define(['jquery'], function ($) {
// this is executed only when jquery
// and its deps are loaded
});
@loige 53
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// app.js
// define paths
requirejs.config({
baseUrl: 'js/lib',
paths: {
jquery: 'jquery-1.9.0'
}
})
define(['jquery'], function ($) {
// this is executed only when jquery
// and its deps are loaded
}); app
@loige 53
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// app.js
// define paths
requirejs.config({
baseUrl: 'js/lib',
paths: {
jquery: 'jquery-1.9.0'
}
})
define(['jquery'], function ($) {
// this is executed only when jquery
// and its deps are loaded
}); app
Require.js config
jquery will be loaded from
://<currentDomain>/js/lib/jquery-1.9.0.js
@loige 53
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
// app.js
// define paths
requirejs.config({
baseUrl: 'js/lib',
paths: {
jquery: 'jquery-1.9.0'
}
})
define(['jquery'], function ($) {
// this is executed only when jquery
// and its deps are loaded
}); app
app main function
Has jquery as dependency
@loige 53
AMD (AMD ( ))
Asynchronous Module DefinitionAsynchronous Module Definition
Require.jsRequire.js
Asynchronous modules
Works on Browsers and Server side
 
Very verbose and convoluted syntax (my opinion™)
@loige 54
UMDUMD
Universal Module DefinitionUniversal Module Definition
A module definition that is compatible with
Global modules, CommonJS & AMD
 
 github.com/umdjs/umd
@loige 55 . 1
(function (root, factory) {
if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('dep'))
} else if (typeof define === 'function' && define.amd) {
// AMD
define(['dep'], function (dep) {
return (root.returnExportsGlobal = factory(dep))
})
} else {
// Global Variables
root.myModule = factory(root.dep)
}
}(this, function (dep) {
// Your actual module
return {}
}))
loige.link/umd@loige 55 . 2
(function (root, factory) {
if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('dep'))
} else if (typeof define === 'function' && define.amd) {
// AMD
define(['dep'], function (dep) {
return (root.returnExportsGlobal = factory(dep))
})
} else {
// Global Variables
root.myModule = factory(root.dep)
}
}(this, function (dep) {
// Your actual module
return {}
}))
loige.link/umd
IIFE with arguments:
 - Current scope (this) and the module
factory function.
 - "dep" is a sample dependency of the
module.
@loige 55 . 2
(function (root, factory) {
if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('dep'))
} else if (typeof define === 'function' && define.amd) {
// AMD
define(['dep'], function (dep) {
return (root.returnExportsGlobal = factory(dep))
})
} else {
// Global Variables
root.myModule = factory(root.dep)
}
}(this, function (dep) {
// Your actual module
return {}
}))
loige.link/umd@loige 55 . 2
(function (root, factory) {
if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('dep'))
} else if (typeof define === 'function' && define.amd) {
// AMD
define(['dep'], function (dep) {
return (root.returnExportsGlobal = factory(dep))
})
} else {
// Global Variables
root.myModule = factory(root.dep)
}
}(this, function (dep) {
// Your actual module
return {}
}))
loige.link/umd@loige 55 . 2
(function (root, factory) {
if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('dep'))
} else if (typeof define === 'function' && define.amd) {
// AMD
define(['dep'], function (dep) {
return (root.returnExportsGlobal = factory(dep))
})
} else {
// Global Variables
root.myModule = factory(root.dep)
}
}(this, function (dep) {
// Your actual module
return {}
}))
loige.link/umd@loige 55 . 2
Allows you to define modules that
can be used by almost any module loader
 
Complex, the wrapper code
is almost impossible to write manually
UMDUMD
Universal Module DefinitionUniversal Module Definition
@loige 55 . 3
ES2015 modulesES2015 modules
Cool & broad subject, it would deserve it's own talk
Wanna know more?
/  syntax referenceimport export
ECMAScript modules in browsers
ES modules: A cartoon deep-dive
ES Modules in Node Today!
@loige 56 . 1
// calculator.js
const add = (num1, num2) => num1 + num2
const sub = (num1, num2) => num1 - num2
const div = (num1, num2) => num1 / num2
const mul = (num1, num2) => num1 * num2
export { add, sub, div, mul }
// app.js
import { add } from './calculator'
console.log(add(2,2)) // 4
ES2015 modulesES2015 modules
@loige 56 . 2
// calculator.js
const add = (num1, num2) => num1 + num2
const sub = (num1, num2) => num1 - num2
const div = (num1, num2) => num1 / num2
const mul = (num1, num2) => num1 * num2
export { add, sub, div, mul }
// app.js
import { add } from './calculator'
console.log(add(2,2)) // 4
ES2015 modulesES2015 modules
module
@loige 56 . 2
// calculator.js
const add = (num1, num2) => num1 + num2
const sub = (num1, num2) => num1 - num2
const div = (num1, num2) => num1 / num2
const mul = (num1, num2) => num1 * num2
export { add, sub, div, mul }
// app.js
import { add } from './calculator'
console.log(add(2,2)) // 4
ES2015 modulesES2015 modules
moduleexported functionalities
@loige 56 . 2
// calculator.js
const add = (num1, num2) => num1 + num2
const sub = (num1, num2) => num1 - num2
const div = (num1, num2) => num1 / num2
const mul = (num1, num2) => num1 * num2
export { add, sub, div, mul }
// app.js
import { add } from './calculator'
console.log(add(2,2)) // 4
ES2015 modulesES2015 modules
module
app
@loige 56 . 2
// calculator.js
const add = (num1, num2) => num1 + num2
const sub = (num1, num2) => num1 - num2
const div = (num1, num2) => num1 / num2
const mul = (num1, num2) => num1 * num2
export { add, sub, div, mul }
// app.js
import { add } from './calculator'
console.log(add(2,2)) // 4
ES2015 modulesES2015 modules
module
app
import specific functionality
@loige 56 . 2
// index.html
<html>
<body>
<!-- ... -->
<script type="module">
import { add } from 'calculator.js'
console.log(add(2,2)) // 4
</script>
</body>
</html>
ES2015 modulesES2015 modules
@loige 56 . 3
// index.html
<html>
<body>
<!-- ... -->
<script type="module">
import { add } from 'calculator.js'
console.log(add(2,2)) // 4
</script>
</body>
</html>
ES2015 modulesES2015 modules
"works" in some modern browsers
@loige 56 . 3
ES2015 modulesES2015 modules
Syntactically very similar to CommonJS...
BUT
import & export are static
(allow static analysis of dependencies)
 
It is a (still work in progress) standard format
 
Works (almost) seamlessly in browsers & servers
@loige 56 . 4
So many options...So many options...
Current most used practice:
Use CommonJS or ES2015 & create "compiled bundles"
@loige 57
1. Why we need modules
2. JavaScript module systems
3. How a module bundler works
4. Webpack in 2 minutes!
5. Advanced module bundling
AgendaAgenda
@loige 58
Let's try to use CommonJSLet's try to use CommonJS
in the browserin the browser
@loige 59
const $ = require('zepto')
const tippy = require('tippy.js')
const UUID = require('uuidjs')
const { confetti } = require('dom-confetti/src/main')
const store = require('store2')
const Favico = require('favico.js')
!(function () {
const colors = ['#a864fd', '#29cdff', '#78ff44', '#ff718d', '#fdff6a']
const todoApp = (rootEl, opt = {}) => {
const todos = opt.todos || []
let completedTasks = opt.completedTasks || 0
const onChange = opt.onChange || (() => {})
const list = rootEl.find('.todo-list')
const footer = rootEl.find('.footer')
const todoCount = footer.find('.todo-count')
const insertInput = rootEl.find('.add-todo-box input')
const insertBtn = rootEl.find('.add-todo-box button')
const render = () => {
let tips
list.html('')
The browser doesn't know how
to process require.
It doesn't support CommonJS!
@loige 60
Module BundlerModule Bundler
A tool that takes modules with dependencies and emits
static assets representing those modules
 
Those static assets can be processed by browsers!
@loige 61
Dependency graphDependency graph
A graph built by connecting every module with its direct
dependencies.
app
dependency A dependency B
dependency A2
shared
dependency
@loige 62
A module bundler has to:A module bundler has to:
Construct the dependency graph
(Dependency Resolution)
Assemble the modules in the graph into a
single executable asset (Packing)
@loige 63
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
64@loige
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
app
64
(entrypoint)
(1)
@loige
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
app
calculator
64
(entrypoint)
(1)
@loige
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
app
calculator
64
(entrypoint)
(1)
(2)
@loige
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
app
calculator
parser
64
(entrypoint)
(1)
(2)
@loige
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
app
calculator
parser
64
(entrypoint)
(1)
(2)
(3)
@loige
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
app
calculator
parser resolver
64
(entrypoint)
(1)
(2)
(3)
@loige
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
app
calculator
parser resolver
64
(entrypoint)
(1)
(2)
(3)
(4)
@loige
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
app
calculator log
parser resolver
64
(entrypoint)
(1)
(2)
(3)
(4)
@loige
// app.js
const calculator = require('./calculator')
const log = require('./log')
log(calculator('2 + 2 / 4'))
// log.js
module.exports = console.log
// calculator.js
const parser = require('./parser')
const resolver = require('./resolver')
module.exports = (expr) => resolver(parser(expr))
// parser.js
module.exports = (expr) => { /* ... */ }
// resolver.js
module.exports = (tokens) => { /* ... */ }
Dependency resolutionDependency resolution
app
calculator log
parser resolver
64
(entrypoint)
(1)
(2)
(3)
(4)
(5)
@loige
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./parser': (module, require) => { … },
@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … },
@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … },
@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … },
require path
@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … },
module factory function
@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … },
const parser = require('./parser');const resolver = 
require('./resolver');module.exports = (expr) => 
resolver(parser(expr))@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … },
const parser = require('./parser');const resolver = 
require('./resolver');module.exports = (expr) => 
resolver(parser(expr))@loige 65
DuringDuring dependency resolutiondependency resolution,,
the bundler creates athe bundler creates a modules mapmodules map
{ 
 
 
 
 
 
 
 
} 
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … },
const parser = require('./parser');const resolver = 
require('./resolver');module.exports = (expr) => 
resolver(parser(expr))@loige 65
PackingPacking
{ 
  ­­­ : ­­­ 
  ­­­ : ­­­­ 
  ­­­ : ­­ 
}
Modules mapModules map
@loige 66
PackingPacking
{ 
  ­­­ : ­­­ 
  ­­­ : ­­­­ 
  ­­­ : ­­ 
}
Modules mapModules map
@loige 66
PackingPacking
.js
{ 
  ­­­ : ­­­ 
  ­­­ : ­­­­ 
  ­­­ : ­­ 
}
Modules mapModules map
Single executableSingle executable
JS fileJS file
@loige 66
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
) 67
@loige
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
)
IIFE passing the modules map as
argument
67
@loige
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
)
Custom require function:
it will load the modules by
evaluating the code from the
modules map
67
@loige
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
)
A reference to a module with an
empty module.exports. 
This will be filled at evaluation
time
67
@loige
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
)
Invoking the factory function for
the given module name.
(Service locator pattern)
67
@loige
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
)
The current reference module is
passed, the factory function will
modify this object by adding the
proper exported values.
67
@loige
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
)
The custom require function is
passed so, modules can
recursively require other modules
67
@loige
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
)
The resulting module.exports is
returned
67
@loige
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
)
The entrypoint module is
required, triggering the actual
execution of the business logic
67
@loige
Packed executable filePacked executable file
((modulesMap) => {
const require = (name) => {
const module = { exports: {} }
modulesMap[name](module, require)
return module.exports
}
require('./app')
})(
{
'./app': (module, require) => { … },
'./calculator': (module, require) => { … },
'./log': (module, require) => { … },
'./parser': (module, require) => { … },
'./resolver': (module, require) => { … }
}
) 67
@loige
Now you know howNow you know how
Module bundlers work!Module bundlers work!
  
And how to convert code writtenAnd how to convert code written
usingusing CommonJSCommonJS to a single file thatto a single file that
works in the browserworks in the browser
@loige 68
A challenge for you!A challenge for you!
If you do, ... I'll have a prize for you!
 
TIP: you can use  or  to parse JavaScript files (look for
require and module.exports) and to map relative module paths to
actual files in the filesystem.
 
Need an inspiration? Check the awesome !
let me know
acorn babel-parser
resolve
minipack
Can you build a (simple) module bundler from scratch?Can you build a (simple) module bundler from scratch?
@loige 69
1. Why we need modules
2. JavaScript module systems
3. How a module bundler works
4. Webpack in 2 minutes!
5. Advanced module bundling
AgendaAgenda
@loige 70
A state of the art moduleA state of the art module
bundler for the webbundler for the web
@loige 71
npm install webpack webpack­cli
@loige 72
webpack app.js
yep, recent versions of Webpack work without config!
@loige 73
webpack ­­mode=development app.js
Do not compress the code and add
annotations!
@loige 74
loige.link/sample-webpacked-file
@loige75
Webpack conceptsWebpack concepts
Entry point: the starting file for dependency resolution.
Output: the destination file (bundled file).
Loaders: algorithms to parse different file types and convert them
into executable javascript (e.g. babel, typescript, but also CSS,
images or other static assets)
Plugins: do extra things (e.g. generate a wrapping HTML or
analysis tools)
@loige 76
const { resolve, join } = require('path')
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
entry: './app.js',
output: {
path: resolve(join(__dirname, 'build')),
filename: 'app.js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env']
]
}
}
}
]
},
plugins: [
new CompressionPlugin()
]
}
Webpack.config.js
@loige77
const { resolve, join } = require('path')
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
entry: './app.js',
output: {
path: resolve(join(__dirname, 'build')),
filename: 'app.js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env']
]
}
}
}
]
},
plugins: [
new CompressionPlugin()
]
}
Webpack.config.js
Entrypoint
Build the dependency graph starting from ./app.js
@loige77
const { resolve, join } = require('path')
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
entry: './app.js',
output: {
path: resolve(join(__dirname, 'build')),
filename: 'app.js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env']
]
}
}
}
]
},
plugins: [
new CompressionPlugin()
]
}
Webpack.config.js
Output
Save the resulting bundled file in ./build/app.js
@loige77
const { resolve, join } = require('path')
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
entry: './app.js',
output: {
path: resolve(join(__dirname, 'build')),
filename: 'app.js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env']
]
}
}
}
]
},
plugins: [
new CompressionPlugin()
]
}
Webpack.config.js
Loaders
All the files matching "*.js" are processed with babel
and converted to ES5 Javascript
@loige77
const { resolve, join } = require('path')
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
entry: './app.js',
output: {
path: resolve(join(__dirname, 'build')),
filename: 'app.js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env']
]
}
}
}
]
},
plugins: [
new CompressionPlugin()
]
}
Webpack.config.js
Plugins
Uses a plugin that generates a gzipped copy of every
emitted file.
@loige77
Everything is a moduleEverything is a module
import React, { Component } from 'react'
import logo from './logo.svg'
import './App.css'
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
</div>
);
}
}
export default App 78
Everything is a moduleEverything is a module
import React, { Component } from 'react'
import logo from './logo.svg'
import './App.css'
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
</div>
);
}
}
export default App 78
Everything is a moduleEverything is a module
import React, { Component } from 'react'
import logo from './logo.svg'
import './App.css'
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
</div>
);
}
}
export default App 78
Everything is a moduleEverything is a module
import React, { Component } from 'react'
import logo from './logo.svg'
import './App.css'
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
</div>
);
}
}
export default App 78
Webpack can load any type of fileWebpack can load any type of file
As long as you specify a "As long as you specify a "loaderloader" that tells" that tells
how to convert the file into something thehow to convert the file into something the
browser understands.browser understands.
This is how Webpack allows you to use Babel, TypeScript,
Clojure, Elm but also to load CSSs, Images and other assets.
79
{
test: /.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', 80
{
test: /.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9',
// Defines how to load .css files (uses a pipeline of loaders)
80
{
test: /.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9',
// Defines how to load .css files (uses a pipeline of loaders)
// parses the file with post-css
80
{
test: /.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9',
// Defines how to load .css files (uses a pipeline of loaders)
// parses the file with post-css
// process @import and url()
// statements
80
{
test: /.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9',
// Defines how to load .css files (uses a pipeline of loaders)
// parses the file with post-css
// process @import and url()
// statements
// inject the resulting code with a <style> tag
80
...Webpack can do (a lot) more!...Webpack can do (a lot) more!
Dev ServerDev Server
Tree shakingTree shaking
Dependencies analyticsDependencies analytics
Source mapsSource maps
Async require / module splittingAsync require / module splitting
@loige 81
1. Why we need modules
2. JavaScript module systems
3. How a module bundler works
4. Webpack in 2 minutes!
5. Advanced module bundling
AgendaAgenda
@loige 82
Webpack inWebpack in create-react-appcreate-react-app
yarn global add create-react-app
create-react-app newapp
cd newapp
yarn
yarn eject
cat ./config/webpack.config.{dev,prod}.js
83
(demo time)(demo time)
84
Webpack is notWebpack is not
the only possibility!the only possibility!
85
1. Why we need modules
2. JavaScript module systems
3. How a module bundler works
4. Webpack in 2 minutes!
5. Advanced module bundling
AgendaAgenda
@loige 86
Module bundlers are your friendsModule bundlers are your friends
Now you know how they work,
they are not (really) magic!
Start small and add more when needed
If you try to build your own you'll learn a
lot more!
@loige 87
THANKS!THANKS!
loige.link/bundle-dublinjs
     Special thanks
, , ,
(reviewers) and
 (inspirations: his and his
)
@Podgeypoos79 @andreaman87 @mariocasciaro
@eugenserbanescu
@MarijnJH amazing book
workshop on JS modules
@loige
Images by .Streamline Emoji pack
88

More Related Content

What's hot

Zend Framework meets Doctrine 2
Zend Framework meets Doctrine 2Zend Framework meets Doctrine 2
Zend Framework meets Doctrine 2
Mayflower GmbH
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescript
Katy Slemon
 
JavaScript Modules Done Right
JavaScript Modules Done RightJavaScript Modules Done Right
JavaScript Modules Done Right
Mariusz Nowak
 
Parte II Objective C
Parte II   Objective CParte II   Objective C
Parte II Objective C
Paolo Quadrani
 
Design patterns
Design patternsDesign patterns
Design patterns
Ba Tran
 
Operator overload rr
Operator overload  rrOperator overload  rr
Operator overload rr
Dhivya Shanmugam
 
Dependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHPDependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHPmtoppa
 
Koin Quickstart
Koin QuickstartKoin Quickstart
Koin Quickstart
Matthew Clarke
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHoward Lewis Ship
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
Siarhei Barysiuk
 
Creational pattern 2
Creational pattern 2Creational pattern 2
Creational pattern 2
Naga Muruga
 
Multithreading and Parallelism on iOS [MobOS 2013]
 Multithreading and Parallelism on iOS [MobOS 2013] Multithreading and Parallelism on iOS [MobOS 2013]
Multithreading and Parallelism on iOS [MobOS 2013]Kuba Břečka
 
Architecting for PHP5 - Why "Runs on PHP5" is not "Written for PHP5"
Architecting for PHP5 - Why "Runs on PHP5" is not "Written for PHP5"Architecting for PHP5 - Why "Runs on PHP5" is not "Written for PHP5"
Architecting for PHP5 - Why "Runs on PHP5" is not "Written for PHP5"
ZendCon
 
Introduction Php
Introduction PhpIntroduction Php
Introduction Php
sanjay joshi
 
Rails 3 hints
Rails 3 hintsRails 3 hints
Rails 3 hints
Tiago Cardoso
 
Visualizing MVC, and an introduction to Giotto
Visualizing MVC, and an introduction to GiottoVisualizing MVC, and an introduction to Giotto
Visualizing MVC, and an introduction to Giottopriestc
 
Developing components and extensions for ext js
Developing components and extensions for ext jsDeveloping components and extensions for ext js
Developing components and extensions for ext jsMats Bryntse
 
Basic Oops concept of PHP
Basic Oops concept of PHPBasic Oops concept of PHP
Basic Oops concept of PHP
Rohan Sharma
 

What's hot (20)

Zend Framework meets Doctrine 2
Zend Framework meets Doctrine 2Zend Framework meets Doctrine 2
Zend Framework meets Doctrine 2
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescript
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
 
JavaScript Modules Done Right
JavaScript Modules Done RightJavaScript Modules Done Right
JavaScript Modules Done Right
 
Parte II Objective C
Parte II   Objective CParte II   Objective C
Parte II Objective C
 
Design patterns
Design patternsDesign patterns
Design patterns
 
Operator overload rr
Operator overload  rrOperator overload  rr
Operator overload rr
 
Dependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHPDependency Inversion and Dependency Injection in PHP
Dependency Inversion and Dependency Injection in PHP
 
Iphone course 1
Iphone course 1Iphone course 1
Iphone course 1
 
Koin Quickstart
Koin QuickstartKoin Quickstart
Koin Quickstart
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
 
Creational pattern 2
Creational pattern 2Creational pattern 2
Creational pattern 2
 
Multithreading and Parallelism on iOS [MobOS 2013]
 Multithreading and Parallelism on iOS [MobOS 2013] Multithreading and Parallelism on iOS [MobOS 2013]
Multithreading and Parallelism on iOS [MobOS 2013]
 
Architecting for PHP5 - Why "Runs on PHP5" is not "Written for PHP5"
Architecting for PHP5 - Why "Runs on PHP5" is not "Written for PHP5"Architecting for PHP5 - Why "Runs on PHP5" is not "Written for PHP5"
Architecting for PHP5 - Why "Runs on PHP5" is not "Written for PHP5"
 
Introduction Php
Introduction PhpIntroduction Php
Introduction Php
 
Rails 3 hints
Rails 3 hintsRails 3 hints
Rails 3 hints
 
Visualizing MVC, and an introduction to Giotto
Visualizing MVC, and an introduction to GiottoVisualizing MVC, and an introduction to Giotto
Visualizing MVC, and an introduction to Giotto
 
Developing components and extensions for ext js
Developing components and extensions for ext jsDeveloping components and extensions for ext js
Developing components and extensions for ext js
 
Basic Oops concept of PHP
Basic Oops concept of PHPBasic Oops concept of PHP
Basic Oops concept of PHP
 

Similar to Unbundling the JavaScript module bundler - DublinJS July 2018

Unbundling the JavaScript module bundler - Codemotion Rome 2018
Unbundling the JavaScript module bundler - Codemotion Rome 2018Unbundling the JavaScript module bundler - Codemotion Rome 2018
Unbundling the JavaScript module bundler - Codemotion Rome 2018
Luciano Mammino
 
Unbundling the JavaScript module bundler - Luciano Mammino - Codemotion Rome ...
Unbundling the JavaScript module bundler - Luciano Mammino - Codemotion Rome ...Unbundling the JavaScript module bundler - Luciano Mammino - Codemotion Rome ...
Unbundling the JavaScript module bundler - Luciano Mammino - Codemotion Rome ...
Codemotion
 
The mighty js_function
The mighty js_functionThe mighty js_function
The mighty js_functiontimotheeg
 
Using Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture projectUsing Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture project
Fabio Collini
 
Navigating the wild seas of es6 modules
Navigating the wild seas of es6 modulesNavigating the wild seas of es6 modules
Navigating the wild seas of es6 modulesGil Tayar
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
Thierry Wasylczenko
 
OpenWebBeans and DeltaSpike at ApacheCon
OpenWebBeans and DeltaSpike at ApacheConOpenWebBeans and DeltaSpike at ApacheCon
OpenWebBeans and DeltaSpike at ApacheCon
os890
 
JavaScript, qué hermoso eres
JavaScript, qué hermoso eresJavaScript, qué hermoso eres
JavaScript, qué hermoso eres
Alea Soluciones, S.L.
 
Advanced Node.JS Meetup
Advanced Node.JS MeetupAdvanced Node.JS Meetup
Advanced Node.JS Meetup
LINAGORA
 
Python import mechanism
Python import mechanismPython import mechanism
Python import mechanism
Yuki Nishiwaki
 
Release management with NuGet/Chocolatey/JIRA
Release management with NuGet/Chocolatey/JIRARelease management with NuGet/Chocolatey/JIRA
Release management with NuGet/Chocolatey/JIRA
Yaroslav Serhieiev
 
MEF Deep Dive by Piotr Wlodek
MEF Deep Dive by Piotr WlodekMEF Deep Dive by Piotr Wlodek
MEF Deep Dive by Piotr Wlodekinfusiondev
 
Context and Dependency Injection
Context and Dependency InjectionContext and Dependency Injection
Context and Dependency Injection
Werner Keil
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
Nascenia IT
 
Android App Architecture with modern libs in practice. Our way in R.I.D., Ser...
Android App Architecture with modern libs in practice. Our way in R.I.D., Ser...Android App Architecture with modern libs in practice. Our way in R.I.D., Ser...
Android App Architecture with modern libs in practice. Our way in R.I.D., Ser...
Sigma Software
 
ZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of itZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of it
Steve Maraspin
 
Scripting
ScriptingScripting
Scriptingaztack
 
Gephi Toolkit Tutorial
Gephi Toolkit TutorialGephi Toolkit Tutorial
Gephi Toolkit Tutorial
Gephi Consortium
 

Similar to Unbundling the JavaScript module bundler - DublinJS July 2018 (20)

Unbundling the JavaScript module bundler - Codemotion Rome 2018
Unbundling the JavaScript module bundler - Codemotion Rome 2018Unbundling the JavaScript module bundler - Codemotion Rome 2018
Unbundling the JavaScript module bundler - Codemotion Rome 2018
 
Unbundling the JavaScript module bundler - Luciano Mammino - Codemotion Rome ...
Unbundling the JavaScript module bundler - Luciano Mammino - Codemotion Rome ...Unbundling the JavaScript module bundler - Luciano Mammino - Codemotion Rome ...
Unbundling the JavaScript module bundler - Luciano Mammino - Codemotion Rome ...
 
The mighty js_function
The mighty js_functionThe mighty js_function
The mighty js_function
 
Using Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture projectUsing Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture project
 
Fpga 13-task-and-functions
Fpga 13-task-and-functionsFpga 13-task-and-functions
Fpga 13-task-and-functions
 
Navigating the wild seas of es6 modules
Navigating the wild seas of es6 modulesNavigating the wild seas of es6 modules
Navigating the wild seas of es6 modules
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
OpenWebBeans and DeltaSpike at ApacheCon
OpenWebBeans and DeltaSpike at ApacheConOpenWebBeans and DeltaSpike at ApacheCon
OpenWebBeans and DeltaSpike at ApacheCon
 
JavaScript, qué hermoso eres
JavaScript, qué hermoso eresJavaScript, qué hermoso eres
JavaScript, qué hermoso eres
 
Advanced Node.JS Meetup
Advanced Node.JS MeetupAdvanced Node.JS Meetup
Advanced Node.JS Meetup
 
Iffy
IffyIffy
Iffy
 
Python import mechanism
Python import mechanismPython import mechanism
Python import mechanism
 
Release management with NuGet/Chocolatey/JIRA
Release management with NuGet/Chocolatey/JIRARelease management with NuGet/Chocolatey/JIRA
Release management with NuGet/Chocolatey/JIRA
 
MEF Deep Dive by Piotr Wlodek
MEF Deep Dive by Piotr WlodekMEF Deep Dive by Piotr Wlodek
MEF Deep Dive by Piotr Wlodek
 
Context and Dependency Injection
Context and Dependency InjectionContext and Dependency Injection
Context and Dependency Injection
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
 
Android App Architecture with modern libs in practice. Our way in R.I.D., Ser...
Android App Architecture with modern libs in practice. Our way in R.I.D., Ser...Android App Architecture with modern libs in practice. Our way in R.I.D., Ser...
Android App Architecture with modern libs in practice. Our way in R.I.D., Ser...
 
ZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of itZF2 Modular Architecture - Taking advantage of it
ZF2 Modular Architecture - Taking advantage of it
 
Scripting
ScriptingScripting
Scripting
 
Gephi Toolkit Tutorial
Gephi Toolkit TutorialGephi Toolkit Tutorial
Gephi Toolkit Tutorial
 

More from Luciano Mammino

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJS
Luciano Mammino
 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
Luciano Mammino
 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Luciano Mammino
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiper
Luciano Mammino
 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!
Luciano Mammino
 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLs
Luciano Mammino
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
Luciano Mammino
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
Luciano Mammino
 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
Luciano Mammino
 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & Airtable
Luciano Mammino
 
Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀
Luciano Mammino
 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust Dublin
Luciano Mammino
 
Monoliths to the cloud!
Monoliths to the cloud!Monoliths to the cloud!
Monoliths to the cloud!
Luciano Mammino
 
The senior dev
The senior devThe senior dev
The senior dev
Luciano Mammino
 
Node.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaNode.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community Vijayawada
Luciano Mammino
 
A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)
Luciano Mammino
 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made Simple
Luciano Mammino
 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti Serverless
Luciano Mammino
 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Luciano Mammino
 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021
Luciano Mammino
 

More from Luciano Mammino (20)

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJS
 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiper
 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!
 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLs
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & Airtable
 
Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀
 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust Dublin
 
Monoliths to the cloud!
Monoliths to the cloud!Monoliths to the cloud!
Monoliths to the cloud!
 
The senior dev
The senior devThe senior dev
The senior dev
 
Node.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaNode.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community Vijayawada
 
A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)
 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made Simple
 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti Serverless
 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021
 

Recently uploaded

European Championships Football Quiz.pptx
European Championships Football Quiz.pptxEuropean Championships Football Quiz.pptx
European Championships Football Quiz.pptx
PaulGray854697
 
Croatia vs Italy Can Luka Modrić Lead Croatia to Euro Cup Germany Glory in Hi...
Croatia vs Italy Can Luka Modrić Lead Croatia to Euro Cup Germany Glory in Hi...Croatia vs Italy Can Luka Modrić Lead Croatia to Euro Cup Germany Glory in Hi...
Croatia vs Italy Can Luka Modrić Lead Croatia to Euro Cup Germany Glory in Hi...
Eticketing.co
 
TAM Sports_IPL 17_Commercial Advertising_Report.pdf
TAM Sports_IPL 17_Commercial Advertising_Report.pdfTAM Sports_IPL 17_Commercial Advertising_Report.pdf
TAM Sports_IPL 17_Commercial Advertising_Report.pdf
Social Samosa
 
Serbia vs England Tickets: Serbia's Return to Euro Cup 2024, A Look at Key Pl...
Serbia vs England Tickets: Serbia's Return to Euro Cup 2024, A Look at Key Pl...Serbia vs England Tickets: Serbia's Return to Euro Cup 2024, A Look at Key Pl...
Serbia vs England Tickets: Serbia's Return to Euro Cup 2024, A Look at Key Pl...
Eticketing.co
 
Spain vs Croatia Date, venue and match preview ahead of Euro Cup clash as Mod...
Spain vs Croatia Date, venue and match preview ahead of Euro Cup clash as Mod...Spain vs Croatia Date, venue and match preview ahead of Euro Cup clash as Mod...
Spain vs Croatia Date, venue and match preview ahead of Euro Cup clash as Mod...
Eticketing.co
 
JORNADA 10 LIGA MURO 2024BASQUETBOL1.pdf
JORNADA 10 LIGA MURO 2024BASQUETBOL1.pdfJORNADA 10 LIGA MURO 2024BASQUETBOL1.pdf
JORNADA 10 LIGA MURO 2024BASQUETBOL1.pdf
Arturo Pacheco Alvarez
 
GilZeimer_SS2024_12Injuries_5-30-24.pptx
GilZeimer_SS2024_12Injuries_5-30-24.pptxGilZeimer_SS2024_12Injuries_5-30-24.pptx
GilZeimer_SS2024_12Injuries_5-30-24.pptx
Zeimer's Advertising Shoppe
 
Narrated Business Proposal for the Philadelphia Eagles
Narrated Business Proposal for the Philadelphia EaglesNarrated Business Proposal for the Philadelphia Eagles
Narrated Business Proposal for the Philadelphia Eagles
camrynascott12
 
Ukraine Vs Belgium What are the odds for Ukraine to make the Euro Cup 2024 qu...
Ukraine Vs Belgium What are the odds for Ukraine to make the Euro Cup 2024 qu...Ukraine Vs Belgium What are the odds for Ukraine to make the Euro Cup 2024 qu...
Ukraine Vs Belgium What are the odds for Ukraine to make the Euro Cup 2024 qu...
World Wide Tickets And Hospitality
 
Spain vs Italy Spain at Euro Cup 2024 Group, Fixtures, Players to Watch and M...
Spain vs Italy Spain at Euro Cup 2024 Group, Fixtures, Players to Watch and M...Spain vs Italy Spain at Euro Cup 2024 Group, Fixtures, Players to Watch and M...
Spain vs Italy Spain at Euro Cup 2024 Group, Fixtures, Players to Watch and M...
Eticketing.co
 
Turkey vs Georgia Turkey's Road to Redemption and Euro 2024 Prospects.pdf
Turkey vs Georgia Turkey's Road to Redemption and Euro 2024 Prospects.pdfTurkey vs Georgia Turkey's Road to Redemption and Euro 2024 Prospects.pdf
Turkey vs Georgia Turkey's Road to Redemption and Euro 2024 Prospects.pdf
Eticketing.co
 
Boletin de la I Copa Panamericana de Voleibol Femenino U17 Guatemala 2024
Boletin de la I Copa Panamericana de Voleibol Femenino U17 Guatemala 2024Boletin de la I Copa Panamericana de Voleibol Femenino U17 Guatemala 2024
Boletin de la I Copa Panamericana de Voleibol Femenino U17 Guatemala 2024
Judith Chuquipul
 
The Split_ Hardik Pandya and Natasa Stankovic Part Ways News by Betkaro247 (3...
The Split_ Hardik Pandya and Natasa Stankovic Part Ways News by Betkaro247 (3...The Split_ Hardik Pandya and Natasa Stankovic Part Ways News by Betkaro247 (3...
The Split_ Hardik Pandya and Natasa Stankovic Part Ways News by Betkaro247 (3...
bet k247
 
Belgium Vs Romania Witsel recalled to Belgium squad for Euro 2024.docx
Belgium Vs Romania Witsel recalled to Belgium squad for Euro 2024.docxBelgium Vs Romania Witsel recalled to Belgium squad for Euro 2024.docx
Belgium Vs Romania Witsel recalled to Belgium squad for Euro 2024.docx
World Wide Tickets And Hospitality
 
CAA Region II Day 1 Morning Result Accra event
CAA Region II Day 1 Morning Result Accra eventCAA Region II Day 1 Morning Result Accra event
CAA Region II Day 1 Morning Result Accra event
Kweku Zurek
 
Understanding Golf Simulator Equipment A Beginner's Guide.pdf
Understanding Golf Simulator Equipment A Beginner's Guide.pdfUnderstanding Golf Simulator Equipment A Beginner's Guide.pdf
Understanding Golf Simulator Equipment A Beginner's Guide.pdf
My Garage Golf
 
Ukraine Euro Cup 2024 Squad Sergiy Rebrov's Selections and Prospects.docx
Ukraine Euro Cup 2024 Squad Sergiy Rebrov's Selections and Prospects.docxUkraine Euro Cup 2024 Squad Sergiy Rebrov's Selections and Prospects.docx
Ukraine Euro Cup 2024 Squad Sergiy Rebrov's Selections and Prospects.docx
Euro Cup 2024 Tickets
 
Belgium vs Romania Injuries and Patience in Belgium’s Euro Cup Germany Squad....
Belgium vs Romania Injuries and Patience in Belgium’s Euro Cup Germany Squad....Belgium vs Romania Injuries and Patience in Belgium’s Euro Cup Germany Squad....
Belgium vs Romania Injuries and Patience in Belgium’s Euro Cup Germany Squad....
Eticketing.co
 
Turkey vs Georgia Tickets: Turkey's Road to Glory and Building Momentum for U...
Turkey vs Georgia Tickets: Turkey's Road to Glory and Building Momentum for U...Turkey vs Georgia Tickets: Turkey's Road to Glory and Building Momentum for U...
Turkey vs Georgia Tickets: Turkey's Road to Glory and Building Momentum for U...
Eticketing.co
 
Turkey Hit by Double Injury Blow before of Euro 2024.docx
Turkey Hit by Double Injury Blow before of Euro 2024.docxTurkey Hit by Double Injury Blow before of Euro 2024.docx
Turkey Hit by Double Injury Blow before of Euro 2024.docx
Euro Cup 2024 Tickets
 

Recently uploaded (20)

European Championships Football Quiz.pptx
European Championships Football Quiz.pptxEuropean Championships Football Quiz.pptx
European Championships Football Quiz.pptx
 
Croatia vs Italy Can Luka Modrić Lead Croatia to Euro Cup Germany Glory in Hi...
Croatia vs Italy Can Luka Modrić Lead Croatia to Euro Cup Germany Glory in Hi...Croatia vs Italy Can Luka Modrić Lead Croatia to Euro Cup Germany Glory in Hi...
Croatia vs Italy Can Luka Modrić Lead Croatia to Euro Cup Germany Glory in Hi...
 
TAM Sports_IPL 17_Commercial Advertising_Report.pdf
TAM Sports_IPL 17_Commercial Advertising_Report.pdfTAM Sports_IPL 17_Commercial Advertising_Report.pdf
TAM Sports_IPL 17_Commercial Advertising_Report.pdf
 
Serbia vs England Tickets: Serbia's Return to Euro Cup 2024, A Look at Key Pl...
Serbia vs England Tickets: Serbia's Return to Euro Cup 2024, A Look at Key Pl...Serbia vs England Tickets: Serbia's Return to Euro Cup 2024, A Look at Key Pl...
Serbia vs England Tickets: Serbia's Return to Euro Cup 2024, A Look at Key Pl...
 
Spain vs Croatia Date, venue and match preview ahead of Euro Cup clash as Mod...
Spain vs Croatia Date, venue and match preview ahead of Euro Cup clash as Mod...Spain vs Croatia Date, venue and match preview ahead of Euro Cup clash as Mod...
Spain vs Croatia Date, venue and match preview ahead of Euro Cup clash as Mod...
 
JORNADA 10 LIGA MURO 2024BASQUETBOL1.pdf
JORNADA 10 LIGA MURO 2024BASQUETBOL1.pdfJORNADA 10 LIGA MURO 2024BASQUETBOL1.pdf
JORNADA 10 LIGA MURO 2024BASQUETBOL1.pdf
 
GilZeimer_SS2024_12Injuries_5-30-24.pptx
GilZeimer_SS2024_12Injuries_5-30-24.pptxGilZeimer_SS2024_12Injuries_5-30-24.pptx
GilZeimer_SS2024_12Injuries_5-30-24.pptx
 
Narrated Business Proposal for the Philadelphia Eagles
Narrated Business Proposal for the Philadelphia EaglesNarrated Business Proposal for the Philadelphia Eagles
Narrated Business Proposal for the Philadelphia Eagles
 
Ukraine Vs Belgium What are the odds for Ukraine to make the Euro Cup 2024 qu...
Ukraine Vs Belgium What are the odds for Ukraine to make the Euro Cup 2024 qu...Ukraine Vs Belgium What are the odds for Ukraine to make the Euro Cup 2024 qu...
Ukraine Vs Belgium What are the odds for Ukraine to make the Euro Cup 2024 qu...
 
Spain vs Italy Spain at Euro Cup 2024 Group, Fixtures, Players to Watch and M...
Spain vs Italy Spain at Euro Cup 2024 Group, Fixtures, Players to Watch and M...Spain vs Italy Spain at Euro Cup 2024 Group, Fixtures, Players to Watch and M...
Spain vs Italy Spain at Euro Cup 2024 Group, Fixtures, Players to Watch and M...
 
Turkey vs Georgia Turkey's Road to Redemption and Euro 2024 Prospects.pdf
Turkey vs Georgia Turkey's Road to Redemption and Euro 2024 Prospects.pdfTurkey vs Georgia Turkey's Road to Redemption and Euro 2024 Prospects.pdf
Turkey vs Georgia Turkey's Road to Redemption and Euro 2024 Prospects.pdf
 
Boletin de la I Copa Panamericana de Voleibol Femenino U17 Guatemala 2024
Boletin de la I Copa Panamericana de Voleibol Femenino U17 Guatemala 2024Boletin de la I Copa Panamericana de Voleibol Femenino U17 Guatemala 2024
Boletin de la I Copa Panamericana de Voleibol Femenino U17 Guatemala 2024
 
The Split_ Hardik Pandya and Natasa Stankovic Part Ways News by Betkaro247 (3...
The Split_ Hardik Pandya and Natasa Stankovic Part Ways News by Betkaro247 (3...The Split_ Hardik Pandya and Natasa Stankovic Part Ways News by Betkaro247 (3...
The Split_ Hardik Pandya and Natasa Stankovic Part Ways News by Betkaro247 (3...
 
Belgium Vs Romania Witsel recalled to Belgium squad for Euro 2024.docx
Belgium Vs Romania Witsel recalled to Belgium squad for Euro 2024.docxBelgium Vs Romania Witsel recalled to Belgium squad for Euro 2024.docx
Belgium Vs Romania Witsel recalled to Belgium squad for Euro 2024.docx
 
CAA Region II Day 1 Morning Result Accra event
CAA Region II Day 1 Morning Result Accra eventCAA Region II Day 1 Morning Result Accra event
CAA Region II Day 1 Morning Result Accra event
 
Understanding Golf Simulator Equipment A Beginner's Guide.pdf
Understanding Golf Simulator Equipment A Beginner's Guide.pdfUnderstanding Golf Simulator Equipment A Beginner's Guide.pdf
Understanding Golf Simulator Equipment A Beginner's Guide.pdf
 
Ukraine Euro Cup 2024 Squad Sergiy Rebrov's Selections and Prospects.docx
Ukraine Euro Cup 2024 Squad Sergiy Rebrov's Selections and Prospects.docxUkraine Euro Cup 2024 Squad Sergiy Rebrov's Selections and Prospects.docx
Ukraine Euro Cup 2024 Squad Sergiy Rebrov's Selections and Prospects.docx
 
Belgium vs Romania Injuries and Patience in Belgium’s Euro Cup Germany Squad....
Belgium vs Romania Injuries and Patience in Belgium’s Euro Cup Germany Squad....Belgium vs Romania Injuries and Patience in Belgium’s Euro Cup Germany Squad....
Belgium vs Romania Injuries and Patience in Belgium’s Euro Cup Germany Squad....
 
Turkey vs Georgia Tickets: Turkey's Road to Glory and Building Momentum for U...
Turkey vs Georgia Tickets: Turkey's Road to Glory and Building Momentum for U...Turkey vs Georgia Tickets: Turkey's Road to Glory and Building Momentum for U...
Turkey vs Georgia Tickets: Turkey's Road to Glory and Building Momentum for U...
 
Turkey Hit by Double Injury Blow before of Euro 2024.docx
Turkey Hit by Double Injury Blow before of Euro 2024.docxTurkey Hit by Double Injury Blow before of Euro 2024.docx
Turkey Hit by Double Injury Blow before of Euro 2024.docx
 

Unbundling the JavaScript module bundler - DublinJS July 2018

  • 1. Unbundling the JavaScript module bundlerUnbundling the JavaScript module bundler Luciano Mammino (Luciano Mammino ( ))@loige@loige DublinJS  03/07/2018 loige.link/bundle-dublinjs 1
  • 3. Webpack == PAIN!?Webpack == PAIN!? twitter.com/search?q=webpack%20pain @loige 3
  • 11. It's not Webpack!It's not Webpack! Module bundling is actually complicated!Module bundling is actually complicated! @loige 11
  • 12. Luciano... whoLuciano... who Find me online: -  (@loige) -  (lmammino) - -  (loige.co) Twitter GitHub Linkedin Blog Solution Architect at with @mariocasciaro with @andreaman87 with @Podgeypoos79 12
  • 13. 1. Why we need modules 2. JavaScript module systems 3. How a module bundler works 4. Webpack in 2 minutes! 5. Advanced module bundling AgendaAgenda @loige 13
  • 16. Dynamic DOM manipulation React, Angular, Vue are so... overrated! @loige 16
  • 20. Persist state through Local Storage + UUIDs  +store2 uuidjs@loige 20
  • 23. 7 Requests only for the JS code! @loige 21
  • 26. How to do this?How to do this? @loige 24
  • 30. lumpy build$ 1. Downloads the files from lumpy.txt (and caches them) 2. Concatenates the content of the files 3. Minifies the resulting source code (using ) 4. Saves the resulting content in vendors.js babel-minify @loige 26 . 3
  • 32. 7 requests 2 requests @loige Even better if you "minify" these! 27
  • 34. This is good...This is good... @loige 29
  • 35. This is good...This is good... @loige 29
  • 36. This is good...This is good... ... in 2008... in 2008 waswas @loige 29
  • 37. Today...Today... We can do better!We can do better! @loige 30
  • 38. Updating dependencies should be easyUpdating dependencies should be easy We don't want to worry about dependencies ofWe don't want to worry about dependencies of dependenciesdependencies We don't have to worry about the order of importsWe don't have to worry about the order of imports Today...Today... @loige 31
  • 39. DependencyDependency (or coupling) a state in which one object uses a function of another object — Wikipedia @loige 32
  • 41. ModulesModules The bricks for structuring non-trivial applications, but also the main mechanism to enforce information hiding by keeping private all the functions and variables that are not explicitly marked to be exported — *Node.js Design Patterns (Second Edition) * yeah, I quite like quoting my stuff... @loige 34
  • 42. 1. Why we need modules 2. JavaScript module systems 3. How a module bundler works 4. Webpack in 2 minutes! 5. Advanced module bundling AgendaAgenda @loige 35
  • 43. Meet my friendMeet my friend I.I.F.E.I.I.F.E. (Immediately Invoked Function Expression) loige.link/iife @loige 36
  • 44. We generally define a function this wayWe generally define a function this way @loige 37
  • 45. We generally define a function this wayWe generally define a function this way const sum = (a, b) => a + b @loige 37
  • 46. We generally define a function this wayWe generally define a function this way const sum = (a, b) => a + b oror @loige 37
  • 47. We generally define a function this wayWe generally define a function this way const sum = (a, b) => a + b sum(a, b) { return a + b } oror @loige 37
  • 48. We generally define a function this wayWe generally define a function this way const sum = (a, b) => a + b sum(a, b) { return a + b } oror then, at some point, we execute it...then, at some point, we execute it... @loige 37
  • 49. We generally define a function this wayWe generally define a function this way const sum = (a, b) => a + b sum(a, b) { return a + b } oror then, at some point, we execute it...then, at some point, we execute it... const four = sum(2, 2) @loige 37
  • 50. A function in JS creates an isolated scopeA function in JS creates an isolated scope @loige 38
  • 51. A function in JS creates an isolated scopeA function in JS creates an isolated scope (a, b) => { const secretString = "Hello" return a + b } console.log(secretString) // undefined @loige 38
  • 52. A function in JS creates an isolated scopeA function in JS creates an isolated scope (a, b) => { const secretString = "Hello" return a + b } console.log(secretString) // undefined secretStringsecretString is not visible outside the functionis not visible outside the function @loige 38
  • 53. IIFE allows you to define an isolated scopeIIFE allows you to define an isolated scope that executes itselfthat executes itself (arg1, arg2) => { // do stuff here const iAmNotVisibleOutside = true } @loige 39
  • 54. IIFE allows you to define an isolated scopeIIFE allows you to define an isolated scope that executes itselfthat executes itself (arg1, arg2) => { // do stuff here const iAmNotVisibleOutside = true } A function with its own scope @loige 39
  • 55. )(someArg1, someArg2) IIFE allows you to define an isolated scopeIIFE allows you to define an isolated scope that executes itselfthat executes itself (arg1, arg2) => { // do stuff here const iAmNotVisibleOutside = true } ( @loige 39
  • 56. )(someArg1, someArg2) IIFE allows you to define an isolated scopeIIFE allows you to define an isolated scope that executes itselfthat executes itself (arg1, arg2) => { // do stuff here const iAmNotVisibleOutside = true } ( This wrapper executes the function immediately and passes arguments from the outer scope @loige 39
  • 57. IIFE is a recurring pattern inIIFE is a recurring pattern in JavaScript modulesJavaScript modules @loige 40
  • 58. Let's implement a moduleLet's implement a module that provides:that provides:   Information hidingInformation hiding exported functionalitiesexported functionalities @loige 41
  • 59. const myModule = (() => { const privateFoo = () => { /* ... */ } const privateBar = [ /* ... */ ] const exported = { publicFoo: () => { /* ... */ }, publicBar: [ /* ... */ ] }; return exported })() myModule.publicFoo() myModule.publicBar[0] myModule.privateFoo // undefined myModule.privateBar // undefined privateFoo // undefined privateBar // undefined @loige42
  • 60. const myModule = (() => { const privateFoo = () => { /* ... */ } const privateBar = [ /* ... */ ] const exported = { publicFoo: () => { /* ... */ }, publicBar: [ /* ... */ ] }; return exported })() A module myModule.publicFoo() myModule.publicBar[0] myModule.privateFoo // undefined myModule.privateBar // undefined privateFoo // undefined privateBar // undefined @loige42
  • 61. const myModule = (() => { const privateFoo = () => { /* ... */ } const privateBar = [ /* ... */ ] const exported = { publicFoo: () => { /* ... */ }, publicBar: [ /* ... */ ] }; return exported })() A module myModule.publicFoo() myModule.publicBar[0] myModule.privateFoo // undefined myModule.privateBar // undefined privateFoo // undefined privateBar // undefined IIFE Creates an isolated scope and executes it @loige42
  • 62. const myModule = (() => { const privateFoo = () => { /* ... */ } const privateBar = [ /* ... */ ] const exported = { publicFoo: () => { /* ... */ }, publicBar: [ /* ... */ ] }; return exported })() A module myModule.publicFoo() myModule.publicBar[0] myModule.privateFoo // undefined myModule.privateBar // undefined privateFoo // undefined privateBar // undefined information hiding non-exposed functionality @loige42
  • 63. const myModule = (() => { const privateFoo = () => { /* ... */ } const privateBar = [ /* ... */ ] const exported = { publicFoo: () => { /* ... */ }, publicBar: [ /* ... */ ] }; return exported })() A module myModule.publicFoo() myModule.publicBar[0] myModule.privateFoo // undefined myModule.privateBar // undefined privateFoo // undefined privateBar // undefined defines exported functionalities @loige42
  • 64. const myModule = (() => { const privateFoo = () => { /* ... */ } const privateBar = [ /* ... */ ] const exported = { publicFoo: () => { /* ... */ }, publicBar: [ /* ... */ ] }; return exported })() A module myModule.publicFoo() myModule.publicBar[0] myModule.privateFoo // undefined myModule.privateBar // undefined privateFoo // undefined privateBar // undefined propagates the exports to the outer scope (assigning it to myModule) @loige42
  • 65. const myModule = (() => { const privateFoo = () => { /* ... */ } const privateBar = [ /* ... */ ] const exported = { publicFoo: () => { /* ... */ }, publicBar: [ /* ... */ ] }; return exported })() A module myModule.publicFoo() myModule.publicBar[0] myModule.privateFoo // undefined myModule.privateBar // undefined privateFoo // undefined privateBar // undefined Can access exported functionalities @loige42
  • 66. const myModule = (() => { const privateFoo = () => { /* ... */ } const privateBar = [ /* ... */ ] const exported = { publicFoo: () => { /* ... */ }, publicBar: [ /* ... */ ] }; return exported })() A module myModule.publicFoo() myModule.publicBar[0] myModule.privateFoo // undefined myModule.privateBar // undefined privateFoo // undefined privateBar // undefined No visibility for the non-exported ones @loige42
  • 67. We want modules to beWe want modules to be   reusablereusable across different apps andacross different apps and organisations...organisations... ...we need...we need AA STANDARD MODULESTANDARD MODULE format!format!@loige 43
  • 68. Module system featuresModule system features Must have Simple syntax for import / export Information hiding Allows to define modules in separate files Modules can import from other modules (nested dependencies) @loige 44
  • 69. Module system featuresModule system features Nice to have Ability to import module subsets Avoid naming collision Asynchronous module loading Seamless support for Browsers & Server-side @loige 45
  • 71. JavaScript module systemsJavaScript module systems globals CommonJS (Node.js) AMD (Require.js / Dojo) UMD ES2015 Modules (ESM) Many others (SystemJS, ...) @loige 47
  • 72. GlobalsGlobals var $, jQuery $ = jQuery = (() => { return { /* ... */ } })() // ... use $ or jQuery in the global scope $.find('.button').remove() @loige 48
  • 73. GlobalsGlobals Might generate naming collisions (e.g. $ overrides browser global variable)   Modules needs to be "fully loaded" in the right order   Cannot import parts of modules @loige 49
  • 74. // or import single functionality const { concat } = require('./loDash') concat([1], [2], [3]) // app.js // import full module const _ = require('./loDash') _.concat([1], [2], [3]) // loDash.js const loDash = { /* ... */ } module.exports = loDash CommonJSCommonJS @loige 50
  • 75. // or import single functionality const { concat } = require('./loDash') concat([1], [2], [3]) // app.js // import full module const _ = require('./loDash') _.concat([1], [2], [3]) // loDash.js const loDash = { /* ... */ } module.exports = loDash CommonJSCommonJS module @loige 50
  • 76. // or import single functionality const { concat } = require('./loDash') concat([1], [2], [3]) // app.js // import full module const _ = require('./loDash') _.concat([1], [2], [3]) // loDash.js const loDash = { /* ... */ } module.exports = loDash CommonJSCommonJS module app using module @loige 50
  • 77. // or import single functionality const { concat } = require('./loDash') concat([1], [2], [3]) // app.js // import full module const _ = require('./loDash') _.concat([1], [2], [3]) // loDash.js const loDash = { /* ... */ } module.exports = loDash CommonJSCommonJS module app using module @loige 50
  • 78. // or import single functionality const { concat } = require('./loDash') concat([1], [2], [3]) // app.js // import full module const _ = require('./loDash') _.concat([1], [2], [3]) // loDash.js const loDash = { /* ... */ } module.exports = loDash CommonJSCommonJS module app using module @loige 50
  • 79. CommonJSCommonJS No naming collisions (imported modules can be renamed) Huge repository of modules through   Synchronous import only Works natively on the server side only (Node.js) NPM @loige 51
  • 80. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // jquery-1.9.0.js define( 'jquery', ['sizzle', 'jqueryUI'], function (sizzle, jqueryUI) { // Returns the exported value return function () { // ... } } ) @loige 52
  • 81. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // jquery-1.9.0.js define( 'jquery', ['sizzle', 'jqueryUI'], function (sizzle, jqueryUI) { // Returns the exported value return function () { // ... } } ) module @loige 52
  • 82. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // jquery-1.9.0.js define( 'jquery', ['sizzle', 'jqueryUI'], function (sizzle, jqueryUI) { // Returns the exported value return function () { // ... } } ) module module name @loige 52
  • 83. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // jquery-1.9.0.js define( 'jquery', ['sizzle', 'jqueryUI'], function (sizzle, jqueryUI) { // Returns the exported value return function () { // ... } } ) module dependencies @loige 52
  • 84. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // jquery-1.9.0.js define( 'jquery', ['sizzle', 'jqueryUI'], function (sizzle, jqueryUI) { // Returns the exported value return function () { // ... } } ) module factory function used to construct the module, receives the dependencies as arguments @loige 52
  • 85. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // jquery-1.9.0.js define( 'jquery', ['sizzle', 'jqueryUI'], function (sizzle, jqueryUI) { // Returns the exported value return function () { // ... } } ) module exported value @loige 52
  • 86. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // app.js // define paths requirejs.config({ baseUrl: 'js/lib', paths: { jquery: 'jquery-1.9.0' } }) define(['jquery'], function ($) { // this is executed only when jquery // and its deps are loaded }); @loige 53
  • 87. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // app.js // define paths requirejs.config({ baseUrl: 'js/lib', paths: { jquery: 'jquery-1.9.0' } }) define(['jquery'], function ($) { // this is executed only when jquery // and its deps are loaded }); app @loige 53
  • 88. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // app.js // define paths requirejs.config({ baseUrl: 'js/lib', paths: { jquery: 'jquery-1.9.0' } }) define(['jquery'], function ($) { // this is executed only when jquery // and its deps are loaded }); app Require.js config jquery will be loaded from ://<currentDomain>/js/lib/jquery-1.9.0.js @loige 53
  • 89. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js // app.js // define paths requirejs.config({ baseUrl: 'js/lib', paths: { jquery: 'jquery-1.9.0' } }) define(['jquery'], function ($) { // this is executed only when jquery // and its deps are loaded }); app app main function Has jquery as dependency @loige 53
  • 90. AMD (AMD ( )) Asynchronous Module DefinitionAsynchronous Module Definition Require.jsRequire.js Asynchronous modules Works on Browsers and Server side   Very verbose and convoluted syntax (my opinion™) @loige 54
  • 91. UMDUMD Universal Module DefinitionUniversal Module Definition A module definition that is compatible with Global modules, CommonJS & AMD    github.com/umdjs/umd @loige 55 . 1
  • 92. (function (root, factory) { if (typeof exports === 'object') { // CommonJS module.exports = factory(require('dep')) } else if (typeof define === 'function' && define.amd) { // AMD define(['dep'], function (dep) { return (root.returnExportsGlobal = factory(dep)) }) } else { // Global Variables root.myModule = factory(root.dep) } }(this, function (dep) { // Your actual module return {} })) loige.link/umd@loige 55 . 2
  • 93. (function (root, factory) { if (typeof exports === 'object') { // CommonJS module.exports = factory(require('dep')) } else if (typeof define === 'function' && define.amd) { // AMD define(['dep'], function (dep) { return (root.returnExportsGlobal = factory(dep)) }) } else { // Global Variables root.myModule = factory(root.dep) } }(this, function (dep) { // Your actual module return {} })) loige.link/umd IIFE with arguments:  - Current scope (this) and the module factory function.  - "dep" is a sample dependency of the module. @loige 55 . 2
  • 94. (function (root, factory) { if (typeof exports === 'object') { // CommonJS module.exports = factory(require('dep')) } else if (typeof define === 'function' && define.amd) { // AMD define(['dep'], function (dep) { return (root.returnExportsGlobal = factory(dep)) }) } else { // Global Variables root.myModule = factory(root.dep) } }(this, function (dep) { // Your actual module return {} })) loige.link/umd@loige 55 . 2
  • 95. (function (root, factory) { if (typeof exports === 'object') { // CommonJS module.exports = factory(require('dep')) } else if (typeof define === 'function' && define.amd) { // AMD define(['dep'], function (dep) { return (root.returnExportsGlobal = factory(dep)) }) } else { // Global Variables root.myModule = factory(root.dep) } }(this, function (dep) { // Your actual module return {} })) loige.link/umd@loige 55 . 2
  • 96. (function (root, factory) { if (typeof exports === 'object') { // CommonJS module.exports = factory(require('dep')) } else if (typeof define === 'function' && define.amd) { // AMD define(['dep'], function (dep) { return (root.returnExportsGlobal = factory(dep)) }) } else { // Global Variables root.myModule = factory(root.dep) } }(this, function (dep) { // Your actual module return {} })) loige.link/umd@loige 55 . 2
  • 97. Allows you to define modules that can be used by almost any module loader   Complex, the wrapper code is almost impossible to write manually UMDUMD Universal Module DefinitionUniversal Module Definition @loige 55 . 3
  • 98. ES2015 modulesES2015 modules Cool & broad subject, it would deserve it's own talk Wanna know more? /  syntax referenceimport export ECMAScript modules in browsers ES modules: A cartoon deep-dive ES Modules in Node Today! @loige 56 . 1
  • 99. // calculator.js const add = (num1, num2) => num1 + num2 const sub = (num1, num2) => num1 - num2 const div = (num1, num2) => num1 / num2 const mul = (num1, num2) => num1 * num2 export { add, sub, div, mul } // app.js import { add } from './calculator' console.log(add(2,2)) // 4 ES2015 modulesES2015 modules @loige 56 . 2
  • 100. // calculator.js const add = (num1, num2) => num1 + num2 const sub = (num1, num2) => num1 - num2 const div = (num1, num2) => num1 / num2 const mul = (num1, num2) => num1 * num2 export { add, sub, div, mul } // app.js import { add } from './calculator' console.log(add(2,2)) // 4 ES2015 modulesES2015 modules module @loige 56 . 2
  • 101. // calculator.js const add = (num1, num2) => num1 + num2 const sub = (num1, num2) => num1 - num2 const div = (num1, num2) => num1 / num2 const mul = (num1, num2) => num1 * num2 export { add, sub, div, mul } // app.js import { add } from './calculator' console.log(add(2,2)) // 4 ES2015 modulesES2015 modules moduleexported functionalities @loige 56 . 2
  • 102. // calculator.js const add = (num1, num2) => num1 + num2 const sub = (num1, num2) => num1 - num2 const div = (num1, num2) => num1 / num2 const mul = (num1, num2) => num1 * num2 export { add, sub, div, mul } // app.js import { add } from './calculator' console.log(add(2,2)) // 4 ES2015 modulesES2015 modules module app @loige 56 . 2
  • 103. // calculator.js const add = (num1, num2) => num1 + num2 const sub = (num1, num2) => num1 - num2 const div = (num1, num2) => num1 / num2 const mul = (num1, num2) => num1 * num2 export { add, sub, div, mul } // app.js import { add } from './calculator' console.log(add(2,2)) // 4 ES2015 modulesES2015 modules module app import specific functionality @loige 56 . 2
  • 104. // index.html <html> <body> <!-- ... --> <script type="module"> import { add } from 'calculator.js' console.log(add(2,2)) // 4 </script> </body> </html> ES2015 modulesES2015 modules @loige 56 . 3
  • 105. // index.html <html> <body> <!-- ... --> <script type="module"> import { add } from 'calculator.js' console.log(add(2,2)) // 4 </script> </body> </html> ES2015 modulesES2015 modules "works" in some modern browsers @loige 56 . 3
  • 106. ES2015 modulesES2015 modules Syntactically very similar to CommonJS... BUT import & export are static (allow static analysis of dependencies)   It is a (still work in progress) standard format   Works (almost) seamlessly in browsers & servers @loige 56 . 4
  • 107. So many options...So many options... Current most used practice: Use CommonJS or ES2015 & create "compiled bundles" @loige 57
  • 108. 1. Why we need modules 2. JavaScript module systems 3. How a module bundler works 4. Webpack in 2 minutes! 5. Advanced module bundling AgendaAgenda @loige 58
  • 109. Let's try to use CommonJSLet's try to use CommonJS in the browserin the browser @loige 59
  • 110. const $ = require('zepto') const tippy = require('tippy.js') const UUID = require('uuidjs') const { confetti } = require('dom-confetti/src/main') const store = require('store2') const Favico = require('favico.js') !(function () { const colors = ['#a864fd', '#29cdff', '#78ff44', '#ff718d', '#fdff6a'] const todoApp = (rootEl, opt = {}) => { const todos = opt.todos || [] let completedTasks = opt.completedTasks || 0 const onChange = opt.onChange || (() => {}) const list = rootEl.find('.todo-list') const footer = rootEl.find('.footer') const todoCount = footer.find('.todo-count') const insertInput = rootEl.find('.add-todo-box input') const insertBtn = rootEl.find('.add-todo-box button') const render = () => { let tips list.html('') The browser doesn't know how to process require. It doesn't support CommonJS! @loige 60
  • 111. Module BundlerModule Bundler A tool that takes modules with dependencies and emits static assets representing those modules   Those static assets can be processed by browsers! @loige 61
  • 112. Dependency graphDependency graph A graph built by connecting every module with its direct dependencies. app dependency A dependency B dependency A2 shared dependency @loige 62
  • 113. A module bundler has to:A module bundler has to: Construct the dependency graph (Dependency Resolution) Assemble the modules in the graph into a single executable asset (Packing) @loige 63
  • 114. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution 64@loige
  • 115. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution app 64 (entrypoint) (1) @loige
  • 116. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution app calculator 64 (entrypoint) (1) @loige
  • 117. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution app calculator 64 (entrypoint) (1) (2) @loige
  • 118. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution app calculator parser 64 (entrypoint) (1) (2) @loige
  • 119. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution app calculator parser 64 (entrypoint) (1) (2) (3) @loige
  • 120. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution app calculator parser resolver 64 (entrypoint) (1) (2) (3) @loige
  • 121. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution app calculator parser resolver 64 (entrypoint) (1) (2) (3) (4) @loige
  • 122. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution app calculator log parser resolver 64 (entrypoint) (1) (2) (3) (4) @loige
  • 123. // app.js const calculator = require('./calculator') const log = require('./log') log(calculator('2 + 2 / 4')) // log.js module.exports = console.log // calculator.js const parser = require('./parser') const resolver = require('./resolver') module.exports = (expr) => resolver(parser(expr)) // parser.js module.exports = (expr) => { /* ... */ } // resolver.js module.exports = (tokens) => { /* ... */ } Dependency resolutionDependency resolution app calculator log parser resolver 64 (entrypoint) (1) (2) (3) (4) (5) @loige
  • 124. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map @loige 65
  • 125. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  @loige 65
  • 126. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, @loige 65
  • 127. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, './calculator': (module, require) => { … }, @loige 65
  • 128. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, './calculator': (module, require) => { … }, './parser': (module, require) => { … }, @loige 65
  • 129. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, './calculator': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … }, @loige 65
  • 130. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … }, @loige 65
  • 131. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … }, require path @loige 65
  • 132. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … }, module factory function @loige 65
  • 133. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … }, const parser = require('./parser');const resolver =  require('./resolver');module.exports = (expr) =>  resolver(parser(expr))@loige 65
  • 134. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … }, const parser = require('./parser');const resolver =  require('./resolver');module.exports = (expr) =>  resolver(parser(expr))@loige 65
  • 135. DuringDuring dependency resolutiondependency resolution,, the bundler creates athe bundler creates a modules mapmodules map {                }  './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … }, const parser = require('./parser');const resolver =  require('./resolver');module.exports = (expr) =>  resolver(parser(expr))@loige 65
  • 139. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) 67 @loige
  • 140. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) IIFE passing the modules map as argument 67 @loige
  • 141. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) Custom require function: it will load the modules by evaluating the code from the modules map 67 @loige
  • 142. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) A reference to a module with an empty module.exports.  This will be filled at evaluation time 67 @loige
  • 143. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) Invoking the factory function for the given module name. (Service locator pattern) 67 @loige
  • 144. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) The current reference module is passed, the factory function will modify this object by adding the proper exported values. 67 @loige
  • 145. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) The custom require function is passed so, modules can recursively require other modules 67 @loige
  • 146. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) The resulting module.exports is returned 67 @loige
  • 147. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) The entrypoint module is required, triggering the actual execution of the business logic 67 @loige
  • 148. Packed executable filePacked executable file ((modulesMap) => { const require = (name) => { const module = { exports: {} } modulesMap[name](module, require) return module.exports } require('./app') })( { './app': (module, require) => { … }, './calculator': (module, require) => { … }, './log': (module, require) => { … }, './parser': (module, require) => { … }, './resolver': (module, require) => { … } } ) 67 @loige
  • 149. Now you know howNow you know how Module bundlers work!Module bundlers work!    And how to convert code writtenAnd how to convert code written usingusing CommonJSCommonJS to a single file thatto a single file that works in the browserworks in the browser @loige 68
  • 150. A challenge for you!A challenge for you! If you do, ... I'll have a prize for you!   TIP: you can use  or  to parse JavaScript files (look for require and module.exports) and to map relative module paths to actual files in the filesystem.   Need an inspiration? Check the awesome ! let me know acorn babel-parser resolve minipack Can you build a (simple) module bundler from scratch?Can you build a (simple) module bundler from scratch? @loige 69
  • 151. 1. Why we need modules 2. JavaScript module systems 3. How a module bundler works 4. Webpack in 2 minutes! 5. Advanced module bundling AgendaAgenda @loige 70
  • 152. A state of the art moduleA state of the art module bundler for the webbundler for the web @loige 71
  • 154. webpack app.js yep, recent versions of Webpack work without config! @loige 73
  • 155. webpack ­­mode=development app.js Do not compress the code and add annotations! @loige 74
  • 157. Webpack conceptsWebpack concepts Entry point: the starting file for dependency resolution. Output: the destination file (bundled file). Loaders: algorithms to parse different file types and convert them into executable javascript (e.g. babel, typescript, but also CSS, images or other static assets) Plugins: do extra things (e.g. generate a wrapping HTML or analysis tools) @loige 76
  • 158. const { resolve, join } = require('path') const CompressionPlugin = require('compression-webpack-plugin') module.exports = { entry: './app.js', output: { path: resolve(join(__dirname, 'build')), filename: 'app.js' }, module: { rules: [ { test: /.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-env'] ] } } } ] }, plugins: [ new CompressionPlugin() ] } Webpack.config.js @loige77
  • 159. const { resolve, join } = require('path') const CompressionPlugin = require('compression-webpack-plugin') module.exports = { entry: './app.js', output: { path: resolve(join(__dirname, 'build')), filename: 'app.js' }, module: { rules: [ { test: /.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-env'] ] } } } ] }, plugins: [ new CompressionPlugin() ] } Webpack.config.js Entrypoint Build the dependency graph starting from ./app.js @loige77
  • 160. const { resolve, join } = require('path') const CompressionPlugin = require('compression-webpack-plugin') module.exports = { entry: './app.js', output: { path: resolve(join(__dirname, 'build')), filename: 'app.js' }, module: { rules: [ { test: /.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-env'] ] } } } ] }, plugins: [ new CompressionPlugin() ] } Webpack.config.js Output Save the resulting bundled file in ./build/app.js @loige77
  • 161. const { resolve, join } = require('path') const CompressionPlugin = require('compression-webpack-plugin') module.exports = { entry: './app.js', output: { path: resolve(join(__dirname, 'build')), filename: 'app.js' }, module: { rules: [ { test: /.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-env'] ] } } } ] }, plugins: [ new CompressionPlugin() ] } Webpack.config.js Loaders All the files matching "*.js" are processed with babel and converted to ES5 Javascript @loige77
  • 162. const { resolve, join } = require('path') const CompressionPlugin = require('compression-webpack-plugin') module.exports = { entry: './app.js', output: { path: resolve(join(__dirname, 'build')), filename: 'app.js' }, module: { rules: [ { test: /.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: [ ['@babel/preset-env'] ] } } } ] }, plugins: [ new CompressionPlugin() ] } Webpack.config.js Plugins Uses a plugin that generates a gzipped copy of every emitted file. @loige77
  • 163. Everything is a moduleEverything is a module import React, { Component } from 'react' import logo from './logo.svg' import './App.css' class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to React</h1> </header> </div> ); } } export default App 78
  • 164. Everything is a moduleEverything is a module import React, { Component } from 'react' import logo from './logo.svg' import './App.css' class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to React</h1> </header> </div> ); } } export default App 78
  • 165. Everything is a moduleEverything is a module import React, { Component } from 'react' import logo from './logo.svg' import './App.css' class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to React</h1> </header> </div> ); } } export default App 78
  • 166. Everything is a moduleEverything is a module import React, { Component } from 'react' import logo from './logo.svg' import './App.css' class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to React</h1> </header> </div> ); } } export default App 78
  • 167. Webpack can load any type of fileWebpack can load any type of file As long as you specify a "As long as you specify a "loaderloader" that tells" that tells how to convert the file into something thehow to convert the file into something the browser understands.browser understands. This is how Webpack allows you to use Babel, TypeScript, Clojure, Elm but also to load CSSs, Images and other assets. 79
  • 168. { test: /.css$/, use: [ require.resolve('style-loader'), { loader: require.resolve('css-loader'), options: { importLoaders: 1, }, }, { loader: require.resolve('postcss-loader'), options: { ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', 80
  • 169. { test: /.css$/, use: [ require.resolve('style-loader'), { loader: require.resolve('css-loader'), options: { importLoaders: 1, }, }, { loader: require.resolve('postcss-loader'), options: { ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // Defines how to load .css files (uses a pipeline of loaders) 80
  • 170. { test: /.css$/, use: [ require.resolve('style-loader'), { loader: require.resolve('css-loader'), options: { importLoaders: 1, }, }, { loader: require.resolve('postcss-loader'), options: { ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // Defines how to load .css files (uses a pipeline of loaders) // parses the file with post-css 80
  • 171. { test: /.css$/, use: [ require.resolve('style-loader'), { loader: require.resolve('css-loader'), options: { importLoaders: 1, }, }, { loader: require.resolve('postcss-loader'), options: { ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // Defines how to load .css files (uses a pipeline of loaders) // parses the file with post-css // process @import and url() // statements 80
  • 172. { test: /.css$/, use: [ require.resolve('style-loader'), { loader: require.resolve('css-loader'), options: { importLoaders: 1, }, }, { loader: require.resolve('postcss-loader'), options: { ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // Defines how to load .css files (uses a pipeline of loaders) // parses the file with post-css // process @import and url() // statements // inject the resulting code with a <style> tag 80
  • 173. ...Webpack can do (a lot) more!...Webpack can do (a lot) more! Dev ServerDev Server Tree shakingTree shaking Dependencies analyticsDependencies analytics Source mapsSource maps Async require / module splittingAsync require / module splitting @loige 81
  • 174. 1. Why we need modules 2. JavaScript module systems 3. How a module bundler works 4. Webpack in 2 minutes! 5. Advanced module bundling AgendaAgenda @loige 82
  • 175. Webpack inWebpack in create-react-appcreate-react-app yarn global add create-react-app create-react-app newapp cd newapp yarn yarn eject cat ./config/webpack.config.{dev,prod}.js 83
  • 177. Webpack is notWebpack is not the only possibility!the only possibility! 85
  • 178. 1. Why we need modules 2. JavaScript module systems 3. How a module bundler works 4. Webpack in 2 minutes! 5. Advanced module bundling AgendaAgenda @loige 86
  • 179. Module bundlers are your friendsModule bundlers are your friends Now you know how they work, they are not (really) magic! Start small and add more when needed If you try to build your own you'll learn a lot more! @loige 87
  • 180. THANKS!THANKS! loige.link/bundle-dublinjs      Special thanks , , , (reviewers) and  (inspirations: his and his ) @Podgeypoos79 @andreaman87 @mariocasciaro @eugenserbanescu @MarijnJH amazing book workshop on JS modules @loige Images by .Streamline Emoji pack 88