<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mono</title>
    <description>The latest articles on DEV Community by Mono (@monosoftware).</description>
    <link>https://dev.to/monosoftware</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1444%2F6beba28b-eba3-4dcf-9072-720d6b6db66e.png</url>
      <title>DEV Community: Mono</title>
      <link>https://dev.to/monosoftware</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/monosoftware"/>
    <language>en</language>
    <item>
      <title>Multiple webpack builds with shared vendors</title>
      <dc:creator>Dino Repac</dc:creator>
      <pubDate>Fri, 29 Nov 2019 13:06:08 +0000</pubDate>
      <link>https://dev.to/monosoftware/multiple-webpack-builds-with-shared-vendors-3729</link>
      <guid>https://dev.to/monosoftware/multiple-webpack-builds-with-shared-vendors-3729</guid>
      <description>&lt;p&gt;&lt;strong&gt;This blog post aims to teach you (and remind me) how to setup multiple client application build procedures with shared vendors. We will be using Asp.Net Core 2 and Webpack (with DllPlugin) to build our client-side code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recently, we had to set up a build procedure for multiple client applications within a &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/overview?view=aspnetcore-2.2"&gt;.NET Core MVC&lt;/a&gt; app. A mix of MVC and &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; was used to display a user interface and &lt;a href="https://mobx.js.org"&gt;MobX&lt;/a&gt; for client-side state management. To build client-side code, we used &lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;p&gt;Because we were using Webpack to build our code, we went on and used it to develop all of it, not just parts based on React and MobX. The requirement stated that the React part of the application has to be decoupled, and the core code (all of the UI logic and state) has to be built as a library. We didn't want React application to end up in that library; thus we used separate &lt;em&gt;webpack configs&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate webpack configs - success!
&lt;/h2&gt;

&lt;p&gt;We created a common config file that was mainly used for vendor optimizations. I won't go into the &lt;em&gt;optimization&lt;/em&gt; and caching strategies, but I encourage you to read this &lt;a href="https://medium.com/hackernoon/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758"&gt;blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, we created two specialized &lt;em&gt;webpack configs&lt;/em&gt; used to build core code and React code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// webpack.config.app.js&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./client/js/app.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nx"&gt;devtool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inline-source-map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name].js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./wwwroot/dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;library&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;libraryTarget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;umd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;umdNamedDefine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// webpack.config.react.js&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./client/ui/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name].js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./wwwroot/dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and a command to build it all (in package.json):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode &amp;lt;development/production&amp;gt; --config webpack.config.app.js --config webpack.config.react.js"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That was super easy - &lt;code&gt;npm run build&lt;/code&gt; and we are almost over! We just had to include scripts in the templates, and that was it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;asp-src-include=&lt;/span&gt;&lt;span class="s"&gt;"~/dist/modules/*.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;asp-src-include=&lt;/span&gt;&lt;span class="s"&gt;"~/dist/*.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  We have a problem...
&lt;/h3&gt;

&lt;p&gt;Now our library &lt;code&gt;app&lt;/code&gt; is undefined, the React application is not displaying!&lt;/p&gt;

&lt;p&gt;We can see that two builds occurred, and that is fine, because of the two &lt;em&gt;webpack configs&lt;/em&gt;. But, what we can also see is that multiple modules were built twice. I assumed that these modules differ and that one overwrites another. Let us test that out. We can split output files in each config and compare the output with tools like &lt;a href="http://kdiff3.sourceforge.net/"&gt;KDiff3&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We compared &lt;code&gt;vendor.babel.js&lt;/code&gt; files in &lt;code&gt;/dist/ui&lt;/code&gt; and &lt;code&gt;/dist/js&lt;/code&gt; folders.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ibxukUSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e611wbo0n07xmq5z1ajc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ibxukUSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e611wbo0n07xmq5z1ajc.png" alt="Comparison"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the files are not identical, meaning that one vendor file might not have everything needed for the other. This is precisely an issue in our case. So what are the possible solutions?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Split build to two different output folders and load that (probably the worst solution).&lt;/li&gt;
&lt;li&gt;Use hash in output (we still end up with duplicate vendors).&lt;/li&gt;
&lt;li&gt;Use shared vendors.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Solution - shared vendors
&lt;/h2&gt;

