Skip to content

Instantly share code, notes, and snippets.

@rcanepa
Last active June 21, 2017 23:53
Show Gist options
  • Select an option

  • Save rcanepa/0447cccb38d6bc8434b5c60431aa5d58 to your computer and use it in GitHub Desktop.

Select an option

Save rcanepa/0447cccb38d6bc8434b5c60431aa5d58 to your computer and use it in GitHub Desktop.
How Webpack actually works

Notes from Webpack: It's Not Magic | Naomi Jacobs | BuzzJS 2.0 2017

https://www.youtube.com/watch?v=_QEM9kdV-b0&feature=youtu.be

Start

Webpack takes a path to a single starting file (entry file)

Webpack has 4 main steps:

  1. Find dependent files
  2. Apply loaders
  3. Implement module system
  4. Create final asset

1. Find dependent files

1.1 Make an array of all dependent files -> [] 1.2 Start the array with the entry file -> [ef] 1.3 Get dependent files from 'import' and 'require' statements 1.4 For each dependency, validate its path (must lead to a npm module or a file) 1.5 Add dependent files to the array -> [ef, dp1, dp2, ..., dpn]

2. Apply loaders (they take code, make transformations and return code)

  • They can be found on NPM
  • How are they used?
    • Must be configured on the webpack config file
    • The developer has to define on which files webpack must apply them (the loaders)
      • E.g: apply the loader on typescript files to convert them to plain javascript
    • They can be chained together and the developer must define the order in which they are applied

3. Implement module system

  • CommonJS allow files to declare dependencies between them throughout import and export statements
  • CommonJS is a standard, not a library
  • Webpack makes the module system work (e.g. CommonJS) by implementing the standard

An Example

  • Two files: hypotenuse.js and square.js

square.js:

module.exports = function(x) {
  return x * x;
};

hypotenuse.js:

var square = require('./square');
module.exports = function(a, b) {
  return square(a) + square(b);
};

Webpack wrap them with a function, which receives two arguments: module and webpackRequire

square.js:

function(module, webpackRequire) {
  module.exports = function(x) {
    return x * x;
  };
}; 

hypotenuse.js:

function(module, webpackRequire) {
  var square = require('./square');
  module.exports = function(a, b) {
    return square(a) + square(b);
  };
};

The array of dependent files should look like this: [hypotenuse.js, square.js]

After that, Webpack replace all require statements in the following way:

require('./square') -> webpackRequire(IndexOfSquareJsFile)

Where IndexOfSquareJsFile is the position of that file in the dependent files array (1 in this case)

This two steps are accomplished by loaders too (adding the wrapper function and replacing the require statements)

4. Create final asset

  • Must have all of our code
  • Must define the webpackRequire function
(function(moduleArray) {
  var cache = {};

  function webpackRequire(index) {
    if (cache[index]) { return cache[index]; }
  
    var module = { exports: {} };
    var file = moduleArray[index];
    file(module, webpackRequire);
    cache[index] = module.exports;
    
    return module.exports;
  
  }
  
  return webpackRequire(0); // <- bootstrap the process from the entry file

})([entryModule, dependency1, dependency2, ..., dependencyN]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment