{"id":259,"date":"2017-06-23T00:43:22","date_gmt":"2017-06-22T21:43:22","guid":{"rendered":"https:\/\/iamakulov.com\/notes\/?p=259"},"modified":"2017-08-18T17:36:42","modified_gmt":"2017-08-18T14:36:42","slug":"polished-webpack","status":"publish","type":"post","link":"https:\/\/iamakulov.com\/notes\/polished-webpack\/","title":{"rendered":"Case study: improving a popular library\u2019s size for webpack users"},"content":{"rendered":"<p>There\u2019s a library called <a href=\"https:\/\/github.com\/styled-components\/polished\">Polished<\/a>. It\u2019s a utility collection for writing styles in JavaScript.<\/p>\n<p><a href=\"https:\/\/github.com\/styled-components\/polished\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1.png\" alt=\"The polished logo\" width=\"159\" height=\"159\" class=\"alignnone size-full wp-image-290\" srcset=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1.png 318w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1-150x150.png 150w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1-300x300.png 300w\" sizes=\"auto, (max-width: 159px) 85vw, 159px\" \/><\/a><\/p>\n<p>And it had a problem.<\/p>\n<h1 id=\"problem\">Problem<a href=\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#problem\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h1>\n<p>A story in three tweets:<\/p>\n<blockquote class=\"twitter-tweet\" data-lang=\"en\">\n<p lang=\"en\" dir=\"ltr\">Seems that import foo from &quot;pkg\/foo&quot; still more effective than import {foo} from &quot;pkg&quot; with wepback 2 even in simple cases \ud83d\ude41<\/p>\n<p>&mdash; Valentin Semirulnik (@7rulnik) <a href=\"https:\/\/twitter.com\/7rulnik\/status\/876533410235396097\">June 18, 2017<\/a><\/p><\/blockquote>\n<p><script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>\n<blockquote class=\"twitter-tweet\" data-lang=\"en\">\n<p lang=\"en\" dir=\"ltr\">Yep. For example: polished. It&#39;s one file with export {}. 4kb vs 8kb.<\/p>\n<p>&mdash; Valentin Semirulnik (@7rulnik) <a href=\"https:\/\/twitter.com\/7rulnik\/status\/876558769597161472\">June 18, 2017<\/a><\/p><\/blockquote>\n<p><script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>\n<blockquote class=\"twitter-tweet\" data-lang=\"en\">\n<p lang=\"en\" dir=\"ltr\">What side effects are you seeing in the bundle that might lead to this, would love to try to get the destructured import smaller.<\/p>\n<p>&mdash; Brian Hough (@b_hough) <a href=\"https:\/\/twitter.com\/b_hough\/status\/876741198525935616\">June 19, 2017<\/a><\/p><\/blockquote>\n<p><script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>\n<p>So, this code: <\/p>\n<pre><code class=\"javascript\">import { opacify, transparentize } from 'polished'; \r\n<\/code><\/pre>\n<p>generates a much larger bundle than this code:<\/p>\n<pre><code class=\"javascript\">import opacify from 'polished\/lib\/color\/opacify.js';\r\nimport transparentize from 'polished\/lib\/color\/transparentize.js';\r\n<\/code><\/pre>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'><a href='https:\/\/webpack.js.org\/guides\/tree-shaking\/'>About tree-shaking<\/a><\/div>\n<div class='annotated-element__content'>\n<p>even despite the Polished\u2019s bundle is built with ES modules and tree-shaking is enabled.<\/p>\n<\/div>\n<\/div>\n<p>Let\u2019s find out what causes this.<\/p>\n<h1 id=\"investigation\">Investigation<a href=\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#investigation\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h1>\n<h2 id=\"1-verify-the-entry-point\">1. Verify the entry point<a href=\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#1-verify-the-entry-point\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'>Environment: <code>polished@1.2.0<\/code> and <code>webpack@2.6.1<\/code> (<code>webpack@3.0.0<\/code> gives the same result)<\/div>\n<div class='annotated-element__content'>\n<p>At first, let\u2019s check that <code>import { ... } from 'polished'<\/code> picks up a file written with ES exports. If it doesn\u2019t, webpack can\u2019t do any tree-shaking at all.<\/p>\n<\/div>\n<\/div>\n<p>When you import a package, webpack understands what exact file to use by looking <a href=\"https:\/\/webpack.js.org\/configuration\/resolve\/#resolve-mainfields\">into specific fields in <code>package.json<\/code><\/a>. Polished\u2019s <code>package.json<\/code> has two of them:<\/p>\n<pre><code class=\"javascript\">{\r\n  \"name\": \"polished\",\r\n  \"description\": \"A lightweight toolset for writing styles in Javascript.\",\r\n  \"main\": \"lib\/index.js\",  \/\/ This one\r\n  \"module\": \"dist\/polished.es.js\",  \/\/ And this one\r\n  ...\r\n}\r\n<\/code><\/pre>\n<p>Webpack prefers <code>module<\/code> over <code>main<\/code>. <code>module<\/code> points to <code>dist\/polished.es.js<\/code>, and this file does have an ES export:<\/p>\n<pre><code class=\"javascript\">\/\/ polished\/dist\/polished.es.js\r\n...\r\nexport { adjustHue$1 as adjustHue, ... };\r\n<\/code><\/pre>\n<p>This point is OK.<\/p>\n<h2 id=\"2-check-if-theres-unused-code-thats-unnecessarily-kept\">2. Check if there\u2019s unused code that\u2019s unnecessarily kept<a href=\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#2-check-if-theres-unused-code-thats-unnecessarily-kept\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p><code>polished\/dist\/polished.es.js<\/code> is written with ES exports. This means that tree-shaking should work properly, and the unused imports shouldn\u2019t be included into the bundle. Then why different imports produce different file sizes?<\/p>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'><em>Side effect<\/em> is when a function changes something outside of itself \u2013 e.g. writes a value to a global variable or initiates a network request<\/div>\n<div class='annotated-element__content'>\n<p>The most possible reason is that <code>polished\/dist\/polished.es.js<\/code> contains some code that\u2019s absent in our <code>polished\/lib\/...<\/code> files and that can\u2019t be simply dropped by the tree-shaker. This is the code that could cause side-effects. E.g. if a file includes a top-level function call, the tree-shaker can\u2019t remove the function even if its result isn\u2019t used. The function could be causing side effects, and removing it could break the app.<\/p>\n<\/div>\n<\/div>\n<p>Let\u2019s compare the bundles that we have after importing <code>polished<\/code> in two different ways and verify this case.<\/p>\n<p>To do this, I create a package:<\/p>\n<pre><code class=\"shell\"># Shell\r\nmkdir polished-test && cd polished-test\r\nnpm init -y\r\nnpm install polished webpack@2\r\n<\/code><\/pre>\n<p>Add two files that import Polished in two different ways:<\/p>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'><code>console.log()<\/code> helps finding the <code>index.js<\/code> file in the bundle + prevents webpack from removing the imports as unused<\/div>\n<div class='annotated-element__content'>\n<pre><code class=\"javascript\">\/\/ index-import-package.js\r\nimport { opacify, transparentize } from 'polished';\r\n\r\nconsole.log('polished', opacify, transparentize);\r\n\r\n\/\/ index-import-files.js\r\nimport opacify from 'polished\/lib\/color\/opacify.js';\r\nimport transparentize from 'polished\/lib\/color\/transparentize.js';\r\n\r\nconsole.log('polished', opacify, transparentize);\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p style=\"margin-top: 1.75em\">Add a special webpack configuration that emits two bundles:<\/p>\n<pre><code class=\"javascript\">\/\/ webpack.config.js\r\nconst webpack = require('webpack');\r\n\r\nmodule.exports = {\r\n  entry: {\r\n    \/\/ We\u2019ll compare two different bundles,\r\n    \/\/ thus two different entry points\r\n    'bundle-import-package': '.\/index-import-package.js',\r\n    'bundle-import-files': '.\/index-import-files.js',\r\n  },\r\n  output: {\r\n    filename: '[name].js',\r\n    path: __dirname,\r\n  },\r\n  plugins: [\r\n    \/\/ We need to run UglifyJS to remove the dead code\r\n    \/\/ (this will do tree-shaking), but prevent it\r\n    \/\/ from uglifying the code (so it\u2019s easier to read the bundle)\r\n    new webpack.optimize.UglifyJsPlugin({\r\n      \/\/ Disable several optimizations so that the bundle\r\n      \/\/ is easier to read\r\n      compress: { sequences: false, properties: false, conditionals: false, comparisons: false, evaluate: false, booleans: false, loops: false, hoist_funs: false, hoist_vars: false, if_return: false, join_vars: false, cascade: false },\r\n\r\n      \/\/ Beautify the bundle after uglifying it\r\n      beautify: true,\r\n\r\n      \/\/ Don\u2019t rename the variables\r\n      mangle: false,\r\n    }),\r\n  ]\r\n}\r\n<\/code><\/pre>\n<p>And run the build:<\/p>\n<pre><code class=\"shell\">.\/node_modules\/.bin\/webpack\r\n<\/code><\/pre>\n<p>Now, I have two bundles, each with a different approach to importing stuff. I open them in my editor and switch to the structure view to their content. And here\u2019s what I see:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/Untitled-1.png\" alt=\"A comparison between the content of two files. The left file is bundle-import-package.js, it has a lot of functions. The right file is bundle-import-files.js, it has much less functions.\" width=\"1800\" height=\"1200\" class=\"alignnone size-full wp-image-324\" style=\"border: 1px solid #ccc\" srcset=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/Untitled-1.png 1800w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/Untitled-1-300x200.png 300w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/Untitled-1-768x512.png 768w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/Untitled-1-1024x683.png 1024w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/Untitled-1-1200x800.png 1200w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/p>\n<p><code>bundle-import-package.js<\/code> has more methods than <code>bundle-import-files.js<\/code>. Most likely, they are kept because of calls with side effects. Let\u2019s dig deeper.<\/p>\n<h2 id=\"3-find-the-exact-cause-of-the-problem\">3. Find the exact cause of the problem<a href=\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#3-find-the-exact-cause-of-the-problem\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h2>\n<p>So, <code>bundle-import-package.js<\/code> has a lot of functions that aren\u2019t used but are still included. If we look through the file to see their usages, we\u2019ll see a large snippet of code like this:<\/p>\n<pre><code class=\"javascript\">\/\/ bundle-import-package.js\r\n\/\/ ...\r\nfunction opacify(amount, color) {\r\n    \/\/ ...\r\n}\r\nvar opacify$1 = curry(opacify);\r\nfunction desaturate(amount, color) {\r\n    \/\/ ...\r\n}\r\ncurry(desaturate);\r\nfunction lighten(amount, color) {\r\n    \/\/ ...\r\n}\r\ncurry(lighten);\r\n\/\/ ...\r\n<\/code><\/pre>\n<p>Here, <code>desaturate<\/code> and <code>lighten<\/code> are those unused functions, and <code>opacify<\/code> is a function we import in the client code.<\/p>\n<p>This code comes to <code>bundle-import-package.js<\/code> from <code>polished\/dist\/polished.es.js<\/code>. The corresponding code in that file looks like this:<\/p>\n<pre><code class=\"javascript\">\/\/ polished\/dist\/polished.es.js\r\n\/\/ ...\r\nfunction opacify(amount, color) {\r\n    \/\/ ...\r\n}\r\n\r\nvar opacify$1 = curry(opacify);\r\n\r\nfunction desaturate(amount, color) {\r\n    \/\/ ...\r\n}\r\n\r\nvar desaturate$1 = curry(desaturate);\r\n\r\nfunction lighten(amount, color) {\r\n    \/\/ ...\r\n}\r\n\r\nvar lighten$1 = curry(lighten);\r\n\/\/ ...\r\n<\/code><\/pre>\n<p>And this code comes into <code>polished\/dist\/polished.es.js<\/code> from the library sources. This is how it looks:<\/p>\n<pre><code class=\"javascript\">\/\/ polished\/src\/color\/opacify.js\r\nfunction opacify(amount: number, color: string): string {\r\n  \/\/ ...\r\n}\r\n\r\nexport default curry(opacify);\r\n\r\n\/\/ polished\/src\/color\/desaturate.js\r\nfunction desaturate(amount: number, color: string): string {\r\n  \/\/ ...\r\n}\r\n\r\nexport default curry(desaturate);\r\n\r\n\/\/ polished\/src\/color\/lighten.js\r\nfunction lighten(amount: number, color: string): string {\r\n  \/\/ ...\r\n}\r\n\r\nexport default curry(lighten);\r\n<\/code><\/pre>\n<p>So what happens here? <code>dist\/polished.es.js<\/code> is built with Rollup. When the library authors do a build, Rollup grabs all the modules and converts exports (<code>export default curry(lighten)<\/code>) into variable assignments (<code>var lighten$1 = curry(lighten)<\/code>).<\/p>\n<p>When we do <code>import { opacify, transparentize } from 'polished'<\/code>, webpack tries to compile <code>dist\/polished.es.js<\/code> and drop the unused code. It removes the <code>desaturate$1<\/code> and <code>lighten$1<\/code> variables because they aren\u2019t exported, but it can\u2019t drop the <code>curry(darken)<\/code> calls because <code>curry<\/code> could produce side-effects. And because functions like <code>desaturate<\/code> and <code>lighten<\/code> are passed into <code>curry()<\/code>, they are also kept in the bundle.<\/p>\n<figure id=\"attachment_308\" aria-describedby=\"caption-attachment-308\" style=\"width: 1920px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/idea64_2017-06-22_17-49-08.png\" alt=\"Screenshot of the editor\" width=\"1920\" height=\"1020\" class=\"alignnone size-full wp-image-320\" style=\"border: 1px solid #ccc\" srcset=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/idea64_2017-06-22_17-49-08.png 1920w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/idea64_2017-06-22_17-49-08-300x159.png 300w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/idea64_2017-06-22_17-49-08-768x408.png 768w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/idea64_2017-06-22_17-49-08-1024x544.png 1024w, https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/idea64_2017-06-22_17-49-08-1200x638.png 1200w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><figcaption id=\"caption-attachment-308\" class=\"wp-caption-text\">This is how you analyze the bundle: open the file structure, find a function that\u2019s absent in the other bundle, and search for its usages<\/figcaption><\/figure>\n<h1 id=\"solution\">Solution<a href=\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#solution\" class=\"heading-link\" aria-label=\"Link to this section\" title=\"Link to this section\">#<\/a><\/h1>\n<p>To decrease the bundle size, we should do one of the following things:<\/p>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'>Pure function is a function that doesn\u2019t produce side effects<\/div>\n<div class='annotated-element__content'>\n<ul>\n<li>tell UglifyJS that it\u2019s safe to remove <code>curry()<\/code> calls because it\u2019s pure\n<li>or move currying into the functions instead of wrapping them.\n<\/ul>\n<\/div>\n<\/div>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'>Another option is passing <code>compressor: { pure_funcs: &lbrack;'curry'&rbrack; }<\/code> to the UglifyJS options, but Polished can\u2019t control this<\/div>\n<div class='annotated-element__content'>\n<p>To tell UglifyJS that <code>curry()<\/code> calls are safe to remove, we have to mark each call with the <code>\/*#__PURE__*\/<\/code> annotation. This way, the minifier will understand that this call is pure and will be able to optimize it:<\/p>\n<\/div>\n<\/div>\n<div class='annotated-element annotated-element_has-code_no annotated-element_keep-size_no annotated-element_mobile-direction_content-then-annotation'>\n<div class='annotated-element__annotation'>We can\u2019t just add the <code>\/*#__PURE__*\/<\/code> annotation after <code>export default<\/code>. Rollup seems to remove comments if they are placed in that position<\/div>\n<div class='annotated-element__content'>\n<pre><code class=\"diff\">\/\/ polished\/src\/color\/lighten.js\r\nfunction lighten(amount: number, color: string): string {\r\n  \/\/ ...\r\n}\r\n \r\n- export default curry(lighten);\r\n+ const curriedLighten = \/*#__PURE__*\/curry(lighten);\r\n+ export default curriedLighten;\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p style=\"margin-top: 1.75em\">The second approach is to move currying into the functions body. With it, we should do something like this:<\/p>\n<pre><code class=\"diff\">\/\/ polished\/src\/color\/lighten.js\r\n- function lighten(amount: number, color: string): string {\r\n-   \/\/ method body\r\n- }\r\n+ function lighten(...args) {\r\n+   return applyCurried(function (amount: number, color: string): string {\r\n+     \/\/ method body\r\n+   }, args);\r\n+ }\r\n \r\n- export default curry(lighten);\r\n+ export default lighten;\r\n<\/code><\/pre>\n<p>I prefer the first approach because it (almost) doesn\u2019t complicate the code.<\/p>\n<p>After adding the <code>\/*#__PURE__*\/<\/code> annotations, minified <code>bundle-import-package.js<\/code> goes from 16 down to 11.8 kB. But that\u2019s not the end \u2013 <code>bundle-import-files.js<\/code> is still smaller (9.86 kB). This is because there\u2019re a few other places that should be optimized.<\/p>\n<p>I\u2019ll skip the part where I find them and jump right to the solution.<\/p>\n<ul>\n<li><b>Change 1 and 2.<\/b> Like with <code>curry()<\/code>, there\u2019re two other places where the export is wrapped into a function. It\u2019s <code>polished\/src\/helpers\/em.js<\/code> and <code>polished\/src\/helpers\/rem.js<\/code>. To optimize them, we should similarly add the <code>\/*#__PURE__*\/<\/code> annotations.<\/li>\n<li><b>Change 3.<\/b> In <code>polished\/src\/mixins\/normalize.js<\/code>, there\u2019re two global objects that use computed object properties. When they are compiled, Babel transforms them to call the Babel\u2019s <code>defineProperty<\/code> function. Because of this, UglifyJS can\u2019t remove them. To solve the problem, we should either move these objects into the <code>normalize()<\/code> function that uses them or wrap them into getter functions.<\/code><\/li>\n<\/ul>\n<p>And, when we apply these additional optimizations, we\u2019ll have this: <\/p>\n<pre><code class=\"nohighlight\">                   Asset     Size  Chunks             Chunk Names\r\n  bundle-import-files.js  9.87 kB       0  [emitted]  bundle-import-files\r\nbundle-import-package.js  7.76 kB       1  [emitted]  bundle-import-package\r\n<\/code><\/pre>\n<p><code>bundle-import-package.js<\/code> is now even smaller than <code>bundle-import-files.js<\/code>! Great.<\/p>\n<p>I\u2019ve submitted <a href=\"https:\/\/github.com\/styled-components\/polished\/pull\/204\">the pull request<\/a>.<\/p>\n<p><!--p class=\"perf-consulting-snippet\">\n<mark>+1s in loading time of your app is \u22127% in conversion.<\/mark> I can help you make it faster, just like I helped this project: <a href=\"https:\/\/iamakulov.com\/perf-consulting\">iamakulov.com\/perf-consulting<\/a>\n<\/p-->\n","protected":false},"excerpt":{"rendered":"<p>There\u2019s a library called Polished. It\u2019s a utility collection for writing styles in JavaScript. And it had a problem. Problem# A story in three tweets: Seems that import foo from &quot;pkg\/foo&quot; still more effective than import {foo} from &quot;pkg&quot; with wepback 2 even in simple cases \ud83d\ude41 &mdash; Valentin Semirulnik (@7rulnik) June 18, 2017 Yep. &hellip; <a href=\"https:\/\/iamakulov.com\/notes\/polished-webpack\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Case study: improving a popular library\u2019s size for webpack users&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[14,15,12],"class_list":["post-259","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-case-study","tag-performance","tag-webpack"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v23.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Case study: improving a popular library\u2019s size for webpack users - Ivan Akulov\u2019s blog<\/title>\n<meta name=\"description\" content=\"Polished is a utility library for writing styles in JavaScript. In this post, I\u2019ll go step-by-step in optimizing it for webpack users.\" \/>\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\/polished-webpack\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Case study: improving the Polished size for webpack users\" \/>\n<meta property=\"og:description\" content=\"There\u2019s a library called Polished which is a utility library for writing styles in JavaScript. In this post, I\u2019ll go step-by-step in optimizing it for webpack users.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/iamakulov.com\/notes\/polished-webpack\/\" \/>\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-06-22T21:43:22+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-08-18T14:36:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/chrome_2017-06-23_00-34-12.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1293\" \/>\n\t<meta property=\"og:image:height\" content=\"751\" \/>\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:title\" content=\"Case study: improving the Polished size for webpack users\" \/>\n<meta name=\"twitter:description\" content=\"There\u2019s a library called Polished which is a utility library for writing styles in JavaScript. In this post, I\u2019ll go step-by-step in optimizing it for webpack users.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/chrome_2017-06-23_00-34-12.png\" \/>\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=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/iamakulov.com\/notes\/polished-webpack\/\",\"url\":\"https:\/\/iamakulov.com\/notes\/polished-webpack\/\",\"name\":\"Case study: improving a popular library\u2019s size for webpack users - Ivan Akulov\u2019s blog\",\"isPartOf\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1.png\",\"datePublished\":\"2017-06-22T21:43:22+00:00\",\"dateModified\":\"2017-08-18T14:36:42+00:00\",\"author\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81\"},\"description\":\"Polished is a utility library for writing styles in JavaScript. In this post, I\u2019ll go step-by-step in optimizing it for webpack users.\",\"breadcrumb\":{\"@id\":\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/iamakulov.com\/notes\/polished-webpack\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#primaryimage\",\"url\":\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1.png\",\"contentUrl\":\"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1.png\",\"width\":318,\"height\":318},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/iamakulov.com\/notes\/polished-webpack\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/iamakulov.com\/notes\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Case study: improving a popular library\u2019s size for webpack users\"}]},{\"@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\/aec4e9e944911b58f2c3d14b7f9e5412a217e5738359c3f52e824b4de2b2263c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/aec4e9e944911b58f2c3d14b7f9e5412a217e5738359c3f52e824b4de2b2263c?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":"Case study: improving a popular library\u2019s size for webpack users - Ivan Akulov\u2019s blog","description":"Polished is a utility library for writing styles in JavaScript. In this post, I\u2019ll go step-by-step in optimizing it for webpack users.","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\/polished-webpack\/","og_locale":"en_US","og_type":"article","og_title":"Case study: improving the Polished size for webpack users","og_description":"There\u2019s a library called Polished which is a utility library for writing styles in JavaScript. In this post, I\u2019ll go step-by-step in optimizing it for webpack users.","og_url":"https:\/\/iamakulov.com\/notes\/polished-webpack\/","og_site_name":"Ivan Akulov\u2019s blog","article_publisher":"http:\/\/facebook.com\/iamakulov.page","article_published_time":"2017-06-22T21:43:22+00:00","article_modified_time":"2017-08-18T14:36:42+00:00","og_image":[{"width":1293,"height":751,"url":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/chrome_2017-06-23_00-34-12.png","type":"image\/png"}],"author":"Ivan Akulov","twitter_card":"summary_large_image","twitter_title":"Case study: improving the Polished size for webpack users","twitter_description":"There\u2019s a library called Polished which is a utility library for writing styles in JavaScript. In this post, I\u2019ll go step-by-step in optimizing it for webpack users.","twitter_image":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/chrome_2017-06-23_00-34-12.png","twitter_creator":"@iamakulov","twitter_site":"@iamakulov","twitter_misc":{"Written by":"Ivan Akulov","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/iamakulov.com\/notes\/polished-webpack\/","url":"https:\/\/iamakulov.com\/notes\/polished-webpack\/","name":"Case study: improving a popular library\u2019s size for webpack users - Ivan Akulov\u2019s blog","isPartOf":{"@id":"https:\/\/iamakulov.com\/notes\/#website"},"primaryImageOfPage":{"@id":"https:\/\/iamakulov.com\/notes\/polished-webpack\/#primaryimage"},"image":{"@id":"https:\/\/iamakulov.com\/notes\/polished-webpack\/#primaryimage"},"thumbnailUrl":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1.png","datePublished":"2017-06-22T21:43:22+00:00","dateModified":"2017-08-18T14:36:42+00:00","author":{"@id":"https:\/\/iamakulov.com\/notes\/#\/schema\/person\/ebf7b61bf573e7be5fe438f50ebd9b81"},"description":"Polished is a utility library for writing styles in JavaScript. In this post, I\u2019ll go step-by-step in optimizing it for webpack users.","breadcrumb":{"@id":"https:\/\/iamakulov.com\/notes\/polished-webpack\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/iamakulov.com\/notes\/polished-webpack\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/iamakulov.com\/notes\/polished-webpack\/#primaryimage","url":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1.png","contentUrl":"https:\/\/iamakulov.com\/notes2\/wp-content\/uploads\/2017\/06\/polished1.png","width":318,"height":318},{"@type":"BreadcrumbList","@id":"https:\/\/iamakulov.com\/notes\/polished-webpack\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/iamakulov.com\/notes\/"},{"@type":"ListItem","position":2,"name":"Case study: improving a popular library\u2019s size for webpack users"}]},{"@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\/aec4e9e944911b58f2c3d14b7f9e5412a217e5738359c3f52e824b4de2b2263c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/aec4e9e944911b58f2c3d14b7f9e5412a217e5738359c3f52e824b4de2b2263c?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\/259","targetHints":{"allow":["GET"]}}],"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=259"}],"version-history":[{"count":99,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts\/259\/revisions"}],"predecessor-version":[{"id":500,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/posts\/259\/revisions\/500"}],"wp:attachment":[{"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/media?parent=259"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/categories?post=259"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/iamakulov.com\/notes\/wp-json\/wp\/v2\/tags?post=259"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}