{"id":85,"date":"2017-03-21T04:28:16","date_gmt":"2017-03-21T01:28:16","guid":{"rendered":"http:\/\/iamakulov.com\/notes2\/?p=85"},"modified":"2017-11-12T20:17:07","modified_gmt":"2017-11-12T17:17:07","slug":"webpack-for-real-tasks-part-1","status":"publish","type":"post","link":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/","title":{"rendered":"webpack for real tasks: bundling front-end and adding compilation"},"content":{"rendered":"<div class=\"webpack-navigator\">\nThis is the first part of a three-part introduction into webpack:<\/p>\n<ol>\n<li>Bundling front-end and adding compilation <em>(you are here!)<\/em><\/li>\n<li><a href=\"\/notes\/webpack-front-end-size-caching\/\">Decreasing front-end size and improving caching<\/a><\/li>\n<li>Speeding up build and improving the development workflow<\/li>\n<\/ol>\n<p>Want to stay tuned for the future posts? <a href=\"#subscribe\">Subscribe<\/a>\n<\/div>\n<h1 id=\"what-is-webpack\">What is webpack<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#what-is-webpack\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h1>\n<p>Webpack is a front-end bundler. And a front-end bundler is a tool\u00a0that combines\u00a0multiple modules into a single file called <em>bundle<\/em>:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31.png\" alt=\"\" width=\"1280\" height=\"720\" class=\"alignnone size-full wp-image-100\" srcset=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31.png 1280w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31-300x169.png 300w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31-768x432.png 768w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31-1024x576.png 1024w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31-1200x675.png 1200w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<p>While the main purpose of webpack is bundling, it also has a lot of other abilities. For example, webpack can compile your front-end, split your code into multiple files or optimize your bundle size. I\u2019m reviewing many of these abilities in this series of posts.<\/p>\n<p>If you\u2019re not familiar with the concept of bundling,\u00a0Preethi Kasireddy\u00a0<a href=\"https:\/\/medium.freecodecamp.com\/javascript-modules-part-2-module-bundling-5020383cf306#.ofug30xz1\">wrote a good introduction to it<\/a>. Check it out and come back!<\/p>\n<h1 id=\"task-bundle-front-end\"><span class=\"task-badge\">Task<\/span> Bundle front-end<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#task-bundle-front-end\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h1>\n<p><em>Given:<\/em> you have an application that consists of lots of modules. Like Cut the Rope:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/Cut-The-Rope-Game-Screenshot1.jpg\" alt=\"\" width=\"1366\" height=\"768\" class=\"alignnone size-full wp-image-101\" srcset=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/Cut-The-Rope-Game-Screenshot1.jpg 1366w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/Cut-The-Rope-Game-Screenshot1-300x169.jpg 300w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/Cut-The-Rope-Game-Screenshot1-768x432.jpg 768w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/Cut-The-Rope-Game-Screenshot1-1024x576.jpg 1024w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/Cut-The-Rope-Game-Screenshot1-1200x675.jpg 1200w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<p>You want to bundle the modules into a single file: to speed up the loading of an app*, or to serve a library as a single module, or for another reason. Let\u2019s see how webpack can help with this.<\/p>\n<p><em>* \u2013 if you\u2019re thinking \u201cWait, HTTP\/2 made bundling unnecessary\u201d, see <a href=\"http:\/\/engineering.khanacademy.org\/posts\/js-packaging-http2.htm\">the Khan Academy\u2019s post about why no bundling is a bad idea<\/a><\/em><\/p>\n<h2 id=\"good-case-your-code-uses-a-popular-module-system\">Good case: your code uses a popular module system<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#good-case-your-code-uses-a-popular-module-system\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<pre><code class=\"javascript\">\/\/ comments.js\r\ndefine([&#039;.\/dist\/lodash.js&#039;], (_) =&gt; {\r\n  \/\/ \u2026\r\n  return { \u2026 };\r\n});\r\n\r\n\/\/ index.js\r\ndefine([&#039;.\/comments&#039;, \u2026], (comments, \u2026) =&gt; {\r\n  \/\/ \u2026\r\n  comments.render(commentsData, &#039;#comments&#039;);\r\n});\r\n<\/code><\/pre>\n<p>If your code uses AMD, CommonJS or ES modules, everything is simple. Webpack supports these module systems out of the box, so to compile a project with them, you\u2019ll only need to specify the entry file and the name of the resulting file.<\/p>\n<p>To do this, create a file called <em>webpack.config.js<\/em> in the root of your project with the content like this:<\/p>\n<pre><code class=\"javascript\">\/\/ webpack.config.js\r\nmodule.exports = {\r\n  \/\/ An entry point. It\u2019s the main module of your application\r\n  \/\/ that references all the other modules\r\n  entry: &#039;.\/src\/index.js&#039;,\r\n\r\n  output: {\r\n    \/\/ The directory where the bundle should be placed\r\n    path: &#039;.\/dist&#039;,\r\n    \/\/ The name of the resulting bundle\r\n    filename: &#039;bundle.js&#039;,\r\n  },\r\n};\r\n<\/code><\/pre>\n<p>Then, run webpack:<\/p>\n<pre><code class=\"javascript\">npm install --global webpack\r\ncd your\/project\/directory\r\nwebpack\r\n<\/code><\/pre>\n<p>Once you launch webpack, it will compile your project and generate a bundle with all your JavaScript. What\u2019s left? Replace the import of your old entry file with the name of the new file:<\/p>\n<pre><code class=\"diff\">\/\/ index.html\r\n&lt;!doctype html&gt;\r\n&lt;body&gt;\r\n  &lt;!-- \u2026 --&gt;\r\n- &lt;script src=&quot;.\/src\/index.js&quot;&gt;&lt;\/script&gt;\r\n+ &lt;script src=&quot;.\/dist\/bundle.js&quot;&gt;&lt;\/script&gt;\r\n&lt;\/body&gt;\r\n<\/code><\/pre>\n<p>Task solved.<\/p>\n<div class=\"snippet\">\n<h2 id=\"bonus-point-all-module-types-at-once\">Bonus point: all module types at once<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#bonus-point-all-module-types-at-once\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>Webpack supports all three module types in the same project simultaneously. So if a part of your code is in AMD and the other part is in ES modules, it will just work. This can be helpful if you decide to gradually migrate from one module format to another.\n<\/p><\/div>\n<h2 id=\"bad-case-your-code-uses-your-own-module-system\">Bad case: your code uses your own module system<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#bad-case-your-code-uses-your-own-module-system\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<pre><code class=\"javascript\">\/\/ comments.js\r\nMyApp.define([&#039;.\/dist\/lodash.js&#039;], (_) =&gt; {\r\n  \/\/ \u2026\r\n  return { \u2026 };\r\n});\r\n\r\n\/\/ index.js\r\nMyApp.define([&#039;.\/comments&#039;, \u2026], (comments, \u2026) =&gt; {\r\n  \/\/ \u2026\r\n  comments.render(commentsData, &#039;#comments&#039;);\r\n});\r\n<\/code><\/pre>\n<p>In case your code uses a module system different from AMD, CommonJS or ES modules, things get more complicated. To make webpack work with your code:<\/p>\n<ul>\n<li>either <mark>migrate your code to a supported module format.<\/mark> Facebook has <a href=\"https:\/\/github.com\/facebook\/codemod\">a tool called <em>codemod<\/em><\/a> which can automate a massive refactoring and could be useful for you;<\/p>\n<\/li>\n<li>or <mark>write a Babel plugin for converting your custom module format<\/mark> to AMD, CommonJS or ES modules. This plugin will be executed on each compilation. Take a look at <a href=\"https:\/\/github.com\/msrose\/babel-plugin-transform-amd-to-commonjs\">babel-plugin-transform-amd-to-commonjs<\/a> to get an idea of how to write it. (We\u2019ll see how to enable Babel a bit later.)<\/p>\n<\/li>\n<\/ul>\n<p>After you deal with the custom module format, configure the entry point and the output as described in \u201cGood case\u201d above.<\/p>\n<div class=\"snippet\">\n<h2 id=\"bonus-point-global-webpack-installation\">Bonus point: global webpack installation<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#bonus-point-global-webpack-installation\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>Although installing webpack globally (<nobr><em>npm install &#8211;global webpack<\/em><\/nobr>) is the easiest way to do the build, I prefer using it through npm scripts. webpack is often installed as a project dependency (because it provides plugins that are used in the configuration), so using it from npm scripts prevents the version conflict. Also, npm scripts can be run from any directory inside the project, not only from the root:<\/p>\n<pre><code >\/\/ package.json\r\n{\r\n  &quot;scripts&quot;: {\r\n    &quot;build&quot;: &quot;webpack&quot;\r\n  }\r\n}\r\n<\/code><\/pre>\n<pre><code ># Console\r\nnpm run build\r\n<\/code><\/pre>\n<\/div>\n<h2 id=\"compile-js\" id=\"compile-js\" id=\"compile-js\"><span class=\"task-badge\">Task<\/span> Compile JavaScript<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#compile-js\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p><em>Given:<\/em> you have some code that cannot be run in the browser. This can be code that uses features from the next JavaScript standard or even code in another language like TypeScript:<\/p>\n<pre><code class=\"javascript\">\/\/ comments.js\r\nimport _ from &#039;lodash&#039;;\r\n\r\nexport async render(\u2026) {\r\n  const userData = await getUserData(userId);\r\n  \/\/ \u2026\r\n}\r\n<\/code><\/pre>\n<p>You want to compile it to make it work. Let\u2019s see how webpack helps to solve this task.<\/p>\n<p>Assume you\u2019re using Babel. You may have used it from the command line specifying the input and the output:<\/p>\n<pre><code class=\"text\">babel .\/src -d .\/dist\r\n<\/code><\/pre>\n<p>Or you may have used it from Gulp as a part of a stream:<\/p>\n<pre><code class=\"javascript\">gulp.task(&#039;default&#039;, () =&gt; {\r\n  return gulp.src(&#039;.\/src\/**\/*.js&#039;)\r\n    .pipe(babel())\r\n    .pipe(gulp.dest(&#039;dist&#039;));\r\n});\r\n<\/code><\/pre>\n<p>webpack has a bit different approach. It uses <em>loaders<\/em>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_41.png\" alt=\"\" width=\"1072\" height=\"740\" class=\"alignnone size-full wp-image-102\" srcset=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_41.png 1072w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_41-300x207.png 300w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_41-768x530.png 768w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_41-1024x707.png 1024w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<p>A loader is a JavaScript module. Webpack pipes all files through specified loaders before adding them into bundle.<\/p>\n<p>A loader accepts any input and converts it to JavaScript which webpack works with. Loaders can be organized into chains; a chain accepts any input, pipes it through the loaders and passes the result to webpack. In this case, intermediate loaders can return anything, not only JavaScript.<\/p>\n<p>In webpack, Babel works as a loader. To use it, install <a href=\"https:\/\/github.com\/babel\/babel-loader\"><em>babel-loader<\/em><\/a> with its peer dependencies. Then, tell webpack to apply the loader with the <em>module.rules<\/em> option:<\/p>\n<pre><code class=\"javascript\">\/\/ webpack.config.js\r\nmodule.exports = {\r\n  \/\/ ...\r\n  module: {\r\n    rules: [\r\n      {\r\n        \/\/ Take every JavaScript file imported into a bundle...\r\n        test: \/.js$\/,\r\n        \/\/ ...and pipe it through babel-loader...\r\n        use: [&#039;babel-loader&#039;],\r\n        \/\/ ...with the following options\r\n        options: {\r\n          presets: [&#039;env&#039;],\r\n        },\r\n      },\r\n    ],\r\n  },\r\n};\r\n<\/code><\/pre>\n<p>The same approach works for TypeScript:<\/p>\n<pre><code class=\"javascript\">\/\/ webpack.config.js\r\nmodule.exports = {\r\n  \/\/ ...\r\n  module: {\r\n    rules: [\r\n      {\r\n        test: \/.ts$\/,\r\n        use: [&#039;ts-loader&#039;]\r\n      }\r\n    ]\r\n  }\r\n};\r\n<\/code><\/pre>\n<p>Or you can chain Babel and Typescript to do transformations that aren\u2019t supported by the latter:<\/p>\n<pre><code class=\"javascript\">\/\/ webpack.config.js\r\nmodule.exports = {\r\n  \/\/ ...\r\n  module: {\r\n    rules: [\r\n      {\r\n        test: \/.ts$\/,\r\n        \/\/ Loaders are applied from right to left\r\n        use: [&#039;ts-loader&#039;, &#039;babel-loader&#039;]\r\n      }\r\n    ]\r\n  }\r\n};\r\n<\/code><\/pre>\n<p>You can find the list of the most popular loaders <a href=\"https:\/\/webpack.js.org\/loaders\/\">in webpack docs<\/a>.<\/p>\n<div class=\"snippet\">\n<h2 id=\"bonus-point-different-ways-to-specify-a-loader\">Bonus point: different ways to specify a loader<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#bonus-point-different-ways-to-specify-a-loader\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>Above, I passed a string array into the <em>use<\/em> property to apply a loader. There\u2019re two more ways to specify loaders. Here\u2019re all of them:<\/p>\n<pre><code class=\"javascript\">\/\/ Specifies a single loader with or without options\r\n{\r\n  test: \/.js$\/,\r\n  loader: 'babel-loader',\r\n  options: { ... } \r\n},\r\n\r\n\/\/ Specifies multiple loaders without options\r\n{\r\n  test: \/.ts$\/,\r\n  use: ['ts-loader', 'babel-loader']\r\n},\r\n\r\n\/\/ Specifies multiple loaders with or without options\r\n{\r\n  test: \/.ts$\/,\r\n  use: ['ts-loader', { loader: 'babel-loader', options: { ... } }]\r\n}\r\n<\/code><\/pre>\n<p>Choose between them based on your needs.<\/p>\n<h2 id=\"bonus-point-loaders-in-the-require-query\">Bonus point: loaders in the require query<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#bonus-point-loaders-in-the-require-query\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>Apart from specifying loaders in <em>webpack.config.js<\/em>, you can also specify them in your import request:<\/p>\n<pre><code >import comments from 'ts-loader!babel-loader?presets[]=env!.\/comments.ts';\r\n<\/code><\/pre>\n<p>This can be useful for testing. Nevertheless, I don\u2019t recommend using it in production because it makes your code dependent on a specific bundler.\n<\/p><\/div>\n<h1 id=\"task-manage-other-files\"><span class=\"task-badge\">Task<\/span> Manage other files<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#task-manage-other-files\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h1>\n<p>Webpack can also help you manage your styles, images or any other files.<\/p>\n<p><em>Given:<\/em> front-end application with styles and other assets.<br \/>\nYou want to manage them with webpack to reduce the number of the necessary tools. Let\u2019s see how to do this.<\/p>\n<p>The one important thing you should remember here is the following:<\/p>\n<div class=\"large-text\">\nIn webpack, every asset is imported as a module\n<\/div>\n<p>That is. In a traditional task manager like Gulp you split your front-end compilation by a file type:<\/p>\n<pre><code class=\"javascript\">\/\/ gulpfile.js\r\ngulp.task(&#039;js&#039;,\u00a0function ()\u00a0{\r\n\u00a0\u00a0return\u00a0gulp.src(&#039;.\/src\/index.js&#039;)\r\n\u00a0\u00a0\u00a0\u00a0\/\/ ...\r\n\u00a0\u00a0\u00a0\u00a0.pipe(gulp.dest(&#039;.\/dist\/&#039;));\r\n});\r\n\r\ngulp.task(&#039;css&#039;, function () {\r\n  return gulp.src(&#039;.\/src\/**\/*.scss&#039;)\r\n    \/\/ ...\r\n    .pipe(gulp.dest(&#039;.\/dist\/&#039;));\r\n});\r\n<\/code><\/pre>\n<p>In webpack, however, you don\u2019t split the compilation. You treat the front-end as <em>a whole single thing<\/em>. <mark>To include styles and other assets, you <em>import<\/em> them:<\/mark><\/p>\n<pre><code class=\"javascript\">\/\/ comments.js\r\nimport _ from &#039;lodash&#039;;\r\nimport &#039;.\/comments.scss&#039;; * \u2190 Here\r\nimport iconUrl from &#039;.\/commentsIcon.svg&#039;; * \u2190 And here\r\n\r\nexport function render() {\r\n  \/\/ ...\r\n}\r\n<\/code><\/pre>\n<p><mark>and apply specific loaders to teach webpack to handle these imports.<\/mark> Imported files either get inlined into the bundle or placed next to it. This depends on the loader you use.<\/p>\n<p>Let\u2019s see how to use this in practice.<\/p>\n<div class=\"snippet\">\n<h2 id=\"q-for-the-mother-of-god-why\">Q: For the mother of god, why?<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#q-for-the-mother-of-god-why\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>A: I don\u2019t know why it was decided like this in the beginning. Nevertheless, this brings a real benefit. Usually, with webpack, you import all files used by a component straight into its main JS file. Because of this, all these files will be included into your bundle only if you actually use the component in your app.\n<\/p><\/div>\n<h2 id=\"styles\">Styles<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#styles\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>Here\u2019s the most basic approach:<\/p>\n<pre><code class=\"javascript\">\/\/ comments.js\r\n\/\/ Import the file to pass it under webpack\u2019s management\r\nimport &#039;.\/comments.css&#039;;\r\n\r\n\/\/ webpack.config.js\r\nmodule.exports = {\r\n  \/\/ ...\r\n  module: {\r\n    rules: [\r\n      \/\/ Configure webpack to pass all .css files through css-loader and style-loader\r\n      \/\/ (remember that loaders are applied from right to left)\r\n      { test: \/.css$\/, use: [&#039;style-loader&#039;, &#039;css-loader&#039;] },\r\n    ],\r\n  },\r\n};\r\n<\/code><\/pre>\n<p>Here\u2019s what the loaders do:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/webpack-contrib\/css-loader\"><em>css-loader<\/em><\/a> reads the CSS file, passes all <em>@import<\/em> and <em>url()<\/em> in that file through webpack and returns the result,<\/li>\n<li><a href=\"https:\/\/github.com\/webpack-contrib\/style-loader\"><em>style-loader<\/em><\/a> gets the passed CSS content and creates code that will append that CSS to <em>&lt;head><\/em> when the bundle gets loaded.<\/li>\n<\/ul>\n<p>If you need to compile your styles with a preprocessor, append a corresponding loader into the loaders list and pass the <em>importLoaders = 1<\/em> option to <em>css-loader<\/em>:<\/p>\n<pre><code class=\"javascript\">\/\/ webpack.config.js\r\nmodule.exports = {\r\n  \/\/ ...\r\n  module: {\r\n    rules: [\r\n      { test: \/.css$\/, use: [\r\n        &#039;style-loader&#039;,\r\n        { loader: &#039;css-loader&#039;, options: { importLoaders: 1 } },\r\n        &#039;sass-loader&#039;,\r\n      ] },\r\n    ],\r\n  },\r\n};\r\n<\/code><\/pre>\n<p>See: <a href=\"https:\/\/github.com\/postcss\/postcss-loader\"><em>postcss-loader<\/em><\/a>, <a href=\"https:\/\/github.com\/webpack-contrib\/sass-loader\"><em>sass-loader<\/em><\/a>, <a href=\"https:\/\/github.com\/webpack-contrib\/sass-loader\"><em>less-loader<\/em><\/a>.<\/p>\n<div class=\"snippet\">\n<h2 id=\"bonus-point-css-modules\">Bonus point: CSS Modules<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#bonus-point-css-modules\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>In the examples above, styles don\u2019t provide any exports and therefore are just imported. However, there\u2019s no technical limitation to provide exports, so there are approaches that do this. One of them is CSS Modules.<br \/>\nWith CSS Modules, importing a stylesheet returns a JavaScript object with class names specified in the file. These class names are converted to be unique, so you can use a class name like <em>.button<\/em>\u00a0in several components without any collision:<\/p>\n<pre><code >\/* button.css *\/\r\n.button { \/* styles for the normal state *\/ }\r\n.disabledButton { \/* styles for the disabled state *\/ }\r\n.errorButton { \/* styles for the error state *\/ }\r\n<\/code><\/pre>\n<pre><code >\/\/ button.js\r\nimport styles from '.\/button.css';\r\n\r\nbuttonElement.outerHTML = `&lt;button class=${styles.button}&gt;Submit&lt;\/button&gt;`;\r\n<\/code><\/pre>\n<p>CSS Modules are enabled by passing the <em>modules = true<\/em> option to <a href=\"https:\/\/github.com\/webpack-contrib\/css-loader\">css-loader<\/a>. Read more <a href=\"https:\/\/glenmaddern.com\/articles\/css-modules\">in the CSS Modules introduction<\/a>.\n<\/div>\n<h2 id=\"other-files\">Other files<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#other-files\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>All the other files are also managed using loaders. Approach for every file type is different, so find the appropriate loader and look into its docs. See the list <a href=\"https:\/\/webpack.js.org\/loaders\/\">of the most popular loaders<\/a>.<\/p>\n<p>Here\u2019re examples of loaders for different file types:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/bhovhannes\/svg-url-loader\"><em>svg-url-loader<\/em><\/a>:<\/p>\n<pre><code >import iconDataUrl from '.\/icon.svg';\r\n\/\/ =&gt; iconDataUrl contains a data url of the icon\r\n<\/code><\/pre>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/pugjs\/pug-loader\"><em>pug-loader<\/em><\/a>:<\/p>\n<pre><code >import template from '.\/template.pug';\r\n\/\/ =&gt; template is a function that returns\r\n\/\/ the rendered HTML\r\n<\/code><\/pre>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/webpack-contrib\/file-loader\"><em>file-loader<\/em><\/a>:<\/p>\n<pre><code >import documentUrl from '.\/document.pdf';\r\n\/\/ =&gt; document.pdf is emitted next to the bundle;\r\n\/\/ documentUrl is its public URL\r\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<h1 id=\"%cf%83\">\u03a3<a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#%cf%83\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h1>\n<p>The key points:<\/p>\n<ul>\n<li>The minimal config of webpack is just the entry point and the output file. Webpack works with AMD, CommonJS and ES modules out of the box\n<\/li>\n<li>\n<p>You can use loaders to compile your JavaScript and manage other front-end files<\/p>\n<\/li>\n<li>\n<p>Every file is imported as a module<\/p>\n<\/li>\n<\/ul>\n<p>See the second part, <a href=\"\/notes\/webpack-front-end-size-caching\/\">\u201cDecreasing front-end size and improving caching\u201d<\/a><\/p>\n<hr \/>\n<p id=\"subscribe\">The third part of the guide, \u201cSpeeding up build and improving the development workflow\u201d, is coming soon. Leave your email to know when it\u2019s out:<br \/>\n<small>(you\u2019ll receive an email about the next part of the guide + a couple of more webpack-related posts if I write them; no spam)<\/small><\/p>\n<div>\n        <link href=\"\/\/cdn-images.mailchimp.com\/embedcode\/horizontal-slim-10_7.css\" rel=\"stylesheet\" type=\"text\/css\">\n<style type=\"text\/css\"> #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; margin: 0 -16px 28px; padding: 19px 15px; background: rgba(255, 219, 1, 0.25); border: 1px solid #ffdb01; border-radius: 4px; } <\/style>\n<div class=\"signup-form\" id=\"mc_embed_signup\">\n<form action=\"\/\/iamakulov.us15.list-manage.com\/subscribe\/post?u=d7d2af05c405078e8f6a48956&#038;id=d24b88eefe\" method=\"post\" id=\"mc-embedded-subscribe-form\" name=\"mc-embedded-subscribe-form\" class=\"validate\" target=\"_blank\" novalidate>\n<div id=\"mc_embed_signup_scroll\"><input type=\"email\" value=\"\" name=\"EMAIL\" class=\"email\" id=\"mce-EMAIL\" placeholder=\"email address\" required> <\/p>\n<div style=\"position: absolute; left: -5000px;\" aria-hidden=\"true\"><input type=\"text\" name=\"b_d7d2af05c405078e8f6a48956_d24b88eefe\" tabindex=\"-1\" value=\"\"><\/div>\n<div class=\"clear\"><input type=\"submit\" value=\"Subscribe\" name=\"subscribe\" id=\"mc-embedded-subscribe\" class=\"button\"><\/div>\n<\/div>\n<\/form>\n<\/div>\n<\/div>\n<p><em>Thanks to <a href=\"https:\/\/twitter.com\/iamsapegin\">Artem Sapegin<\/a> for reviewing this post<\/em><\/p>\n<style>\n.task-badge {\n    font-weight: normal;\n    font-size: 0.7em;\n    border: 1px solid black;\n    padding: 2px 4px;\n    border-radius: 2px;\n    text-transform: uppercase;\n    letter-spacing: 1px;\n    vertical-align: 2px;\n} .webpack-navigator {\n    margin: 0 -16px -20px;\n    padding: 19px 15px;\n    background: rgba(255, 219, 1, 0.25);\n    border: 1px solid #ffdb01;\n    border-radius: 4px;\n} .webpack-navigator p:last-child {\n  margin-bottom: 0;\n} .webpack-navigator li:not(:last-child) {\n  margin-bottom: 0;\n}\n<\/style>\n","protected":false},"excerpt":{"rendered":"<p>This is the first part of a three-part introduction into webpack: Bundling front-end and adding compilation (you are here!) Decreasing front-end size and improving caching Speeding up build and improving the development workflow Want to stay tuned for the future posts? Subscribe What is webpack# Webpack is a front-end bundler. And a front-end bundler is &hellip; <a href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;webpack for real tasks: bundling front-end and adding compilation&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[12],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v23.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>webpack for real tasks: bundling front-end and adding compilation - Ivan Akulov\u2019s blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"webpack for real tasks: bundling front-end and adding compilation - Ivan Akulov\u2019s blog\" \/>\n<meta property=\"og:description\" content=\"This is the first part of a three-part introduction into webpack: Bundling front-end and adding compilation (you are here!) Decreasing front-end size and improving caching Speeding up build and improving the development workflow Want to stay tuned for the future posts? Subscribe What is webpack# Webpack is a front-end bundler. And a front-end bundler is &hellip; Continue reading &quot;webpack for real tasks: bundling front-end and adding compilation&quot;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/\" \/>\n<meta property=\"og:site_name\" content=\"Ivan Akulov\u2019s blog\" \/>\n<meta property=\"article:publisher\" content=\"http:\/\/facebook.com\/iamakulov.page\" \/>\n<meta property=\"article:published_time\" content=\"2017-03-21T01:28:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-11-12T17:17:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/cover11.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1200\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Ivan Akulov\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@iamakulov\" \/>\n<meta name=\"twitter:site\" content=\"@iamakulov\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ivan Akulov\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/\",\"url\":\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/\",\"name\":\"webpack for real tasks: bundling front-end and adding compilation - Ivan Akulov\u2019s blog\",\"isPartOf\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#primaryimage\"},\"thumbnailUrl\":\"http:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31.png\",\"datePublished\":\"2017-03-21T01:28:16+00:00\",\"dateModified\":\"2017-11-12T17:17:07+00:00\",\"author\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81\"},\"breadcrumb\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#primaryimage\",\"url\":\"http:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31.png\",\"contentUrl\":\"http:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/iamakulov.com\/notes\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"webpack for real tasks: bundling front-end and adding compilation\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/iamakulov.com\/notes\/#website\",\"url\":\"https:\/\/iamakulov.com\/notes\/\",\"name\":\"Ivan Akulov\u2019s blog\",\"description\":\"Ivan Akulov writes about his front-end experience, React, webpack, and performance optimizations.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/iamakulov.com\/notes\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81\",\"name\":\"Ivan Akulov\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f68e4cd477cef1577c339e6f09736d3a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f68e4cd477cef1577c339e6f09736d3a?s=96&d=mm&r=g\",\"caption\":\"Ivan Akulov\"},\"description\":\"I'm a software engineer specializing in web performance, JavaScript, and React. I\u2019m also a Google Developer Expert. I work at Framer.\",\"sameAs\":[\"http:\/\/iamakulov.com\",\"https:\/\/x.com\/iamakulov\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"webpack for real tasks: bundling front-end and adding compilation - Ivan Akulov\u2019s blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/","og_locale":"en_US","og_type":"article","og_title":"webpack for real tasks: bundling front-end and adding compilation - Ivan Akulov\u2019s blog","og_description":"This is the first part of a three-part introduction into webpack: Bundling front-end and adding compilation (you are here!) Decreasing front-end size and improving caching Speeding up build and improving the development workflow Want to stay tuned for the future posts? Subscribe What is webpack# Webpack is a front-end bundler. And a front-end bundler is &hellip; Continue reading \"webpack for real tasks: bundling front-end and adding compilation\"","og_url":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/","og_site_name":"Ivan Akulov\u2019s blog","article_publisher":"http:\/\/facebook.com\/iamakulov.page","article_published_time":"2017-03-21T01:28:16+00:00","article_modified_time":"2017-11-12T17:17:07+00:00","og_image":[{"width":2000,"height":1200,"url":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/cover11.png","type":"image\/png"}],"author":"Ivan Akulov","twitter_card":"summary_large_image","twitter_creator":"@iamakulov","twitter_site":"@iamakulov","twitter_misc":{"Written by":"Ivan Akulov","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/","url":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/","name":"webpack for real tasks: bundling front-end and adding compilation - Ivan Akulov\u2019s blog","isPartOf":{"@id":"https:\/\/iamakulov.com\/notes\/#website"},"primaryImageOfPage":{"@id":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#primaryimage"},"image":{"@id":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#primaryimage"},"thumbnailUrl":"http:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31.png","datePublished":"2017-03-21T01:28:16+00:00","dateModified":"2017-11-12T17:17:07+00:00","author":{"@id":"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81"},"breadcrumb":{"@id":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#primaryimage","url":"http:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31.png","contentUrl":"http:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/03\/slide_31.png"},{"@type":"BreadcrumbList","@id":"https:\/\/iamakulov.com\/notes\/webpack-for-real-tasks-part-1\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/iamakulov.com\/notes\/"},{"@type":"ListItem","position":2,"name":"webpack for real tasks: bundling front-end and adding compilation"}]},{"@type":"WebSite","@id":"https:\/\/iamakulov.com\/notes\/#website","url":"https:\/\/iamakulov.com\/notes\/","name":"Ivan Akulov\u2019s blog","description":"Ivan Akulov writes about his front-end experience, React, webpack, and performance optimizations.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/iamakulov.com\/notes\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81","name":"Ivan Akulov","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/f68e4cd477cef1577c339e6f09736d3a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f68e4cd477cef1577c339e6f09736d3a?s=96&d=mm&r=g","caption":"Ivan Akulov"},"description":"I'm a software engineer specializing in web performance, JavaScript, and React. I\u2019m also a Google Developer Expert. I work at Framer.","sameAs":["http:\/\/iamakulov.com","https:\/\/x.com\/iamakulov"]}]}},"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts\/85"}],"collection":[{"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/comments?post=85"}],"version-history":[{"count":21,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts\/85\/revisions"}],"predecessor-version":[{"id":838,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts\/85\/revisions\/838"}],"wp:attachment":[{"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/media?parent=85"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/categories?post=85"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/tags?post=85"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}