{"action":"created","comment":{"url":"https://api.github.com/repos/madewithlove/blog/pulls/comments/42234642","id":42234642,"diff_hunk":"@@ -0,0 +1,968 @@\n+---\n+layout: post\n+title: Webpack your bags\n+date: 2015-10-09T00:00:00.000Z\n+author: maxime\n+excerpt: Learn how to leverage Webpack to bundle your applications efficiently\n+---\n+\n+![](https://webpack.github.io/assets/what-is-webpack.png)\n+\n+# Webpack your bags\n+By now you've probably heard about this new cool tool on the block called **Webpack**. If you haven't looked that much into it you're probably a bit confused by some people calling it a build tool _à la_ **Gulp** and other people calling it a bundler like **Browserify**. If on the other hand you _have_ looked into it you're probably still confused because the homepage presents Webpack as both.\n+\n+To be honest, at first the blur around \"what Webpack is\" frustrated me, and I closed the tab. After all _I already had a build system_, and was perfectly happy with it. And if you follow closely the very fast Javascript scene, like me, you've probably been burnt in the past by jumping on the bandwagon too soon. Having now a bit more experience with it I felt I should write this article for those still on the fence to explain more clearly what Webpack is, and more importantly what is so great about it that it deserves so much attention.\n+\n+## What is Webpack?\n+Right off the bat let's answer the question posed by the introduction: is Webpack a build system or a module bundler? Well, it's both– and by this I don't mean that it _does_ both I mean that it _combines_ both. Webpack doesn't build your assets, and then separately bundle your modules, it considers your assets _to be modules themselves_.\n+\n+What this means more precisely is that instead of building all your Sass files, and optimizing all your images, and including them on one side, then bundling all your modules, and including them on your page on another, you have this:\n+\n+```js\n+import stylesheet from 'styles/my-styles.scss';\n+import logo from 'img/my-logo.svg';\n+import someTemplate from 'html/some-template.html';\n+\n+console.log(stylesheet); // \"body{font-size:12px}\"\n+console.log(logo); // \"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5[...]\"\n+console.log(someTemplate) // \"<html><body><h1>Hello</h1></body></html>\"\n+```\n+\n+All your assets are considered modules themselves, that can be imported, modified, manipulated, and that ultimately can be packed into your final bundle.\n+\n+In order for this to work, you register **loaders** in your Webpack configuration. Loaders are small plugins that basically say \"When you encounter this kind of file, do this with it\". Some examples of loaders:\n+\n+```js\n+{\n+  // When you import a .ts file, parse it with Typescript\n+  test: /\\.ts/,\n+  loader: 'typescript',\n+},\n+{\n+  // When you encounter images, compress them with image-webpack (wrapper around imagemin)\n+  // and then inline them as data64 URLs\n+  test: /\\.(png|jpg|svg)/,\n+  loaders: ['url', 'image-webpack'],\n+},\n+{\n+  // When you encounter SCSS files, parse them with node-sass, then pass autoprefixer on them\n+  // then return the results as a string of CSS\n+  test: /\\.scss/,\n+  loaders: ['css', 'autoprefixer', 'sass'],\n+}\n+```\n+\n+Ultimately at the end of the food chain all loaders return strings. This allows Webpack to wrap them into Javascript modules. Per example once your Sass file is done being transformed by the loaders, it may internally look something like that:\n+\n+```js\n+export default 'body{font-size:12px}';\n+```\n+\n+![](http://i.imgur.com/iK7sL6Z.gif)\n+\n+## Why on earth would you do that?\n+Once you understand what Webpack does that's most likely the second question that will come to mind: what possible benefits could this approach have? \"Images and CSS? In my JS? What the hell man?\". Well consider this: for a long while we've been taught and trained to concatenate all the things into one single file; to be very preserving about our HTTP requests, yada yada.\n+\n+This has led to one big downside which is that most people nowadays bundle _all their assets_ into one single `app.js` file that is then included in all the pages. Which means most of the time on any given page you're loading a ton of assets that aren't required. And if you aren't doing that, then you're most likely including assets by hand on certain pages but not on others, which leads to a big mess of dependency trees to maintain and keep track of: on which pages is this dependency needed already? Which pages do the stylesheets A and B affect?\n+\n+Neither approaches are right, nor wrong. Consider Webpack a middleground– it's not just a build system or a bundler, it's a _wicked smart_ module packing system. Once properly configured, it'll _know more about your stack_ then even you do, and it'll know better than you how to best optimize it.\n+\n+## Let's build a small app together\n+In order for you to more easily understand the benefits of Webpack we'll build a _very_ small app and bundle the assets with it. For this tutorial I recommend running Node 4 and NPM 3 as the flat dependencies tree will avoid a good bunch of headaches when working with Webpack. If you don't have NPM 3 yet, you can install it through `npm install npm@3 -g`.\n+\n+```bash\n+$ node --version\n+v4.1.2\n+$ npm --version\n+3.3.6\n+```\n+\n+I also recommend you add `node_modules/.bin` to your PATH variable to avoid having to type `node_modules/.bin/webpack` every time. All examples after this won't show the `node_modules/.bin` part of the commands I'll run.\n+\n+### Basic bootstrapping\n+Let's start by creating our project and installing Webpack, we'll also pull in jQuery to demonstrate some things later on.\n+\n+```bash\n+$ npm init\n+$ npm install jquery --save\n+$ npm install webpack --save-dev\n+```\n+\n+Now let's create our app's entry point, in plain ES5 for now:\n+\n+**src/index.js**\n+\n+```js\n+var $ = require('jquery');\n+\n+$('body').html('Hello');\n+```\n+\n+And let's create our Webpack configuration, in a `webpack.config.js` file. Webpack configuration is just Javascript, and needs to export an object:\n+\n+**webpack.config.js**\n+\n+```js\n+module.exports = {\n+    entry:  './src',\n+    output: {\n+        path:     'builds',\n+        filename: 'bundle.js',\n+    },\n+};\n+```\n+\n+Here, `entry` tells Webpack which files are the _entry points_ of your application. Those are your main files, that sit at the top of your dependencies tree. Then we tell it to compile our bundle in the `builds` directory under the name `bundle.js`. So let's setup our index HTML accordingly:\n+\n+```html\n+<!DOCTYPE html>\n+<html>\n+<body>\n+    <h1>My title</h1>\n+    <a>Click me</a>\n+\n+    <script src=\"builds/bundle.js\"></script>\n+</body>\n+</html>\n+```\n+\n+Let's run Wepack, and if everything went right we should get a message telling us it compiled our `bundle.js` properly:\n+\n+```\n+$ webpack\n+Hash: 65ea4aab7f0755f7fc8e\n+Version: webpack 1.12.2\n+Time: 350ms\n+    Asset    Size  Chunks             Chunk Names\n+bundle.js  257 kB       0  [emitted]  main\n+   [0] ./src/index.js 53 bytes {0} [built]\n+    + 1 hidden modules\n+```\n+\n+Here you can see Webpack tells you your `bundle.js` contains our entry point (`index.js`) as well as one hidden module. This is jQuery, by default Webpack hides modules that are not yours. To see all the modules compiled by Webpack, we can pass the `--display-modules` flag:\n+\n+```\n+$ webpack --display-modules\n+bundle.js  257 kB       0  [emitted]  main\n+   [0] ./src/index.js 53 bytes {0} [built]\n+   [1] ./~/jquery/dist/jquery.js 248 kB {0} [built]\n+```\n+\n+You can also run `webpack --watch` to make it automatically watch for changes to your files and recompile as needed.\n+\n+### Setting up our first loader\n+Now remember how we talked about Webpack being able to import CSS and HTML and all kinds of things? Where does that fit in? Well if you're in tune with the large movement towards Web Components these past few years (Angular 2, Vue, React, Polymer, X-Tag, etc.) you've probably heard about the idea that your app – instead of being one interconnected monolithic piece of UI – would be more maintainable as a set of small reusable self-contained pieces of UI: web components (I'm simplifying here, but you get the idea). Now in order for components to be truly self-contained, they need to pack all their requirements within themselves. Imagine a button component: it has some HTML sure, but also some JS to make it interact with things, and probably also some styles. It would be nice if all of those would only be loaded when needed, right? Only when we import the Button component, would we get all its related assets.\n+\n+Let's write our button; first-off, as most of you are I assume now more accustomed to ES2015 we'll add our first loader: Babel. To install a loader in Webpack you do two things: `npm install {whatever}-loader`, and add it to the `module.loaders` part of your Webpack configuration, so let's do that. Here we want babel, so:\n+\n+```bash\n+$ npm install babel-loader --save-dev\n+```\n+\n+And update our configuration: what do we want? We want Babel to run on all files that end in `.js`, **but** as Webpack traverses all dependencies we want to avoid Babel running on third-party code like jQuery, so we can filter this a bit more. Loaders can have both an `include` or an `exclude` rule. It can be a string, a regex, a callback, whatever you want. In our case, we want Babel to only run on _our_ files, so we'll `include` only our source directory:\n+\n+```js\n+module.exports = {\n+    entry:  './src',\n+    output: {\n+        path:     'builds',\n+        filename: 'bundle.js',\n+    },\n+    module: {\n+        loaders: [\n+            {\n+                test:   /\\.js/,\n+                loader: 'babel',\n+                include: __dirname + '/src',\n+            }\n+        ],\n+    }\n+};\n+```\n+\n+We can now rewrite our little `index.js` in ES6 since we pulled in Babel. All examples from now on will be in ES6.\n+\n+```js\n+import $ from 'jquery';\n+\n+$('body').html('Hello');\n+```\n+\n+### Writing a small component\n+Let's now write a small Button component, it'll have some SCSS styles, an HTML template, and some behavior. So we'll install the things we need. First of all we'll need Mustache which is a very lightweight templating package, but we'll also need loaders for Sass and HTML files. Also, as results are piped from one loader to another, we'll need a CSS loader to handle the results of the Sass loader. Now, once we have our CSS, there are multiple ways to handle them, for now we'll use a loader called the `style-loader` which takes a piece of CSS and injects it into the page dynamically.\n+\n+```bash\n+$ npm install mustache --save\n+$ npm install css-loader style-loader html-loader sass-loader node-sass --save-dev\n+```\n+\n+Now in order to tell Webpack to \"pipe\" things from one loader to another we simply pass a series of loaders, from right to left, separated by a `!`. Alternatively you can use an array by using the `loaders` attribute instead of `loader`:\n+\n+```js\n+{\n+    test:    /\\.js/,\n+    loader:  'babel',\n+    include: __dirname + '/src',\n+},\n+{\n+    test:   /\\.scss/,\n+    loader: 'style!css!sass',\n+    // Or\n+    loaders: ['style', 'css', 'sass'],\n+},\n+{\n+    test:   /\\.html/,\n+    loader: 'html',\n+}\n+```\n+\n+Now that we have our loaders in place, let's write our button:\n+\n+**src/Components/Button.scss**\n+\n+```scss\n+.button {\n+  background: tomato;\n+  color: white;\n+}\n+```\n+\n+**src/Components/Button.html**\n+\n+```mustache\n+<a class=\"button\" href=\"{{link}}\">{{text}}</a>\n+```\n+\n+**src/Components/Button.js**\n+\n+```js\n+import $ from 'jquery';\n+import template from './Button.html';\n+import Mustache from 'mustache';\n+import './Button.scss';\n+\n+export default class Button {\n+    constructor(link) {\n+        this.link = link;\n+    }\n+\n+    onClick(event) {\n+        event.preventDefault();\n+        alert(this.link);\n+    }\n+\n+    render(node) {\n+        const text = $(node).text();\n+\n+        // Render our button\n+        $(node).html(\n+            Mustache.render(template, {text})\n+        );\n+\n+        // Attach our listeners\n+        $('.button').click(this.onClick.bind(this));\n+    }\n+}\n+```\n+\n+Your `Button.js` is now 100% self-contained and whenever imported, in whichever context it'll run, it'll have all the tools in hands to be used and rendered properly. Now we just need to render (very dirtily) our Button on our page:\n+\n+```js\n+import Button from './Components/Button';\n+\n+const button = new Button('google.com');\n+button.render('a');\n+```\n+\n+Let's try to run Webpack and refresh our page, you should now see our disgusting button in action.\n+\n+![](http://i.imgur.com/8Ov1x2P.png)\n+\n+You've now learned how to setup loaders and how to define the dependencies of each part of your app. This may look like it doesn't matter much now, but let's push our example further.\n+\n+### Code splitting\n+This example is fine and everything, but maybe we don't always need our button. Maybe on some pages there won't be an `a` to render the button on, and in these cases, we'd like to not import all the Button styles, and templates, and Mustache and everything, correct? That's when code splitting comes into play. Code splitting is Webpack's answer to this problematic of \"Monolithic bundle\" vs \"Unmaintainable manual imports\". It's the idea that you define, in your code, \"split points\": areas of your code that could be easily split off into a separate file and then loaded on-demand. The syntax is very simple:\n+\n+```js\n+import $ from 'jquery';\n+\n+// This is a split point\n+require.ensure([], () => {\n+  // All the code in here, and everything that is imported\n+  // will be in a separate file\n+  const library = require('some-big-library');\n+  $('foo').click(() => library.doSomething());\n+});\n+```\n+\n+Everything in the `require.ensure` callback would be split into a _chunk_ – a separate bundle that Webpack will load only when needed, through an AJAX request. That means we would basically have this:\n+\n+```\n+bundle.js\n+|- jquery.js\n+|- index.js // our main file\n+chunk1.js\n+|- some-big-libray.js\n+|- index-chunk.js // the code in the callback\n+```\n+\n+And you don't have to import or load `chunk1.js` anywhere. Webpack will load it on-demand, only when it is needed. That means you can wrap chunks of your code with various pieces of logic, which is what we'll do in our example. We only want our Button component when we have a link on the page:\n+\n+**src/index.js**\n+\n+```js\n+if (document.querySelectorAll('a').length) {\n+    require.ensure([], () => {\n+        const Button = require('./Components/Button');\n+        const button = new Button('google.com');\n+\n+        button.render('a');\n+    });\n+}\n+```\n+\n+Webpack's output should now be different, accordingly. Let's run it with the `--display-chunks` flag to see what modules are in which chunks:\n+\n+```\n+$ webpack --display-modules --display-chunks\n+Hash: 432341dc518c06c9d8da\n+Version: webpack 1.12.2\n+Time: 952ms\n+      Asset     Size  Chunks             Chunk Names\n+  bundle.js  3.88 kB       0  [emitted]  main\n+1.bundle.js   287 kB       1  [emitted]\n+chunk    {0} bundle.js (main) 294 bytes [rendered]\n+    [0] ./src/index.js 294 bytes {0} [built]\n+chunk    {1} 1.bundle.js 278 kB {0} [rendered]\n+    [1] ./src/Components/Button.js 2.02 kB {1} [built]\n+    [2] ./~/jquery/dist/jquery.js 248 kB {1} [built]\n+    [3] ./src/Components/Button.html 72 bytes {1} [built]\n+    [4] ./~/mustache/mustache.js 19.3 kB {1} [built]\n+    [5] ./src/Components/Button.scss 1.05 kB {1} [built]\n+    [6] ./~/css-loader!./~/sass-loader!./src/Components/Button.scss 212 bytes {1} [built]\n+    [7] ./~/css-loader/lib/css-base.js 1.51 kB {1} [built]\n+    [8] ./~/style-loader/addStyles.js 6.09 kB {1} [built]\n+```\n+\n+As you can see, our entry point (`bundle.js`) now only contains some Webpack logic, and everything else (jQuery, Mustache, Button) is in the `1.bundle.js` chunk and will only be loaded if we have an anchor on the page. Now in order for Webpack to know where to find the chunks when loading them with AJAX, we have to add a little line to our configuration:\n+\n+```js\n+path:       'builds',\n+filename:   'bundle.js',\n+publicPath: 'builds/',\n+```\n+\n+The `output.publicPath` option tells Webpack where to find built assets _from the point of view of the page_ (so in our case in /builds/). If we visit our page now we'll see that everything is still working, but more importantly we'll see that, since we had an anchor on the page, Webpack properly loaded our chunk:\n+\n+![](http://i.imgur.com/rPvIRiB.png)\n+\n+If we didn't have an anchor on our page, only `bundle.js` would have been loaded. This allows you to intelligently split off heavy logic in your application and only let each page require what it truly needs. Note also that we can name our split points so that instead of `1.bundle.js` we have more meaningful chunk names. You can do so by passing a third argument to `require.ensure`:\n+\n+```js\n+require.ensure([], () => {\n+    const Button = require('./Components/Button');\n+    const button = new Button('google.com');\n+\n+    button.render('a');\n+}, 'button');\n+```\n+\n+Would generate `button.bundle.js` instead of `1.bundle.js`.\n+\n+### Adding a second component\n+Now this is pretty cool and all but let's add a second component, and we'll see we'll hit a problem:\n+\n+**src/Components/Header.scss**\n+\n+```sass\n+.header {\n+  font-size: 3rem;\n+}\n+```\n+\n+**src/Components/Header.html**\n+\n+```html\n+<header class=\"header\">{{text}}</header>\n+```\n+\n+**src/Components/Header.js**\n+\n+```js\n+import $ from 'jquery';\n+import Mustache from 'mustache';\n+import template from './Header.html';\n+import './Header.scss';\n+\n+export default class Header {\n+    render(node) {\n+        const text = $(node).text();\n+\n+        $(node).html(\n+            Mustache.render(template, {text})\n+        );\n+    }\n+}\n+```\n+\n+And let's render it in our application:\n+\n+```js\n+// If we have an anchor, render the Button component on it\n+if (document.querySelectorAll('a').length) {\n+    require.ensure([], () => {\n+        const Button = require('./Components/Button');\n+        const button = new Button('google.com');\n+\n+        button.render('a');\n+    });\n+}\n+\n+// If we have a title, render the Header component on it\n+if (document.querySelectorAll('h1').length) {\n+    require.ensure([], () => {\n+        const Header = require('./Components/Header');\n+\n+        new Header().render('h1');\n+    });\n+}\n+```\n+\n+Now if you look at the output Webpack with the `--display-chunks --display-modules` flags:\n+\n+```\n+$ webpack --display-modules --display-chunks\n+Hash: 1d1634f6b452523fb30d\n+Version: webpack 1.12.2\n+Time: 2744ms\n+      Asset     Size  Chunks             Chunk Names\n+  bundle.js  4.14 kB       0  [emitted]  main\n+1.bundle.js   287 kB       1  [emitted]\n+2.bundle.js   287 kB       2  [emitted]\n+chunk    {0} bundle.js (main) 534 bytes [rendered]\n+    [0] ./src/index.js 534 bytes {0} [built]\n+chunk    {1} 1.bundle.js 278 kB {0} [rendered]\n+    [1] ./src/Components/Button.js 2.02 kB {1} [built]\n+    [2] ./~/jquery/dist/jquery.js 248 kB {1} {2} [built]\n+    [3] ./src/Components/Button.html 72 bytes {1} [built]\n+    [4] ./~/mustache/mustache.js 19.3 kB {1} {2} [built]\n+    [5] ./src/Components/Button.scss 1.05 kB {1} [built]\n+    [6] ./~/css-loader!./~/sass-loader!./src/Components/Button.scss 212 bytes {1} [built]\n+    [7] ./~/css-loader/lib/css-base.js 1.51 kB {1} {2} [built]\n+    [8] ./~/style-loader/addStyles.js 6.09 kB {1} {2} [built]\n+chunk    {2} 2.bundle.js 277 kB {0} [rendered]\n+    [2] ./~/jquery/dist/jquery.js 248 kB {1} {2} [built]\n+    [4] ./~/mustache/mustache.js 19.3 kB {1} {2} [built]\n+    [7] ./~/css-loader/lib/css-base.js 1.51 kB {1} {2} [built]\n+    [8] ./~/style-loader/addStyles.js 6.09 kB {1} {2} [built]\n+    [9] ./src/Components/Header.js 1.69 kB {2} [built]\n+   [10] ./src/Components/Header.html 64 bytes {2} [built]\n+   [11] ./src/Components/Header.scss 1.05 kB {2} [built]\n+   [12] ./~/css-loader!./~/sass-loader!./src/Components/Header.scss 192 bytes {2} [built]\n+```\n+\n+You may see a rather major issue: both our components need jQuery and Mustache, which means these dependencies are getting duplicated in our chunks, which is not what we want. By default Webpack will perform very little optimizations. But it packs in a lot of firepower to help you turn things around, in the form of _plugins_.\n+\n+Plugins differ from loaders in the sense that instead of only executing on a certain set of files, and being more of a \"pipe\", they execute on _all_ files and perform more advanced actions, that aren't necessarily related to transformations. Webpack comes will a handful of plugins to perform all various kinds of optimizations, the one that interests us in this case is the **CommonChunksPlugin**: it analyzes your chunks for recurring dependencies, and extract them somewhere else. It can be a completely separate file (like `vendor.js`) or it can be your main file.","path":"_posts/2015-10-09-webpack-your-bags.md","position":466,"original_position":466,"commit_id":"d1b56be1866876e4048d523c129f74ad4367fa99","original_commit_id":"d1b56be1866876e4048d523c129f74ad4367fa99","user":{"login":"hannesvdvreken","id":1410358,"avatar_url":"https://avatars.githubusercontent.com/u/1410358?v=3","gravatar_id":"","url":"https://api.github.com/users/hannesvdvreken","html_url":"https://github.com/hannesvdvreken","followers_url":"https://api.github.com/users/hannesvdvreken/followers","following_url":"https://api.github.com/users/hannesvdvreken/following{/other_user}","gists_url":"https://api.github.com/users/hannesvdvreken/gists{/gist_id}","starred_url":"https://api.github.com/users/hannesvdvreken/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hannesvdvreken/subscriptions","organizations_url":"https://api.github.com/users/hannesvdvreken/orgs","repos_url":"https://api.github.com/users/hannesvdvreken/repos","events_url":"https://api.github.com/users/hannesvdvreken/events{/privacy}","received_events_url":"https://api.github.com/users/hannesvdvreken/received_events","type":"User","site_admin":false},"body":"it analyzes your chunks for recurring dependencies, and extract**s** them somewhere else","created_at":"2015-10-16T11:56:08Z","updated_at":"2015-10-16T11:56:08Z","html_url":"https://github.com/madewithlove/blog/pull/49#discussion_r42234642","pull_request_url":"https://api.github.com/repos/madewithlove/blog/pulls/49","_links":{"self":{"href":"https://api.github.com/repos/madewithlove/blog/pulls/comments/42234642"},"html":{"href":"https://github.com/madewithlove/blog/pull/49#discussion_r42234642"},"pull_request":{"href":"https://api.github.com/repos/madewithlove/blog/pulls/49"}}},"pull_request":{"url":"https://api.github.com/repos/madewithlove/blog/pulls/49","id":47293028,"html_url":"https://github.com/madewithlove/blog/pull/49","diff_url":"https://github.com/madewithlove/blog/pull/49.diff","patch_url":"https://github.com/madewithlove/blog/pull/49.patch","issue_url":"https://api.github.com/repos/madewithlove/blog/issues/49","number":49,"state":"open","locked":false,"title":"Add Webpack article","user":{"login":"Anahkiasen","id":1321596,"avatar_url":"https://avatars.githubusercontent.com/u/1321596?v=3","gravatar_id":"","url":"https://api.github.com/users/Anahkiasen","html_url":"https://github.com/Anahkiasen","followers_url":"https://api.github.com/users/Anahkiasen/followers","following_url":"https://api.github.com/users/Anahkiasen/following{/other_user}","gists_url":"https://api.github.com/users/Anahkiasen/gists{/gist_id}","starred_url":"https://api.github.com/users/Anahkiasen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Anahkiasen/subscriptions","organizations_url":"https://api.github.com/users/Anahkiasen/orgs","repos_url":"https://api.github.com/users/Anahkiasen/repos","events_url":"https://api.github.com/users/Anahkiasen/events{/privacy}","received_events_url":"https://api.github.com/users/Anahkiasen/received_events","type":"User","site_admin":false},"body":"Brace yourselves, this is a long one. Don't hesitate to tell me if I didn't explain something properly or anything. Also I count on @hannesvdvreken for detypoifying the shit out of this ( ͡° ͜ʖ ͡°) ","created_at":"2015-10-09T16:35:45Z","updated_at":"2015-10-16T11:56:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8839afde1add8f0834a01a8f9936631ec74d38a2","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/madewithlove/blog/pulls/49/commits","review_comments_url":"https://api.github.com/repos/madewithlove/blog/pulls/49/comments","review_comment_url":"https://api.github.com/repos/madewithlove/blog/pulls/comments{/number}","comments_url":"https://api.github.com/repos/madewithlove/blog/issues/49/comments","statuses_url":"https://api.github.com/repos/madewithlove/blog/statuses/d1b56be1866876e4048d523c129f74ad4367fa99","head":{"label":"madewithlove:webpack-article","ref":"webpack-article","sha":"d1b56be1866876e4048d523c129f74ad4367fa99","user":{"login":"madewithlove","id":600038,"avatar_url":"https://avatars.githubusercontent.com/u/600038?v=3","gravatar_id":"","url":"https://api.github.com/users/madewithlove","html_url":"https://github.com/madewithlove","followers_url":"https://api.github.com/users/madewithlove/followers","following_url":"https://api.github.com/users/madewithlove/following{/other_user}","gists_url":"https://api.github.com/users/madewithlove/gists{/gist_id}","starred_url":"https://api.github.com/users/madewithlove/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/madewithlove/subscriptions","organizations_url":"https://api.github.com/users/madewithlove/orgs","repos_url":"https://api.github.com/users/madewithlove/repos","events_url":"https://api.github.com/users/madewithlove/events{/privacy}","received_events_url":"https://api.github.com/users/madewithlove/received_events","type":"Organization","site_admin":false},"repo":{"id":28820310,"name":"blog","full_name":"madewithlove/blog","owner":{"login":"madewithlove","id":600038,"avatar_url":"https://avatars.githubusercontent.com/u/600038?v=3","gravatar_id":"","url":"https://api.github.com/users/madewithlove","html_url":"https://github.com/madewithlove","followers_url":"https://api.github.com/users/madewithlove/followers","following_url":"https://api.github.com/users/madewithlove/following{/other_user}","gists_url":"https://api.github.com/users/madewithlove/gists{/gist_id}","starred_url":"https://api.github.com/users/madewithlove/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/madewithlove/subscriptions","organizations_url":"https://api.github.com/users/madewithlove/orgs","repos_url":"https://api.github.com/users/madewithlove/repos","events_url":"https://api.github.com/users/madewithlove/events{/privacy}","received_events_url":"https://api.github.com/users/madewithlove/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/madewithlove/blog","description":"The madewithlove blog","fork":false,"url":"https://api.github.com/repos/madewithlove/blog","forks_url":"https://api.github.com/repos/madewithlove/blog/forks","keys_url":"https://api.github.com/repos/madewithlove/blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/madewithlove/blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/madewithlove/blog/teams","hooks_url":"https://api.github.com/repos/madewithlove/blog/hooks","issue_events_url":"https://api.github.com/repos/madewithlove/blog/issues/events{/number}","events_url":"https://api.github.com/repos/madewithlove/blog/events","assignees_url":"https://api.github.com/repos/madewithlove/blog/assignees{/user}","branches_url":"https://api.github.com/repos/madewithlove/blog/branches{/branch}","tags_url":"https://api.github.com/repos/madewithlove/blog/tags","blobs_url":"https://api.github.com/repos/madewithlove/blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/madewithlove/blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/madewithlove/blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/madewithlove/blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/madewithlove/blog/statuses/{sha}","languages_url":"https://api.github.com/repos/madewithlove/blog/languages","stargazers_url":"https://api.github.com/repos/madewithlove/blog/stargazers","contributors_url":"https://api.github.com/repos/madewithlove/blog/contributors","subscribers_url":"https://api.github.com/repos/madewithlove/blog/subscribers","subscription_url":"https://api.github.com/repos/madewithlove/blog/subscription","commits_url":"https://api.github.com/repos/madewithlove/blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/madewithlove/blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/madewithlove/blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/madewithlove/blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/madewithlove/blog/contents/{+path}","compare_url":"https://api.github.com/repos/madewithlove/blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/madewithlove/blog/merges","archive_url":"https://api.github.com/repos/madewithlove/blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/madewithlove/blog/downloads","issues_url":"https://api.github.com/repos/madewithlove/blog/issues{/number}","pulls_url":"https://api.github.com/repos/madewithlove/blog/pulls{/number}","milestones_url":"https://api.github.com/repos/madewithlove/blog/milestones{/number}","notifications_url":"https://api.github.com/repos/madewithlove/blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/madewithlove/blog/labels{/name}","releases_url":"https://api.github.com/repos/madewithlove/blog/releases{/id}","created_at":"2015-01-05T16:13:23Z","updated_at":"2015-10-09T18:10:58Z","pushed_at":"2015-10-09T22:28:59Z","git_url":"git://github.com/madewithlove/blog.git","ssh_url":"git@github.com:madewithlove/blog.git","clone_url":"https://github.com/madewithlove/blog.git","svn_url":"https://github.com/madewithlove/blog","homepage":null,"size":19752,"stargazers_count":4,"watchers_count":4,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":4,"mirror_url":null,"open_issues_count":5,"forks":4,"open_issues":5,"watchers":4,"default_branch":"gh-pages"}},"base":{"label":"madewithlove:gh-pages","ref":"gh-pages","sha":"592bf9b0dd1031bd084e101517b88e1cb544215a","user":{"login":"madewithlove","id":600038,"avatar_url":"https://avatars.githubusercontent.com/u/600038?v=3","gravatar_id":"","url":"https://api.github.com/users/madewithlove","html_url":"https://github.com/madewithlove","followers_url":"https://api.github.com/users/madewithlove/followers","following_url":"https://api.github.com/users/madewithlove/following{/other_user}","gists_url":"https://api.github.com/users/madewithlove/gists{/gist_id}","starred_url":"https://api.github.com/users/madewithlove/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/madewithlove/subscriptions","organizations_url":"https://api.github.com/users/madewithlove/orgs","repos_url":"https://api.github.com/users/madewithlove/repos","events_url":"https://api.github.com/users/madewithlove/events{/privacy}","received_events_url":"https://api.github.com/users/madewithlove/received_events","type":"Organization","site_admin":false},"repo":{"id":28820310,"name":"blog","full_name":"madewithlove/blog","owner":{"login":"madewithlove","id":600038,"avatar_url":"https://avatars.githubusercontent.com/u/600038?v=3","gravatar_id":"","url":"https://api.github.com/users/madewithlove","html_url":"https://github.com/madewithlove","followers_url":"https://api.github.com/users/madewithlove/followers","following_url":"https://api.github.com/users/madewithlove/following{/other_user}","gists_url":"https://api.github.com/users/madewithlove/gists{/gist_id}","starred_url":"https://api.github.com/users/madewithlove/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/madewithlove/subscriptions","organizations_url":"https://api.github.com/users/madewithlove/orgs","repos_url":"https://api.github.com/users/madewithlove/repos","events_url":"https://api.github.com/users/madewithlove/events{/privacy}","received_events_url":"https://api.github.com/users/madewithlove/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/madewithlove/blog","description":"The madewithlove blog","fork":false,"url":"https://api.github.com/repos/madewithlove/blog","forks_url":"https://api.github.com/repos/madewithlove/blog/forks","keys_url":"https://api.github.com/repos/madewithlove/blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/madewithlove/blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/madewithlove/blog/teams","hooks_url":"https://api.github.com/repos/madewithlove/blog/hooks","issue_events_url":"https://api.github.com/repos/madewithlove/blog/issues/events{/number}","events_url":"https://api.github.com/repos/madewithlove/blog/events","assignees_url":"https://api.github.com/repos/madewithlove/blog/assignees{/user}","branches_url":"https://api.github.com/repos/madewithlove/blog/branches{/branch}","tags_url":"https://api.github.com/repos/madewithlove/blog/tags","blobs_url":"https://api.github.com/repos/madewithlove/blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/madewithlove/blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/madewithlove/blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/madewithlove/blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/madewithlove/blog/statuses/{sha}","languages_url":"https://api.github.com/repos/madewithlove/blog/languages","stargazers_url":"https://api.github.com/repos/madewithlove/blog/stargazers","contributors_url":"https://api.github.com/repos/madewithlove/blog/contributors","subscribers_url":"https://api.github.com/repos/madewithlove/blog/subscribers","subscription_url":"https://api.github.com/repos/madewithlove/blog/subscription","commits_url":"https://api.github.com/repos/madewithlove/blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/madewithlove/blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/madewithlove/blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/madewithlove/blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/madewithlove/blog/contents/{+path}","compare_url":"https://api.github.com/repos/madewithlove/blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/madewithlove/blog/merges","archive_url":"https://api.github.com/repos/madewithlove/blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/madewithlove/blog/downloads","issues_url":"https://api.github.com/repos/madewithlove/blog/issues{/number}","pulls_url":"https://api.github.com/repos/madewithlove/blog/pulls{/number}","milestones_url":"https://api.github.com/repos/madewithlove/blog/milestones{/number}","notifications_url":"https://api.github.com/repos/madewithlove/blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/madewithlove/blog/labels{/name}","releases_url":"https://api.github.com/repos/madewithlove/blog/releases{/id}","created_at":"2015-01-05T16:13:23Z","updated_at":"2015-10-09T18:10:58Z","pushed_at":"2015-10-09T22:28:59Z","git_url":"git://github.com/madewithlove/blog.git","ssh_url":"git@github.com:madewithlove/blog.git","clone_url":"https://github.com/madewithlove/blog.git","svn_url":"https://github.com/madewithlove/blog","homepage":null,"size":19752,"stargazers_count":4,"watchers_count":4,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":4,"mirror_url":null,"open_issues_count":5,"forks":4,"open_issues":5,"watchers":4,"default_branch":"gh-pages"}},"_links":{"self":{"href":"https://api.github.com/repos/madewithlove/blog/pulls/49"},"html":{"href":"https://github.com/madewithlove/blog/pull/49"},"issue":{"href":"https://api.github.com/repos/madewithlove/blog/issues/49"},"comments":{"href":"https://api.github.com/repos/madewithlove/blog/issues/49/comments"},"review_comments":{"href":"https://api.github.com/repos/madewithlove/blog/pulls/49/comments"},"review_comment":{"href":"https://api.github.com/repos/madewithlove/blog/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/madewithlove/blog/pulls/49/commits"},"statuses":{"href":"https://api.github.com/repos/madewithlove/blog/statuses/d1b56be1866876e4048d523c129f74ad4367fa99"}}}}