The Era of Module Bundlers - GDG Dev Fest Delhi 2017

The Era of Module Bundlers - GDG Dev Fest Delhi 2017

This talk will walk everyone through the concept and practical usage of JavaScript module bundling and optimisation. With the emergence of advanced bundling tools like Webpack, the JavaScript ecosystem has been enriched with the right set of processes and tools required for creating production-ready builds, which is what this talk aims at covering.
This talk will also cover essential differences between task runners and bundlers with focus on advanced optimisation techniques like Tree shaking and Code splitting.

C00289a7b57c00bb0ab55d5e04cc3345?s=128

Arun Michael Dsouza

October 29, 2017
Tweet

Transcript

  1. THE ERA OF MODULE BUNDLERS Arun Michael Dsouza Software Engineer,

    AdPushup Inc. github.com/arunmichaeldsouza twitter.com/amdsouza92 1
  2. Arun Michael Dsouza New Delhi, India 2

  3. THE ERA OF MODULE BUNDLERS https://icons8.com/icon/45069/module 3 Image source :

  4. JAVASCRIPT MODULES 4

  5. MAINTAINABILITY REUSABILITY EASE OF TESTING 5 JavaScript Modules

  6. MODULE SYSTEMS IN JAVASCRIPT 6

  7. Immediately Invoked Function Expression 7 (function() { // Module code

    }); Module Systems in JavaScript
  8. bit.ly/block-scoping-es6 8 (function() { // Module code }); { //

    Module code } Module Systems in JavaScript
  9. Object Interface bit.ly/design-patterns-javascript 9 var math = (function() { return

    { sum: function() { // Method code }, product: function() { // Method code } }; })(); Module Systems in JavaScript
  10. AMD COMMON JS 10 Module Systems in JavaScript

  11. AMD app.js 11 define(['math', 'data'], function(math, data) { return math.sum(2,

    3); }); Module Systems in JavaScript
  12. AMD math.js 12 define([], function() { return { sum: function()

    { // Method code }, product: function() { // Method code } }; }); Module Systems in JavaScript
  13. COMMON JS math.js 13 var math = { sum: function()

    { // Method code }, product: function() { // Method code } }; module.exports = math; Module Systems in JavaScript
  14. COMMON JS app.js 14 var math = require('./math'); var value

    = math.sum(2, 3); Module Systems in JavaScript
  15. MODULE LOADERS Module Loader AMD Common JS 15 https://github.com/alrra/browser-logos Image

    source :
  16. Common JS / AMD Module Loader REQUIRE JS AMD Module

    Loader bit.ly/require-js bit.ly/system-js SYSTEM JS 16 Module Loaders
  17. bit.ly/require-js-examples 17 <!DOCTYPE html> <html> <head> <title>Page 1</title> <script data-main="js/page1"

    src="js/lib/require.js"></script> </head> <body> </body> </html> Module Loaders
  18. 18 Module Loaders

  19. 19 Module Loaders

  20. MODULE BUNDLING Module Bundler Bundle Modules .css .js .js .png

    .scss 20 https://github.com/voodootikigod/logo.js/ Image source :
  21. HOW DO MODULE BUNDLERS WORK ? index.js data.js math.js api.js

    model.js db.js sql.js unit.js constants.js jsm.js Dependency Graph 21 Module Bundling
  22. BROWSERIFY NPM modules on the browser side! Yay! 22 https://github.com/substack/browserify-website

    Image source : Intro to Browserify
  23. 23 http://bit.ly/mind-blown-gif Image source : Intro to Browserify

  24. INSTALLATION > npm install -g browserify USAGE > browserify app.js

    -o bundle.js 24 Intro to Browserify
  25. TRANSFORMS Babelify ES6 ES5 http://bit.ly/browserify-transforms 25 https://github.com/substack/browserify-website Image source :

    Intro to Browserify
  26. USING TRANSFORMS > browserify app.js -o bundle.js -t [ babelify

    --presets [ es2015 ] ] 26 Intro to Browserify
  27. TASK RUNNERS 27

  28. 28 grunt.initConfig({ watchFiles: { // Watcher task }, browserify: {

    // Module bundling task }, minifyCss: { // CSS optimisation task }, optimiseImages: { // Image optimisation task }, uploadOnCDN: { // Deployment task } }); Task Runners
  29. BABELIFY TRANSFORM > npm install grunt grunt-browserify babelify babel- preset-es2015

    —save-dev 29 Task Runners
  30. WEBPACK 30 https://webpack.github.io/ Image source : Intro to Webpack

  31. INSTALLATION > npm install -g webpack USAGE > webpack app.js

    bundle.js 31 Intro to Webpack
  32. WEBPACK CONFIG FILE 32 module.exports = { entry: './app.js', output:

    { filename: './bundle.js' } }; Intro to Webpack
  33. 33 https://npm-stat.com/ Image source : Intro to Webpack

  34. LOADERS Transform code from one form to another that is

    part of the bundle PLUGINS Act on the bundle or bundle chunks for customisation and optimisation 34 Intro to Webpack
  35. BUNDLE OPTIMISATION WITH WEBPACK 35

  36. BUNDLE ANALYSIS 36 Bundle Optimisation with Webpack

  37. WEBPACK BUNDLE ANALYZERS http://bit.ly/webpack-bundle-analyzer http://bit.ly/webpack-chart http://bit.ly/webpack-visualizer NPM Module Web-based Analysers

    37 Bundle Optimisation with Webpack
  38. WEBPACK BUNDLE ANALYZER plugins: [ new BundleAnalyzerPlugin( ) ] 38

    plugins: [ new BundleAnalyzerPlugin() ] Bundle Optimisation with Webpack
  39. plugins: [ new BundleAnalyzerPlugin( ) ] 39 Bundle Optimisation with

    Webpack
  40. WEB-BASED BUNDLE ANALYZERS > webpack --profile --json > stats.json 40

    Bundle Optimisation with Webpack
  41. PRODUCTION READY BUNDLE 41 Bundle Optimisation with Webpack

  42. 42 Bundle Optimisation with Webpack

  43. UGLIFICATION 43 plugins: [ new webpack.optimize.UglifyJsPlugin() ] Bundle Optimisation with

    Webpack
  44. 44 Bundle Optimisation with Webpack

  45. NODE ENVIRONMENT VARIABLE 45 plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production')

    }) ] Bundle Optimisation with Webpack
  46. 46 Bundle Optimisation with Webpack

  47. WEBPACK PRODUCTION FLAG > webpack -p 47 Bundle Optimisation with

    Webpack
  48. CSS MINIFICATION 48 > npm install css-loader —save-dev Bundle Optimisation

    with Webpack
  49. 49 Bundle Optimisation with Webpack

  50. CSS MINIFICATION 50 ... module: { loaders: [ { test:

    /\.css?$/, loader: 'css-loader', options: { minimize: true } } ] }, ... Bundle Optimisation with Webpack
  51. 51 Bundle Optimisation with Webpack

  52. CSS EXTRACTION/ CSS CODE SPLITTING 52 > npm install —save-dev

    extract-text-webpack-plugin Bundle Optimisation with Webpack
  53. 53 ... module: { loaders: [ { test: /\.css?$/, use:

    ExtractTextPlugin.extract({ use: [{ loader: 'css-loader', options: { minimize: true } }] }) } ] }, plugins: [ new ExtractTextPlugin('./build/styles.min.css'), ] CSS EXTRACTION/ CSS CODE SPLITTING Bundle Optimisation with Webpack
  54. 54 Bundle Optimisation with Webpack

  55. BUILD-TIME GZIPPING 55 Bundle Optimisation with Webpack

  56. DYNAMIC GZIPPING 56 var compression = require('compression'); app.use(compression()); Bundle Optimisation

    with Webpack
  57. BUILD-TIME GZIPPING > npm install compression-webpack-plugin --save-dev http://bit.ly/webpack-compression-plugin 57 Bundle

    Optimisation with Webpack
  58. 58 app.get('*.js', function(req, res, next) { req.url = req.url +

    '.gz'; res.set('Content-Encoding', 'gzip'); next(); }); Bundle Optimisation with Webpack
  59. TREE SHAKING Dead Code Elimination Works with ES2015 Modules 59

    Bundle Optimisation with Webpack
  60. math.js 60 const sum = (a, b) => a +

    b; const product = (a, b) => a * b; export { sum, product }; Bundle Optimisation with Webpack
  61. app.js 61 import { sum } from './math'; const value

    = sum(2,3); console.log(value); Bundle Optimisation with Webpack
  62. babel-loader babel-plugin-transform-es2015-modules-commonjs 62 Bundle Optimisation with Webpack

  63. ES2015 MODULES (STATIC STRUCTURE) Can be tree-shaken COMMON JS &

    OTHERS (DYNAMIC STRUCTURE) Cannot be tree-shaken 63 Bundle Optimisation with Webpack
  64. 64 "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var

    sum = function sum(a, b) { return a + b; }; var product = function product(a, b) { return a * b; }; exports.sum = sum; exports.product = product; Bundle Optimisation with Webpack
  65. HOW TREE SHAKING WORKS Babel-loader ES6 65 Bundle Optimisation with

    Webpack Minifier With { modules: false } option ES5 Tree-shaken code ES5 Code with unused exports
  66. 66 … module: { loaders: [ { test: /\.jsx?$/, loader:

    'babel-loader', query: { presets: [['es2015', { modules: false }]] } } ] }, … Bundle Optimisation with Webpack
  67. 67 "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a",

    function() { return sum; }); /* unused harmony export product */ var sum = function sum(a, b) { return a + b; }; var product = function product(a, b) { return a * b; }; Bundle Optimisation with Webpack
  68. 68 "use strict"; n.d(t, "a", function() { return r });

    // Only sum method exported var r = function(e, t) { return e + t } Bundle Optimisation with Webpack
  69. CODE SPLITTING bundle.js styles.css page1.js page2.js 69 Bundle Optimisation with

    Webpack
  70. CSS CODE SPLITTING App code with styles Separate CSS bundle

    css-loader Bundle with processed CSS ExtractTextWebpackPlugin 70 Bundle Optimisation with Webpack
  71. CODE SPLITTING LIBRARIES bundle.js JQuery Lodash App Code vendor.js JQuery

    Lodash bundle.js App Code 71 Bundle Optimisation with Webpack
  72. index.js product.js 72 import $ from 'jquery'; // index.js code

    import $ from 'jquery'; // product.js code Bundle Optimisation with Webpack
  73. plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: 2 }) ]

    COMMON CHUNKS PLUGIN http://bit.ly/common-chunks-plugin 73 Bundle Optimisation with Webpack
  74. 74 Bundle Optimisation with Webpack

  75. IMPLICIT COMMON VENDOR CHUNK 75 plugins: [ new webpack.optimize.CommonsChunkPlugin({ name:

    'vendor', minChunks: function (module) { return module.context && module.context.indexOf('node_modules') !== -1; } }) ] Bundle Optimisation with Webpack
  76. AUTOMATIC SPLITTING 76 import header from 'header'; import slider from

    'slider'; require.ensure(['./productList'], function(require) { require('./productList'); }); Bundle Optimisation with Webpack
  77. 77 Bundle Optimisation with Webpack

  78. 78 <Route path="/product" getComponent={(location, callback) => { require.ensure([], require =>

    { callback(null, require('./productPage')) }) }}/> Bundle Optimisation with Webpack
  79. ES6 MODULES 79 ES6 Modules const sum = (a, b)

    => a + b; export default sum; import sum from './sum'; bit.ly/state-of-js-modules
  80. THE ERA OF MODULE BUNDLERS 80 THANK YOU Arun Michael

    Dsouza Software Engineer, AdPushup Inc. github.com/arunmichaeldsouza twitter.com/amdsouza92