&lt;p&gt;We will use &lt;a href="https://webpack.js.org/plugins/dll-plugin/"&gt;DllPlugin&lt;/a&gt;. If you are coming from Microsoft stack, you will be (hopefully) familiar with the term DLL (Dynamic Link library).&lt;/p&gt;

&lt;p&gt;If not, in short, DLL is a library that can be used by multiple programs simultaneously. For more information, read &lt;a href="https://support.microsoft.com/en-gb/help/815065/what-is-a-dll"&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let us get back to Webpack DllPlugin. Essentially it is the same as described above. The plugin is splitted into two parts: &lt;em&gt;DllPlugin&lt;/em&gt; and &lt;em&gt;DllReferencePlugin&lt;/em&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Webpack DllPlugin:&lt;br&gt;
This plugin is used in a separate webpack config exclusively to create a dll-only-bundle. It creates a manifest.json file, which is used by the DllReferencePlugin to map dependencies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What we have to do?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create new webpack.config.vendors.js with DllPlugin.&lt;/li&gt;
&lt;li&gt;Define our dependencies.&lt;/li&gt;
&lt;li&gt;Add DllReferencePlugin to our &lt;em&gt;webpack.config.app.js&lt;/em&gt; &amp;amp; &lt;em&gt;webpack.config.react.js&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Add build script for vendors.&lt;/li&gt;
&lt;li&gt;Don't forget to include scripts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We create &lt;code&gt;webpack.config.vendors.js&lt;/code&gt; file just like any other Webpack config, but the entry point will point to our dependencies. Our dependencies are &lt;em&gt;react&lt;/em&gt;, &lt;em&gt;react-dom&lt;/em&gt;, &lt;em&gt;mobx&lt;/em&gt; and &lt;em&gt;mobx-react&lt;/em&gt;. If we do that, we will end up with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mobx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mobx-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vendors.[hash].js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./wwwroot/dist/vendors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;library&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vendor_lib_[hash]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DllPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vendor_lib_[hash]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./wwwroot/dist/vendors/vendor-manifest.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we can proceed to add &lt;em&gt;DllReferencePlugin&lt;/em&gt; into the &lt;code&gt;webpack.config.common.js&lt;/code&gt;. We also have to reference the manifest file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DllReferencePlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./wwwroot/dist/vendor-manifest.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We create a separate build script, especially for vendors, and run it before the main build. The existence of &lt;code&gt;vendor-manifest.json&lt;/code&gt; is &lt;strong&gt;required&lt;/strong&gt; for running two other builds. &lt;/p&gt;

&lt;p&gt;Running vendors build script generates &lt;code&gt;dist/vendors&lt;/code&gt; folder with all the vendors and the manifest. When we build the rest of the code, we end up with this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NPB4ivWJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/5c040j445l68g9vwse1u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NPB4ivWJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/5c040j445l68g9vwse1u.png" alt="Dist folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Notice the scripts with &lt;code&gt;~&lt;/code&gt;. These are shared scripts between vendors and our code (it may be different in your case). This was the side effect of the &lt;em&gt;optimization&lt;/em&gt; in the &lt;code&gt;webpack.config.common.js&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have to include our scripts in the correct order and test our app.&lt;/p&gt;

&lt;p&gt;The correct order would be: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;vendors&lt;/li&gt;
&lt;li&gt;shared scripts&lt;/li&gt;
&lt;li&gt;specific scripts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We have this in the &lt;code&gt;_Layout.cshtml&lt;/code&gt; at the bottom of the &lt;em&gt;body&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;asp-src-include=&lt;/span&gt;&lt;span class="s"&gt;"~/dist/vendors/vendors.*.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;asp-src-include=&lt;/span&gt;&lt;span class="s"&gt;"~/dist/vendors~**.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;asp-src-include=&lt;/span&gt;&lt;span class="s"&gt;"~/dist/app.**.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;asp-src-include=&lt;/span&gt;&lt;span class="s"&gt;"~/dist/react-app.**.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And we are finally done!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;DllPlugin allows you to separate your app and vendors. Your primary focus stays on the app you are developing, and you won't have to wait for vendors to build. You build them once, and you generally don't worry about them anymore.&lt;/p&gt;

&lt;p&gt;While there are many blog posts around this topic, I couldn't find a single one targeting ASP.NET Core 2. Entire code used for this blog post can be found here: &lt;a href="https://github.com/Nodios/SharedVendorsSampleApp"&gt;https://github.com/Nodios/SharedVendorsSampleApp&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Space for improvements and known issues
&lt;/h3&gt;

