Wrapping your js
Making your scripts digestible for the browser
Maurizio Lupo (@sithmel)
Global namespace
Browser Javascript
Different scripts communicate using the
wrap the scope using a closure, but only within the same script
Browser Javascript
Javascript allows to
It is not always updated
(we currently support es5)
Browser Javascript
Browser Javascript
Issues:
Polluting global scope
Bundle more modules together
Provide old browser compatibility
Bundling
First solution: wrap a group of scripts within a closure
(function () {
... script1 ...
... script2 ...
... script3 ...
...
}());
Bundling
AMD
define('react', function () {
...
return react;
});
define('jquery', function () {
...
return $;
});
define('myapp', ['jquery', 'react'], function ($, react) {
...
});
Can run natively in the browser (horribly slow)
To fix performance uses bundling step
Bundling
commonjs
--- react.js
...
module.exports = react;
--- file jquery.js
...
module.exports = jquery;
--- file app.js
var jquery = require('jquery');
var react = require('react');
...
Can't run natively in the browser
Rely on a bundling step
Cross compatible with node.js
Bundling
commonjs
var _get = require('lodash/get');
Allows to cherry pick what you need!
Please do not import a gorilla to get a banana
Bundling
ES2015 modules
--- react.js
...
export default react;
--- file jquery.js
...
export default jquery;
--- file app.js
import jquery from 'jquery';
import react from 'react';
...
Can't run natively in the browser
Rely on a bundling step
Can be transpiled to common.js
Its semantic allows "treeshaking" (with webpack 2 and rollup)
How it works: Browserify
A loader is inserted in each bundle
Every module is wrapped within a closure
If a module rely on any node.js feature, this is added: __dirname, process, buffer etc.
Compatible with commonjs: ES2015 must be converted by babel
How it works: Browserify
The module is happended to a object
The keys of the object are the name or path in the require
if you use the "fullPath" option the keys are absolute paths (very bad)
If you use the bundle-collapser module keys are converted in integers
How it works: Browserify
if you use the "debug" option, sourcemaps are appended to the file
How it works: Webpack 2
A loader is inserted in each bundle
Every module is wrapped within a closure
If a module rely on any node.js feature, this is added: __dirname, process, buffer etc.
Compatible with AMD, commonjs, ES2015
How it works: Webpack 2
Modules are happended to a object
The keys of the object is a number
Any non js require is treated accordingly to its loader
How it works: Webpack 2
Using ES2015 imports, unused modules are stripped (treeshaking)
But you have to configure babel to not transpile es2015 modules:
presets: [['es2015', {modules: false}], 'react']
How it works: Webpack 2
What about third party modules?
You have to add the module field to the package.json
{
"name": "my-package",
"version": "0.1.0",
"main": "dist/my-package.umd.js",
"module": "dist/my-package.es2015.js"
}
How it works: Rollup
No loader required
No closures, it renames conflicting variables
If a module rely on any node.js feature, this is added: __dirname, process, buffer etc. (work in progress)
A bit immature but:
Treeshaking is similar to webpack
It uses ES2015 natively and requires a plugin for commonjs
Second part: transpilation
Babel
Transpilation
const a = 10;
To
From
var a = 10;
It only requires the appropriate preset
For ES use babel-preset-env
Babel
Polyfilling
babel-polyfill.js
It includes:
polyfills in the global namespace
Regenerator runtime: used in conjunction with transpiled generators
It throws an exception if imported more than once and it is massive!!!
Babel
Polyfilling
runtime-transform
It is a plugin and includes:
polyfills in the private namespace (core-js)
Regenerator runtime: used in conjunction with transpiled generators
It doesn't include polyfills for existing built-ins: .includes .contains etc.
Babel
Polyfilling
core-js
It is a collection of polyfills, they can be cherry picked
regenerator-runtime
for using generators
Babel
babel-preset-env has a plugin to automatically import individual corejs imports as required by target environment!
Always check what you are importing:
- does it need a global polyfill? (axios)
- does it need transpiling?
Be careful to import a module designed for the server:
- does it uses commonjs or es2015?
- does it need transpiling?
- is it importing more than necessary?
Checklist
Thanks!
Wrapping your js
By Maurizio Lupo
Wrapping your js
Making your script digestible for the browser
- 461