&lt;p&gt;If we try to add vendor optimization to the &lt;code&gt;webpack.config.vendors.js&lt;/code&gt; the build messes up &lt;code&gt;vendor-manifest.json&lt;/code&gt;. I am yet to find a reason why that happens. If you have an answer, please contact me. &lt;/p&gt;

&lt;p&gt;As you can see, incorporating scripts into the views is a tedious job. You have to be very careful with the ord&lt;br&gt;
er of the scripts; otherwise, your code won't work. I used &lt;a href="https://github.com/jantimon/html-webpack-plugin"&gt;HtmlWebpackPlugin&lt;/a&gt; to inject scrips in the view, but the problem is when you have multiple layouts and areas things tend to go out of hand - especially with shared scripts. If you have a solution to this, feel free to contact me as well.&lt;/p&gt;




&lt;p&gt;This article is originally published on &lt;a href="https://mono.software/2019/11/15/multiple-webpack-builds-with-shared-vendors/"&gt;Mono&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webpack</category>
      <category>aspnetcore</category>
      <category>vendors</category>
    </item>
    <item>
      <title>Supercharge your colors with the PostCSS color() function</title>
      <dc:creator>Mihael Tomić</dc:creator>
      <pubDate>Fri, 25 Oct 2019 09:17:20 +0000</pubDate>
      <link>https://dev.to/monosoftware/supercharge-your-colors-with-the-postcss-color-function-3be8</link>
      <guid>https://dev.to/monosoftware/supercharge-your-colors-with-the-postcss-color-function-3be8</guid>
      <description>&lt;p&gt;Colors provide an atmosphere crucial to our design. They communicate design intentions and send a message to the people. &lt;/p&gt;

&lt;p&gt;In this article, we will take a look how using plugins for &lt;a href="https://github.com/postcss/postcss" rel="noopener noreferrer"&gt;PostCSS&lt;/a&gt; can help us in defining a color theme for our website and how to use colors across our project.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the color function?
&lt;/h2&gt;

&lt;p&gt;CSS color function is a &lt;a href="https://drafts.csswg.org/css-color/#modifying-colors" rel="noopener noreferrer"&gt;W3C draft&lt;/a&gt; proposed by &lt;a href="https://github.com/tabatkins" rel="noopener noreferrer"&gt;Tab Atkins&lt;/a&gt; which will help us to modify base color with the assistance of color-adjusters like hue, saturation, lightness, tint, opacity, etc. If you are familiar with a graphic software like Photoshop, Affinity Photo or any similar software and its adjustments tools, this will sound familiar.&lt;/p&gt;

&lt;p&gt;In our case we will use a tool called &lt;a href="https://github.com/postcss/postcss-color-function" rel="noopener noreferrer"&gt;postcss-color-function&lt;/a&gt; - &lt;em&gt;a plugin to transform &lt;a href="http://dev.w3.org/csswg/css-color/#modifying-colors" rel="noopener noreferrer"&gt;W3C CSS color function&lt;/a&gt; to more compatible CSS.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;What is so wonderful about this? After browsers start to fully support specification and implement it, we can kick out the plugins and start using browser native CSS parsing for color function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining our color theme
&lt;/h2&gt;

&lt;p&gt;To create a functional color theme, we have to define the right colors for our project. The initial setup is important since it will help us create a starting point for simple color usage across all the (Post)CSS files.&lt;/p&gt;

&lt;p&gt;We will use a color naming tool from &lt;a href="http://www.color-blindness.com/color-name-hue/" rel="noopener noreferrer"&gt;Colblindor&lt;/a&gt; to assign a name to our hex colors. For this demo, we will use color palette created from the Star Wars™ The Last Jedi poster.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-886335965744082944-986" src="https://platform.twitter.com/embed/Tweet.html?id=886335965744082944"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-886335965744082944-986');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=886335965744082944&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkxidk4t3m38i01ahiaru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkxidk4t3m38i01ahiaru.png" alt="Color scheme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we will define variables* using the &lt;a href="https://github.com/postcss/postcss-simple-vars" rel="noopener noreferrer"&gt;postcss-simple-vars&lt;/a&gt; plugin which gives us the ability to write and use JS-like variables we're familiar from &lt;code&gt;Sass&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** Brand colors **/
$cinnabar: #DF3D2F;
$seal-brown: #080202;

/** Theme colors **/
$color-primary: $cinnabar;
$color-secondary: $seal-brown;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're finished with our setup. From now on - we will use only theme colors in our project.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;You can also use CSS variables which are W3C CR and not fully supported by all browsers. In our workflow we use PostCSS, and I'll use it in the following examples.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical use cases
&lt;/h2&gt;

&lt;p&gt;There's a lot of stuff we can do with color functions, and I'll cover some of them in following examples. I won't include all the adjusters; you can find them in documentation and explore in detail by yourself. &lt;/p&gt;

&lt;p&gt;The color function accepts many color spaces - you can use RGB, HSL/hwb, browser colors and HEX values and manipulate them.&lt;/p&gt;

&lt;p&gt;With the right combination of PostCSS plugins (for nesting, variables and color function) we can quickly create consistent and easily maintainable pseudo states for buttons in our project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Button pseudo state&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our HTML code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button type="submit"&amp;gt;Join me!&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;combined with our PostCSS...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;button {
  ...
  box-shadow: 1px 1px 3px color(black a(0.2));
  background-color: $color-primary;

  &amp;amp;:hover,
  &amp;amp;:active {
    background-color: color($color-primary lightness(+5%));
    box-shadow: 0px 3px 10px color(black a(0.4));
  }

  &amp;amp;:focus {
    background-color: color(black blackness(+10%));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...gives us a great level of control over the &lt;code&gt;button&lt;/code&gt; element. We can change our base colors as many times as we want without thinking about what will happen with the pseudo states.&lt;/p&gt;

&lt;p&gt;As you can see from compiled CSS, all values are &lt;em&gt;readable&lt;/em&gt; for all browsers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;button {
  box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);
  background-color: #DF3D2F;
}

button:hover,
  button:active {
  background-color: rgb(226, 83, 70);
  box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.4);
}

button:focus {
  background-color: rgb(196, 58, 46);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;View functional example on CodePen:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/mihaeltomic/embed/przMrG/?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Using color function with postcss-inline-svg
&lt;/h2&gt;

&lt;p&gt;One of the tools we use in our everyday projects is &lt;a href="https://github.com/TrySound/postcss-inline-svg" rel="noopener noreferrer"&gt;postcss-inline-svg&lt;/a&gt; - "&lt;em&gt;a plugin to inline SVG and customize its styles&lt;/em&gt;". I find the combination of these two plugins handy. Since CodePen does not support inline-svg plugin, I'll try to reproduce it through images and code examples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source PostCSS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.icon--empire {
    background-image: svg-load(../images/icon-delete.svg, fill: color($color-secondary lightness(+30%)));

  &amp;amp;:hover {
      background-image: svg-load(../images/icon-delete.svg, fill=$color-primary);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Compiled CSS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.icon--empire {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg fill='%23030303' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");

  &amp;amp;:hover {
      background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg fill='%23DF3D2F' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");

  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PostCSS would produce an SVG icon in &lt;code&gt;base64&lt;/code&gt; after compiling. &lt;/p&gt;

&lt;p&gt;&lt;a href="/img/blog/SuperchargeColorFunction/empire-crest.svg" class="article-body-image-wrapper"&gt;&lt;img src="/img/blog/SuperchargeColorFunction/empire-crest.svg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The good&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;The good thing about this approach is that you can generate icons easily through CSS and have color control for fill and stroke. All icons are in one place and can be used across as utils.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The bad&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There's no way (as far as I know) to add CSS classes and animate SVG through CSS paths or other elements in SVG. Also, there's no SVG code in our markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  To wrap it up
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;color() function&lt;/strong&gt; is a &lt;strong&gt;powerful tool&lt;/strong&gt; and can be used in many creative ways. After browsers start to support it fully, we will see its full potential. For now, we have tools to help us unlock that potential and use its benefits today.&lt;/p&gt;




&lt;p&gt;This one is an old article I wrote for &lt;a href="https://mono.software/2017/08/08/supercharge-your-colors/" rel="noopener noreferrer"&gt;Mono&lt;/a&gt;, but I feel it also belongs here, on Dev.to community.&lt;/p&gt;

</description>
      <category>postcss</category>
      <category>css</category>
      <category>color</category>
      <category>svg</category>
    </item>
  </channel>
</rss>
