<?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>Forem: JeB</title>
    <description>The latest articles on Forem by JeB (@jeb).</description>
    <link>https://forem.com/jeb</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%2Fuser%2Fprofile_image%2F87672%2F1a2e7cda-9147-417d-a3da-0193bdfaa1d7.jpeg</url>
      <title>Forem: JeB</title>
      <link>https://forem.com/jeb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jeb"/>
    <language>en</language>
    <item>
      <title>Open Source Series: Documentation</title>
      <dc:creator>JeB</dc:creator>
      <pubDate>Sun, 16 Feb 2020 18:14:56 +0000</pubDate>
      <link>https://forem.com/jeb/open-source-series-documentation-2m1c</link>
      <guid>https://forem.com/jeb/open-source-series-documentation-2m1c</guid>
      <description>&lt;h3&gt;
  
  
  or answering the what and how questions
&lt;/h3&gt;

&lt;p&gt;Hello and welcome to the third part of the “Open Source” journey.&lt;br&gt;
For those of you who haven’t read the previous parts or wonder what is the planned content for the next parts:&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/jeb/owning-an-open-source-part-1-38f2"&gt;Intro&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/jeb/owning-an-open-source-project-part-2-15ea"&gt;Starting a Project&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publicity (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Issues and PRs (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automation (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Versions management (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;In the previous parts we’ve discussed what Open Source is and how one can start a new open source project. &lt;br&gt;
The first two parts were targeted to those who consider creating an open source project, to let them know what to expect and give them some headstart in the open source world.&lt;/p&gt;

&lt;p&gt;This part, as well as the coming ones, will also be relevant to the people who already maintain an open source project and help them improve at what they do.&lt;/p&gt;

&lt;h3&gt;
  
  
  The baseline for this part:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;h1&gt;
  
  
  You already have an open source project, it is available on Github and it can be consumed easily via one of the package registries.
&lt;/h1&gt;
&lt;/blockquote&gt;

&lt;p&gt;*** If you have no idea what I’m talking about I suggest you to read the first two parts.&lt;/p&gt;

&lt;h2&gt;
  
  
  So here we go
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;h1&gt;
  
  
  An open source project without documentation is a dead project
&lt;/h1&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is dead because no one will dive into your code to find out how it should be used. And even before &lt;em&gt;how&lt;/em&gt;, no one even knows &lt;em&gt;what&lt;/em&gt; your code is supposed to do.&lt;/p&gt;

&lt;p&gt;So these are basically the two things that your documentation should contain — &lt;em&gt;what&lt;/em&gt; and &lt;em&gt;how&lt;/em&gt;. These are the corner stones, the must-haves of documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Description
&lt;/h2&gt;

&lt;p&gt;Description is the first thing everyone sees upon entering a Github repository. Therefore a good description should answer in a short and informative manner to the &lt;em&gt;what&lt;/em&gt; question. For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/facebook/react"&gt;React&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A declarative, efficient, and flexible JavaScript library for building user interfaces. &lt;a href="https://reactjs.org/"&gt;https://reactjs.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/moment/moment"&gt;Moment.js:&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Parse, validate, manipulate, and display dates in javascript. &lt;a href="http://momentjs.com/"&gt;http://momentjs.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/just-jeb/angular-builders"&gt;Angular builders&lt;/a&gt; (this one is mine):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Angular build facade extensions (Jest and custom webpack configuration)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The description can be edited by clicking on the Edit button at the top right of your repository:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  README.MD
&lt;/h3&gt;

&lt;p&gt;README.MD is a file in the root directory of your project written with &lt;a href="https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax"&gt;Markdown syntax&lt;/a&gt;, which contains all the information one needs to know about your project.&lt;/p&gt;

&lt;p&gt;The README file should contain a detailed description (which expands on the &lt;em&gt;what&lt;/em&gt; question) and very detailed instructions on &lt;em&gt;how&lt;/em&gt; to use you project. &lt;br&gt;
The instructions should cover every single piece of &lt;em&gt;public API&lt;/em&gt;, preferably with usage examples.&lt;/p&gt;

&lt;p&gt;A few points for writing a good API documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Keep it simple&lt;br&gt;
&lt;em&gt;The simpler the API and the example — the easier for a user to understand what it does on how to use it&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep it structured&lt;br&gt;
&lt;em&gt;Use the same template and visual structure for every API method, this way you’ll define your own language for communicating the API to the user&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be a user&lt;br&gt;
&lt;em&gt;Always write API description from the users perspective. Assume that you know nothing about the internals and this documentation is all you have.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep it up to date&lt;br&gt;
&lt;em&gt;As your project evolves the APIs might change. Make sure that your README file always contains the most actual APIs and examples&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The README can (but doesn’t have to) contain the following things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Link to a contribution guide&lt;/li&gt;
&lt;li&gt;List of contributors&lt;/li&gt;
&lt;li&gt;Link to a change log&lt;/li&gt;
&lt;li&gt;Latest version&lt;/li&gt;
&lt;li&gt;License&lt;/li&gt;
&lt;li&gt;Build status&lt;/li&gt;
&lt;li&gt;Downloads counter&lt;/li&gt;
&lt;li&gt;Link to a chat for fast feedback&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Badges
&lt;/h2&gt;

&lt;p&gt;Badges are a fairly good way to visually expose the essential info about your project, such as: build status, version, license and various tools used by your project.&lt;br&gt;
There are quite a few options but I’d recommend you use &lt;a href="https://shields.io/"&gt;shields.io&lt;/a&gt; badges. &lt;br&gt;
They have a badge for literally everything.&lt;/p&gt;

&lt;p&gt;Adding a badge to your README file is really simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://shields.io/"&gt;shields.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Choose the appropriate category&lt;/li&gt;
&lt;li&gt;Click on a badge you’d like to add to your README&lt;/li&gt;
&lt;li&gt;Fill in the required information (if any)&lt;/li&gt;
&lt;li&gt;Choose Copy Markdown from a drop down menu&lt;/li&gt;
&lt;li&gt;Paste the markdown into your README file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hSWiJI26--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4pzjplqu957gq7rb44oz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hSWiJI26--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4pzjplqu957gq7rb44oz.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The badges are usually put at the top of the README file right before the detailed description. This is what it looks like:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;p&gt;API reference is great, but nothing compares to a real code using your public APIs. &lt;br&gt;
One of the best ways to complement your documentation is having a good code coverage with descriptive tests. Sometimes tests explain the code better than any documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping it up
&lt;/h2&gt;

&lt;p&gt;In this part we’ve only covered the basics of documentation. It has a lot more than just a README or a description, for example, as your project grows and issues arise, they become an integral part of the documentation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h1&gt;
  
  
  However, having a README file that covers the public API is the bare minimum for any decent open source project
&lt;/h1&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks for reading, make sure you follow me here or on &lt;a href="https://twitter.com/_Just_JeB_"&gt;Twitter&lt;/a&gt; if you don’t want to miss the next part in which we’re going to talk about &lt;strong&gt;Publicity&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>Open Source Series: Starting a Project</title>
      <dc:creator>JeB</dc:creator>
      <pubDate>Wed, 22 Jan 2020 20:44:57 +0000</pubDate>
      <link>https://forem.com/jeb/owning-an-open-source-project-part-2-15ea</link>
      <guid>https://forem.com/jeb/owning-an-open-source-project-part-2-15ea</guid>
      <description>&lt;h3&gt;
  
  
  or how to open your project to the world
&lt;/h3&gt;

&lt;p&gt;Hello and welcome to the second part of the “Open Source” journey. For those of you who haven’t read the &lt;a href="https://dev.to/jeb/owning-an-open-source-part-1-38f2"&gt;first part&lt;/a&gt; or wonder what is the planned content for the next parts:&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/jeb/owning-an-open-source-part-1-38f2"&gt;Intro&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Starting a project&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/jeb/open-source-series-documentation-2m1c"&gt;Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spreading the word (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Getting collaborators (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Issues and PRs (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automation (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Versions management (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;In the previous part we’ve discussed what is Open Source and why anyone would bother with that. In this part we’re going to get more practical and we’ll discuss how one actually starts an open source project.&lt;/p&gt;

&lt;p&gt;So you’re in scenario #1, you have a solution for a specific problem and you’re eager to share it with the world. Let’s emphasize it again:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It’s not about your ego&lt;/li&gt;
&lt;li&gt;You’re not hoping to benefit from it&lt;/li&gt;
&lt;li&gt;You truly want to help others with the same problem&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you answered yes to all of these then here is a quick checklist for you to make sure you’re doing the right thing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make sure that open source is the right format. If it’s something small that you want to share with the world then a small blog post might be just enough.&lt;/li&gt;
&lt;li&gt;Double check that a similar project doesn’t exist already. Maybe your solution makes a perfect PR for an established open source project.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Be prepared for what’s coming
&lt;/h2&gt;

&lt;p&gt;As I mentioned, owning an open source project carries a lot of difficulties.&lt;/p&gt;

&lt;p&gt;One difficulty that stands out is that it requires a lot of your time. Everything that you do for your open source requires time, whether it’s writing code, managing issues, updating dependencies, talking to people, answering questions and etc. Every minute that you invest into your open source is a minute that you could have but didn’t invest in your family, your hobby, your health and what not.&lt;/p&gt;

&lt;p&gt;The only thing that you can do about it is delegation. &lt;br&gt;
When (or should I say “if”) you have enough collaborators you can outsource part of your responsibilities to the people you trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code separation
&lt;/h2&gt;

&lt;p&gt;So here we go, you have a solution for your specific problem and you think others can benefit from that. It is still integrated within your code base and you probably don’t want to make the whole code base an open source (unless you do).&lt;/p&gt;

&lt;p&gt;First you have to separate this code from the rest of your code base.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Start with refactoring
&lt;/h3&gt;

&lt;p&gt;…which will eventually cause all the code that is going to be opened to reside in a separate directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make it generic
&lt;/h3&gt;

&lt;p&gt;Make sure that the code in the new directory is generic and is not bound to your specific problem, make an abstraction layer if needed.&lt;/p&gt;

&lt;p&gt;As an example I started &lt;a href="https://github.com/just-jeb/angular-builders"&gt;angular-builders&lt;/a&gt; with a very specific need (coming from &lt;a href="https://github.com/just-jeb/electron-angular-native"&gt;one of my other open source projects&lt;/a&gt;) of adding custom loader for native modules to Angular build. &lt;br&gt;
I could have created &lt;em&gt;native-module-builder&lt;/em&gt; which would serve solely this very purpose. However, I realized that at a relatively low cost I can create a more generic solution that would solve similar (but not the same!) problems.&lt;/p&gt;

&lt;p&gt;This is how &lt;a href="https://github.com/just-jeb/angular-builders/tree/master/packages/custom-webpack"&gt;custom-webpack&lt;/a&gt; builder was born.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep it simple
&lt;/h3&gt;

&lt;p&gt;Generic is great but be careful not to get too excited about that.&lt;/p&gt;

&lt;p&gt;Premature optimization and over-generalization are two very well known problems in software engineering. You should find this sweet spot where your solution solves problems other than yours but &lt;em&gt;not all the problems in the world.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you build a scale where the solution for your specific problem is 1 and a solution for all the world problems is 100 then you should start with 2.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Your generic code should be able to solve a a few more problems than your specific code.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://en.wikipedia.org/wiki/Eating_your_own_dog_food"&gt;Eat your own dog food&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Keep using this generic code in your code base at every step — doing so makes sure you eliminate the unnecessary parts and leave only what’s needed. It also ensures that the code you’re going to open is working properly.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Remember, you are the very first user of your open source project.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Don’t get sued
&lt;/h3&gt;

&lt;p&gt;If you’re extracting the code from your company code base consult with your superiors and if needed with the legal department. Make sure that they support your initiative and that the code you’re going to open is not subject to the IP (intellectual property) of your company. This will also help you to decide which &lt;a href="https://opensource.org/licenses"&gt;open source license&lt;/a&gt; is more suitable for your project.&lt;/p&gt;

&lt;p&gt;When everything is working, the code is separated and is generic enough, you have all the approvals (if needed) - it is time to open it to the world.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Opening the project to the world
&lt;/h2&gt;

&lt;p&gt;Once your open source code is separated and generalized it’s time to disconnect it completely from your code base.&lt;/p&gt;

&lt;h3&gt;
  
  
  Going public
&lt;/h3&gt;

&lt;p&gt;First, you have to open the source code of your project (at the end of the day that what makes it an Open Source Project!). &lt;br&gt;
There are &lt;a href="https://stackify.com/source-code-repository-hosts/"&gt;different options&lt;/a&gt; for hosting source code online but we’ll go with the default — Github.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://help.github.com/en/github/getting-started-with-github/create-a-repo"&gt;Create a new repo&lt;/a&gt; on Github&lt;/li&gt;
&lt;li&gt;Clone the repository&lt;/li&gt;
&lt;li&gt;Move the sources from the directory you previously created (don’t remove the directory yet).&lt;/li&gt;
&lt;li&gt;Commit &amp;amp; push — voila it’s now an open source project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Or is it?&lt;/em&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Creating a package
&lt;/h3&gt;

&lt;p&gt;Your project is publicly available, but no one is using it (including you, since you’re using a copy of this code within your larger code base), and no one is aware of its existence.&lt;/p&gt;

&lt;p&gt;Furthermore the only format in which your project is publicly available on the web is the &lt;em&gt;source code&lt;/em&gt;, and the only way to consume it is copy-pasting the code into ones code base. Not a very convenient way, don’t you think?&lt;/p&gt;

&lt;p&gt;In order to properly distribute your project you have to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a package out of the source code&lt;/li&gt;
&lt;li&gt;Make this package available on one of the public package registries (depends on your ecosystem, for example, for Java it might be &lt;a href="https://search.maven.org/"&gt;Maven Central Repository&lt;/a&gt;, in the case of JavaScript it might be &lt;a href="https://www.npmjs.com/"&gt;Npm Package Registry&lt;/a&gt; and etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is when you add a build chain to your new shiny repository, define project name etc.&lt;/p&gt;

&lt;p&gt;I’m not going to break down the whole process because it is very dependent on your ecosystem, set of tools and language you are using.&lt;/p&gt;

&lt;p&gt;You might be an all around person to whom defining a new project as well as adding a build chain and publishing the package is a piece of cake. &lt;br&gt;
If this is the case — good for you!&lt;/p&gt;

&lt;p&gt;You also might be a person that is used to only write code but never faced all these definitions, configurations, artifacts and stuff like that. It might be a whole new world to you. &lt;br&gt;
Well, time to learn. Not going to be quick, I promise you that.&lt;/p&gt;

&lt;h3&gt;
  
  
  In any case
&lt;/h3&gt;

&lt;p&gt;When you’re done with filling all the missing puzzle pieces in your head, you’ve learned everything about the relevant package registry and your package is actually published, &lt;em&gt;then&lt;/em&gt; &lt;em&gt;and only then&lt;/em&gt; can you truly consider your project open source.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;At this point you can actually tell people: “Hey, I already have a solution to your problem, just add this package to your project and use it!”&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sanity check
&lt;/h3&gt;

&lt;p&gt;Before your project goes viral you better make sure it works.&lt;/p&gt;

&lt;p&gt;A sanity check for your package would be actually removing the generic directory from your larger code base and use the publicly available package instead. &lt;br&gt;
After all, &lt;em&gt;you’re the very first user of your open source project&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further development
&lt;/h3&gt;

&lt;p&gt;When you start using the package in your code base the development flow is likely to change: previously the now-open-source-code has been a part of your code base; you could consume the changes right away but now it’s as much of an external package as any other 3rd party package used in your code.&lt;/p&gt;

&lt;p&gt;Thus, when you develop a new feature in your shiny new open source project you’ll have to publish it first in order to be able to consume it in your larger code base. However you cannot publish it if you aren’t positive it works, because once published it might affect other users.&lt;/p&gt;

&lt;p&gt;So here are a few things you can do in order to avoid publishing broken versions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cover your code with tests, both unit tests and end-to-end tests.
&lt;em&gt;I don’t think I have to convince you how important the tests are.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Package and install the new version of the package locally, into your larger code base.
&lt;em&gt;Once verified that everything works as expected you may publish it.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Publish a beta version which is available only for those who explicitly want it rather than to the whole world.
&lt;em&gt;For example in npm package registry there are &lt;a href="https://docs.npmjs.com/cli/dist-tag"&gt;dist tags&lt;/a&gt; that can be used for this purpose. 
The default tag is &lt;code&gt;latest&lt;/code&gt; and when you run &lt;code&gt;npm install mypackage&lt;/code&gt; it effectively runs &lt;code&gt;npm install mypackage@latest&lt;/code&gt;. When you publish a new version under another tag, for instance &lt;code&gt;beta&lt;/code&gt;, one will have to explicitly install from this tag in order to get the latest version: 
&lt;code&gt;npm install mypackage@beta&lt;/code&gt;.&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrapping it up
&lt;/h2&gt;

&lt;p&gt;Unlike the previous part, which was completely theoretical, this part actually requires some work from you. Depending on your experience and learning abilities it might take you a few days or even weeks to complete this mandatory step. And we didn’t even start yet.&lt;br&gt;
This is why it is my duty to ask you again:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Are you really prepared to give a decent amount of your precious time to the community?
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks for reading, make sure you follow me here or on &lt;a href="https://twitter.com/_Just_JeB_"&gt;Twitter&lt;/a&gt; if you don’t want to miss the next part in which we’re going to talk about &lt;strong&gt;Documentation&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>Owning an Open Source Project: Part 1</title>
      <dc:creator>JeB</dc:creator>
      <pubDate>Sun, 05 Jan 2020 14:59:36 +0000</pubDate>
      <link>https://forem.com/jeb/owning-an-open-source-part-1-38f2</link>
      <guid>https://forem.com/jeb/owning-an-open-source-part-1-38f2</guid>
      <description>&lt;h3&gt;
  
  
  Intro or where the journey begins
&lt;/h3&gt;

&lt;p&gt;Have you ever thought of having your own open source project? &lt;br&gt;
I bet you have — you’re reading this article. Maybe you are thinking about it right now. Maybe you came here to better know what to expect, what challenges you’re going to face and how to deal with them.&lt;br&gt;
Well, you’ve come to the right place.&lt;/p&gt;

&lt;p&gt;In the following series of articles I’m going to share my personal experience in owning an open source project. Owning. Not contributing to an open source project but owning one. There is a big difference and in this series we’re going to learn why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Intro or where the journey begins&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/jeb/owning-an-open-source-project-part-2-15ea"&gt;Starting an open source project&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/jeb/open-source-series-documentation-2m1c"&gt;Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spreading the word (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Getting collaborators (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Managing issues and pull requests (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automation (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Breaking changes and back-ports (WIP)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who I am
&lt;/h2&gt;

&lt;p&gt;My name is JeB and I’ve been maintaining a few open source projects for a couple of years. The most popular one and the one from which I’ve learnt the most is &lt;a href="https://github.com/just-jeb/angular-builders"&gt;@angular-builders&lt;/a&gt;. At the moment of writing this article it has ~600 stars on Github and about 400k monthly downloads.&lt;/p&gt;

&lt;p&gt;Yes, it’s not even close to huge projects like Angular or React but I feel that I have enough experience to share with you in order to help you avoid the same mistakes I did and more important — to understand the cost of owning an open source project.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what is open source?
&lt;/h2&gt;

&lt;p&gt;Let’s first establish a common language and align on key terms and definitions.&lt;br&gt;
What is open source? Here is a very generic &lt;a href="https://en.wikipedia.org/wiki/Open_source_(disambiguation)"&gt;definition&lt;/a&gt; from a well known &lt;em&gt;Open Source&lt;/em&gt; Encyclopedia (aka Wikipedia):&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  &lt;a href="https://en.wikipedia.org/wiki/Open_source"&gt;Open source&lt;/a&gt; is the concept of the information allowing the replication or modification of something being open to the public.
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;or, in terms of &lt;a href="https://en.wikipedia.org/wiki/Open-source_model"&gt;software development&lt;/a&gt; models:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  The open-source model is a decentralized &lt;a href="https://en.wikipedia.org/wiki/Software_development"&gt;software development&lt;/a&gt; model that encourages &lt;a href="https://en.wikipedia.org/wiki/Open_collaboration"&gt;open collaboration&lt;/a&gt;.
&lt;/h3&gt;
&lt;h3&gt;
  
  
  A main principle of &lt;a href="https://en.wikipedia.org/wiki/Open-source_software_development"&gt;open-source software development&lt;/a&gt; is &lt;a href="https://en.wikipedia.org/wiki/Peer_production"&gt;peer production&lt;/a&gt;, with products such as source code, &lt;a href="https://en.wikipedia.org/wiki/Blueprint"&gt;blueprints&lt;/a&gt;, and documentation freely available to the public.
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the case of Wiki we have those who edit the articles (&lt;em&gt;contributors&lt;/em&gt;) and those who approve the edits (more experienced members, moderators). If we project it onto the software world the editors would form a core team of an open source project and the contributors would be, well, contributors.&lt;/p&gt;

&lt;p&gt;Wikipedia is a huge open source project but it has all started from &lt;a href="https://en.wikipedia.org/wiki/History_of_Wikipedia"&gt;something small&lt;/a&gt;. Wikipedia was born from Nupedia and it was born for a reason:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Despite its mailing list of interested editors, and the presence of a full-time editor-in-chief, &lt;a href="https://en.wikipedia.org/wiki/Larry_Sanger"&gt;Larry Sanger&lt;/a&gt;, a graduate &lt;a href="https://en.wikipedia.org/wiki/Philosophy"&gt;philosophy&lt;/a&gt; student hired by Wales, the writing of content for Nupedia was extremely slow, with only 12 articles written during the first year.
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;So here’s where the first question comes:&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bothering with open source
&lt;/h2&gt;

&lt;p&gt;As you can imagine from the previously read one of the main reasons for opening something to the wider audience is &lt;em&gt;to gain collaborators.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Together we’re strong
&lt;/h3&gt;
&lt;h3&gt;
  
  
  (Zarya, 2016)
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the moment of writing this article Wikipedia &lt;a href="https://en.wikipedia.org/wiki/Wikipedia:Wikipedians"&gt;has&lt;/a&gt; 37,899,499 registered accounts of which 134,022 are actively editing.&lt;/p&gt;

&lt;p&gt;Just think of it… &lt;strong&gt;&lt;em&gt;134,022 active collaborators.&lt;/em&gt;&lt;/strong&gt; Oh, and it &lt;a href="https://en.wikipedia.org/wiki/Special:Statistics"&gt;has&lt;/a&gt; 6M content pages!&lt;/p&gt;

&lt;p&gt;Would the numbers have been the same if Nupedia didn’t move to open source model? I highly doubt it.&lt;/p&gt;

&lt;p&gt;Nothing is different when it comes to the software. In order to solve a certain problem you have to write code. In order to solve a big problem you have to write a lot of code. In order to solve it properly you have to write high quality code, make a high quality design etc. All this &lt;em&gt;requires resources,&lt;/em&gt; which, let’s be honest, you don’t have. You have a rent to pay after all.&lt;/p&gt;

&lt;p&gt;While gaining collaborators is a reasonable incentive, almost no one starts a new open source project solely because of it. &lt;br&gt;
Obviously the reasons might be different but let’s talk about most popular ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Careful what you wish for
&lt;/h2&gt;

&lt;p&gt;A few scenarios that come across my mind are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You face a problem, there is nothing out there that solves it for you (or there is something but it costs money) so you have to solve it yourself, you manage to solve it, you’re really excited about your work and you think others can benefit from it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You want to be recognized as founder of an open source project, you want this fancy line in your CV, you have an ego (we’re all human after all). If this is the &lt;em&gt;main reason&lt;/em&gt; for you then I promise you, after reading this series you’ll reconsider — it’s not worth it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You face a problem, there is an open source project that actually solves it for you but it’s not good enough (in your opinion) or doesn’t have the exact feature you need. If you create a new open source project solely because of this then &lt;em&gt;most probably&lt;/em&gt; you’re at #2 (ego). Make yourself a contributor, create a PR to the existing project instead.&lt;br&gt;
&lt;em&gt;If the existing project has a different vision and making a PR is not an option you should consider either extending it by reusing its functionality in your project or &lt;a href="https://help.github.com/en/github/getting-started-with-github/fork-a-repo"&gt;forking&lt;/a&gt; it. It may save you a lot of headache later.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You face a problem, there is nothing out there that solves it for you and you think that starting the solution as open source from the very beginning is a very good idea.&lt;br&gt;
It’s not.&lt;br&gt;
Solve the problem, make sure it works for you and after that go to #1.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are the 4 incentives I find most popular for creating a new open source project but in this series we’re going to focus mainly on scenario #1.&lt;/p&gt;

&lt;p&gt;The reason is simple — I believe that if the &lt;em&gt;main reason&lt;/em&gt; for starting an open source project is other than eagerness to share and contribute then this won’t hold. &lt;br&gt;
For quite a long time the fact that you’re helping someone might be the only reward you get. And if this is not the kind of satisfaction you’re looking for then maybe you should stop here and not waste your time.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There is another quite popular scenario which is worth to mention.&lt;br&gt;
There are companies that open part of their code to the community. &lt;br&gt;
For example, Angular (maintained by Google), React (maintained by Facebook), VSCode (maintained by Microsoft) and more.&lt;br&gt;
The reasons for them to do that may vary but gaining collaborators and contributing to community are surely among them.&lt;br&gt;
While I can’t argue with the importance of this practice, this scenario is quite different from the others because employees that maintain such projects &lt;strong&gt;get paid&lt;/strong&gt; for their job. &lt;br&gt;
If you work at a company that considers the possibility of creating an open source project, the majority of the content here will be still relevant for you, however the incentives might be different.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping it up
&lt;/h2&gt;

&lt;p&gt;If I had to summarize this part in one sentence it would be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Make sure your intentions match your expectations
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;Believing that you want to have an open source project is not the same as actually having one, as you will see in the following articles.&lt;/p&gt;

&lt;p&gt;Thanks for reading, make sure you follow me here or on &lt;a href="https://twitter.com/_Just_JeB_"&gt;Twitter&lt;/a&gt; if you don’t want to miss the next part in which we’re going to talk about actually &lt;strong&gt;Starting an open source project&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>Angular 6: “ng test” with Jest in 3 minutes</title>
      <dc:creator>JeB</dc:creator>
      <pubDate>Tue, 21 Aug 2018 11:55:42 +0000</pubDate>
      <link>https://forem.com/jeb/angular-6-ng-test-with-jest-in-3-minutes-43l8</link>
      <guid>https://forem.com/jeb/angular-6-ng-test-with-jest-in-3-minutes-43l8</guid>
      <description>&lt;p&gt;Hey folks.&lt;/p&gt;

&lt;p&gt;Today I’m going to show you how to setup your Angular CLI workspace to work with &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; &lt;em&gt;while keeping it clear of boilerplate code&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I'm not going to explain why you should choose Jest over Karma, assuming you already did that choice, however I will give you a &lt;a href="https://www.xfive.co/blog/testing-angular-faster-jest/"&gt;link&lt;/a&gt; to an article that explains the reasons.&lt;/p&gt;

&lt;p&gt;So let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Jest
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Remove Karma related stuff:
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm remove karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter
rm src/karma.conf.js src/test.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Install &lt;a href="https://github.com/meltedspark/angular-builders/tree/master/packages/jest"&gt;@angular-builders/jest&lt;/a&gt; and &lt;code&gt;jest&lt;/code&gt;:
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D jest @angular-builders/jest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Update your Typescript configurations:
&lt;/h4&gt;

&lt;p&gt;Although you run your unit tests with Jest, Protractor (e2e tests) still &lt;a href="https://github.com/angular/protractor/issues/3889"&gt;has to use Jasmine&lt;/a&gt;. Due to this fact it’s possible that you favorite IDE will get confused with the typings and will propose you Jasmine types in unit tests or Jest types in e2e test. In order to avoid that kind of problems you have to specify the types explicitly:&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;tsconfig.spec.json&lt;/em&gt; (&lt;em&gt;src&lt;/em&gt; directory or project roots, used by Jest):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"compilerOptions": {
 ...
 "module": "commonjs",
 "types": ["jest"]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In &lt;em&gt;tsconfig.json&lt;/em&gt; (root directory, used by IDE):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"compilerOptions": {
    ...
    "types": ["jest"]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  In &lt;em&gt;angular.json&lt;/em&gt; change &lt;code&gt;@angular-devkit/build-angular:karma&lt;/code&gt; to &lt;code&gt;@angular-builders/jest:run&lt;/code&gt;:
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"projects": {
    ...
    "[your-project]": {
         ...
         "architect": {
                ...
                "test": {
                          "builder": "@angular-builders/jest:run"
                          "options": {
                                ...// see below
                          }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Detailed description of &lt;code&gt;options&lt;/code&gt; object can be found &lt;a href="https://github.com/meltedspark/angular-builders/tree/master/packages/jest#builder-options"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is it, now you can run your tests with Jest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the tests with Jest
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To run tests for all the projects in workspace: &lt;code&gt;ng test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;To run tests for a specific project &lt;em&gt;my-project&lt;/em&gt;: &lt;code&gt;ng test my-project&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You can specify &lt;a href="https://jestjs.io/docs/en/cli.html"&gt;Jest CLI options&lt;/a&gt; either in builder options (useful when it is a persistent config) or right to &lt;code&gt;ng test&lt;/code&gt; as a parameter (useful when it is a one-timer).  
For example to run a single test:  
&lt;code&gt;ng test --testNamePattern="My test suite My test case"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;If you’d like to learn more about builders and even considering creating one of your own check out &lt;a href="https://dev.to/meltedspark/angular-cli-6-under-the-hood-builders-demystified-2975"&gt;this&lt;/a&gt; article.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>jest</category>
      <category>unittest</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Angular CLI 6 under the hood  - builders demystified</title>
      <dc:creator>JeB</dc:creator>
      <pubDate>Tue, 07 Aug 2018 15:43:44 +0000</pubDate>
      <link>https://forem.com/jeb/angular-cli-6-under-the-hood-builders-demystified-2975</link>
      <guid>https://forem.com/jeb/angular-cli-6-under-the-hood-builders-demystified-2975</guid>
      <description>&lt;h3&gt;
  
  
  &lt;em&gt;Update&lt;/em&gt;:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The article is relevant up to Angular 7.2.x. &lt;br&gt;
In 7.3.0 this API has been deprecated (yet supported) and in 8.0.0 it will be replaced with the new API.&lt;br&gt;
The updated article is yet to come.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hey folks. Hope the sun is shining for you today.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/meltedspark/customizing-angular-cli-6-buildan-alternative-to-ng-eject-1oc4"&gt;previous article&lt;/a&gt; we talked about customizing Angular 6 build configuration without ejecting the underlying webpack configuration.&lt;/p&gt;

&lt;p&gt;The proposed solution was to use an &lt;em&gt;existing&lt;/em&gt; &lt;a href="https://github.com/meltedspark/angular-builders/tree/master/packages/custom-webpack"&gt;custom builder&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today we’ll take a look under the hood and create our own custom builder from scratch.&lt;/p&gt;
&lt;h2&gt;
  
  
  Angular CLI builders
&lt;/h2&gt;

&lt;p&gt;Angular CLI 6 came with a new architecture, basically a rewrite of the old CLI, which was broken down into small pieces.&lt;/p&gt;

&lt;p&gt;In fact, Angular CLI &lt;em&gt;itself&lt;/em&gt; has nothing to do with the configuration you provide in &lt;em&gt;angular.json&lt;/em&gt;, not anymore. Instead, it wraps &lt;a href="https://github.com/angular/angular-cli/tree/7.2.x/packages/angular_devkit"&gt;Angular Dev Kit&lt;/a&gt; and triggers &lt;em&gt;architect targets&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Briefly speaking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/angular/angular-cli/tree/7.2.x/packages/angular/cli"&gt;Angular CLI
package&lt;/a&gt;
contains pre-defined commands, help and CLI related stuff.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/angular/angular-cli/tree/7.2.x/packages/angular_devkit/architect"&gt;Architect package&lt;/a&gt; handles the configuration from &lt;em&gt;angular.json&lt;/em&gt;. It is responsible for mapping the architect target into the relevant builder, create the builder and trigger it with the configuration specified in &lt;em&gt;angular.json&lt;/em&gt; for this builder.&lt;/li&gt;
&lt;li&gt;Builders are the ones who do the actual job. Thus,&lt;a href="https://github.com/angular/angular-cli/tree/7.2.x/packages/angular_devkit/build_angular/src/browser"&gt;BrowserBuilder&lt;/a&gt; runs webpack build for browser target, &lt;a href="https://github.com/angular/angular-cli/tree/7.2.x/packages/angular_devkit/build_angular/src/karma"&gt;KarmaBuilder&lt;/a&gt; starts the Karma server and runs webpack build for unit tests and so on.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Angular CLI commands and architect targets
&lt;/h2&gt;

&lt;p&gt;When you run &lt;code&gt;ng build&lt;/code&gt; or &lt;code&gt;ng test&lt;/code&gt; or any of the &lt;a href="https://github.com/angular/angular-cli/wiki"&gt;predefined Angular CLI commands&lt;/a&gt; a few things happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Angular CLI command is transformed into a relevant architect target&lt;/li&gt;
&lt;li&gt;A relevant builder is created&lt;/li&gt;
&lt;li&gt;A relevant builder is triggered with the relevant configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you run a custom architect target, the following happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A relevant builder is created&lt;/li&gt;
&lt;li&gt;A relevant builder is triggered with the relevant configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see the only difference between the predefined command and custom architect target is that in the latter there is no mapping from the Angular CLI command to an architect target.&lt;/p&gt;

&lt;p&gt;In a nutshell there is one generic command &lt;code&gt;ng run&lt;/code&gt; , that receives an architect target as an argument (in format &lt;code&gt;project:target&lt;/code&gt; ) and asks the architect to execute this command.&lt;/p&gt;

&lt;p&gt;Thus, &lt;em&gt;each one&lt;/em&gt; of the predefined Angular CLI commands that are mapped to an architect target can be executed with &lt;code&gt;ng run&lt;/code&gt;. E.g:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ng build&lt;/code&gt;: &lt;code&gt;ng run my-cool-project:build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ng test&lt;/code&gt; : &lt;code&gt;ng run my-cool-project:test&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so on…&lt;/p&gt;

&lt;p&gt;The beauty is that once you’ve created your own builder you can put it in any architect target you want:&lt;/p&gt;

&lt;p&gt;You can create your own target, call it &lt;code&gt;my-target&lt;/code&gt; and execute it with &lt;br&gt;
&lt;code&gt;ng run my-cool-project:my-target&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;OR&lt;/p&gt;

&lt;p&gt;You can replace the builder in one of the existing targets (say, &lt;code&gt;build&lt;/code&gt; target) and execute it with the predefined Angular CLI command ( &lt;code&gt;ng build&lt;/code&gt; ), because as we’ve seen, Angular CLI commands are just &lt;em&gt;mappings into relevant architect targets&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architect targets configuration
&lt;/h2&gt;

&lt;p&gt;Let’s take a closer look on &lt;em&gt;angular.json&lt;/em&gt; file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "example": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
            ...
        },
        "serve": {
            ...
        },
      }          
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Inside each project there is an entry called &lt;code&gt;architect&lt;/code&gt; and it contains &lt;em&gt;architect targets&lt;/em&gt; configurations. Thus, in this particular example we have only one project called &lt;code&gt;example&lt;/code&gt; which, in turn, has two architect targets: &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;serve&lt;/code&gt;.&lt;br&gt;
If you wanted to add another architect target called, say, &lt;code&gt;format&lt;/code&gt; , the file would become:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "example": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {},
      "architect": {
        "build": {
            ...
        },
        "serve": {
            ...
        },            
        "format": {
            ...
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Every architect target configuration has 3 properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;builder&lt;/code&gt; — path to the builder.
The format of the path is &lt;code&gt;[package-path]:[builder-name]&lt;/code&gt;, where &lt;code&gt;[package-path]&lt;/code&gt; is a path to a folder with &lt;em&gt;package.json&lt;/em&gt; containing &lt;em&gt;builders&lt;/em&gt; entry and &lt;code&gt;[builder-name]&lt;/code&gt; is one of the entries in &lt;em&gt;builders.json&lt;/em&gt; (we’ll return to this later)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;options&lt;/code&gt; — the configuration of the builder. Must match the builder configuration schema, otherwise the command will fail.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configurations&lt;/code&gt; — a map of alternative target options (prod, dev etc.). This is
an optional property.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s pretty much it for the theoretical background.&lt;/p&gt;

&lt;p&gt;Enough talk, let’s do something real!&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating you own builder
&lt;/h2&gt;

&lt;p&gt;I’m not a fan of doing things in vain, so I had to come up with something more than just &lt;em&gt;Hello World Builder&lt;/em&gt;, yet as simple as &lt;em&gt;Hello World Builder&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So imagine you want to display the date and the time on which your application was built last time. The system is loading up, fetching some file that contains the timestamp for the latest build and the date is displayed in the page footer.&lt;/p&gt;

&lt;p&gt;What we’re going to do is implement a builder that creates this timestamp file.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating the package
&lt;/h3&gt;

&lt;p&gt;A single package can contain multiple builders but in our case it will contain only one.&lt;/p&gt;

&lt;p&gt;First thing after you’ve created a folder for your builders package is adding &lt;em&gt;package.json&lt;/em&gt; into this folder (architect assumes that builders package is an npm package).&lt;br&gt;
This &lt;em&gt;package.json&lt;/em&gt; is just a plain &lt;a href="https://docs.npmjs.com/files/package.json"&gt;package.json&lt;/a&gt; file with one additional entry:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"builders": "builders.json"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Spoiler: the file doesn’t have to be builders.json, can be any name you choose.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  builders.json
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;builders.json&lt;/code&gt; is a file that describes your builders. It’s a json file that&lt;br&gt;
follows Angular builders &lt;a href="https://github.com/angular/angular-cli/blob/7.2.x/packages/angular_devkit/architect/src/builders-schema.json"&gt;schema&lt;/a&gt; and has the following structure:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "$schema": "@angular-devkit/architect/src/builders-schema.json",
  "builders": {
    "builder-name": {
      "class": "path-to-builder-class",
      "schema": "path-to-builder-schema",
      "description": "builder-description"
    },
    ... more builders definitions
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Single &lt;code&gt;builders.json&lt;/code&gt; can contain definitions for multiple builders.&lt;/p&gt;
&lt;h3&gt;
  
  
  Builder definition
&lt;/h3&gt;

&lt;p&gt;Each builder is defined by two properties:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;code&gt;class&lt;/code&gt; — path to Javascript class that implements &lt;code&gt;Builder&lt;/code&gt; interface.
Architect will parse the configuration and create an instance of this class.
You can find the definition of the interface &lt;a href="https://github.com/angular/angular-cli/blob/7.2.x/packages/angular_devkit/architect/src/architect.ts"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;schema&lt;/code&gt; — path to json schema that defines builder configuration
( &lt;code&gt;options&lt;/code&gt; property in architect target definition).
Architect verifies the configuration against this schema and if the configuration is wrong it will fail the target.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here what our &lt;em&gt;builders.json&lt;/em&gt; will look like:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "$schema": "@angular-devkit/architect/src/builders-schema.json",
  "builders": {
    "file": {
      "class": "./timestamp.builder.js",
      "schema": "./schema.json",
      "description": "Builder that creates timestamp"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  schema.json
&lt;/h3&gt;

&lt;p&gt;Let’s say we want to allow the user to modify the format of the timestamp and the name of the file to which the timestamp will be saved.&lt;/p&gt;

&lt;p&gt;Thus, our &lt;em&gt;schema.json&lt;/em&gt; will look like this:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "id": "TimestampBuilderSchema",
  "title": "Timestamp builder",
  "description": "Timestamp builder options",
  "properties": {
    "format": {
      "type": "string",
      "description": "Timestamp format",
      "default": "dd/mm/yyyy"
    },
    "path": {
      "type": "string",
      "description": "Path to the timestamp file",
      "default": "./timestamp"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If the user hasn’t specified any options in the architect target configuration, architect will pick up the defaults from the schema.&lt;/p&gt;
&lt;h3&gt;
  
  
  Installing dependencies
&lt;/h3&gt;

&lt;p&gt;To format the Date we will use &lt;a href="https://www.npmjs.com/package/dateformat"&gt;dateformat&lt;/a&gt; package, let’s install it: &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i dateformat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We’re going to develop our builder with Typescript (though it’s not mandatory) so we have to install it too. &lt;br&gt;
We will also seize the functionality of &lt;code&gt;@angular-devkit/core&lt;/code&gt; as well as some of the interfaces from &lt;code&gt;@angular-devkit/architect&lt;/code&gt;. &lt;br&gt;
To benefit from Typescript static typing we will probably want to install &lt;code&gt;@types&lt;/code&gt; for &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;dateformat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is it for &lt;em&gt;devDependencies&lt;/em&gt; ( &lt;code&gt;@angular-devkit&lt;/code&gt; will be used at runtime but rather as a peer dependency). Let’s install them:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D @angular-devkit/core @angular-devkit/architect @types/node @types/dateformat typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  The builder
&lt;/h3&gt;

&lt;p&gt;Now we’re ready to implement the builder itself.&lt;br&gt; First of all let’s define our builder configuration as an interface in &lt;em&gt;schema.d.ts&lt;/em&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Once we have the interface we can implement the generic &lt;code&gt;Builder&lt;/code&gt; interface:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;run&lt;/code&gt; method should return an Observable of &lt;code&gt;BuildEvent&lt;/code&gt; that looks like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;BuildEvent&lt;/code&gt; will notify the architect of successful or unsuccessful execution,&lt;br&gt;
and architect, in turn, will pass the execution result to CLI that will&lt;br&gt;
eventually finish the process with appropriate exit value.&lt;/p&gt;

&lt;p&gt;In our case we want to return success if the file with the timestamp was&lt;br&gt;
successfully created and failure otherwise:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let’s break it down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; First of all we get the root (which is the root folder of the host application)&lt;/li&gt;
&lt;li&gt; Next we retrieve the &lt;code&gt;path&lt;/code&gt; and the &lt;code&gt;format&lt;/code&gt; from the options. These should be specified in architect target configuration in &lt;em&gt;angular.json&lt;/em&gt; of host application. If none were specified, the default values will be taken from the builder’s schema.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;getSystemPath&lt;/code&gt; is a utility function that returns system specific path and we concatenate it with the relative &lt;code&gt;path&lt;/code&gt; from the options.&lt;/li&gt;
&lt;li&gt; We use &lt;code&gt;writeFile&lt;/code&gt; function from &lt;code&gt;fs&lt;/code&gt; module but since we have to return an Observable and &lt;code&gt;writeFile&lt;/code&gt; works with callbacks, we use &lt;code&gt;bindNodeCallback&lt;/code&gt; function to transform it into a function that returns Observable.&lt;/li&gt;
&lt;li&gt; We format the date with the &lt;code&gt;formatDate&lt;/code&gt; function while using the &lt;code&gt;format&lt;/code&gt; we’ve got from the options and write the formatted date to the file.&lt;/li&gt;
&lt;li&gt; Finally we return success if the file was created successfully and return
failure otherwise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Side node: use the logger to provide build information to the user&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Compile the source code to JavaScript and you’re good to go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the builder
&lt;/h3&gt;

&lt;p&gt;Now when the builder is ready you can use it by either specifying a relative&lt;br&gt;
path to the folder in &lt;em&gt;angular.json:&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"architect": {
        "timestamp": {
          "builder": "[relative-path-to-package]/timestamp:file",
          "options": {}
        }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;… or packing it into npm package and installing it locally:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm pack
cp angular-builders-timestamp-1.0.0.tgz [host-application-root]
cd [host-application-root]
npm i -D angular-builders-timestamp-1.0.0.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;angular.json:&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"architect": {
        "timestamp": {
          "builder": "@angular-builders/timestamp:file",
          "options": {}
        }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;… or publishing it on npm and installing from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finishing words
&lt;/h2&gt;

&lt;p&gt;I hope you enjoyed the article and understand the concept better now.&lt;br&gt;
I also hope the sun is still shining and you didn’t spend all the day on this booooooring stuff.&lt;/p&gt;

&lt;p&gt;If you’re into open source and have some brilliant idea for a builder that can be useful for everyone, you’re welcome to contribute to &lt;a href="https://github.com/meltedspark/angular-builders"&gt;angular-builders&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;All the source code of the timestamp builder (as well as the example app that uses this builder) is available on &lt;a href="https://github.com/meltedspark/angular-builders/tree/master/packages/timestamp"&gt;github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Customizing Angular CLI 6 build  - an alternative to ng eject</title>
      <dc:creator>JeB</dc:creator>
      <pubDate>Fri, 27 Jul 2018 16:00:53 +0000</pubDate>
      <link>https://forem.com/jeb/customizing-angular-cli-6-buildan-alternative-to-ng-eject-1oc4</link>
      <guid>https://forem.com/jeb/customizing-angular-cli-6-buildan-alternative-to-ng-eject-1oc4</guid>
      <description>&lt;p&gt;So your Angular 6 project just went a bit beyond TODO app and you have to customize your build configuration. &lt;br&gt;
The question is how?&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular CLI 1.x ng eject VS Angular CLI 6 builders
&lt;/h2&gt;

&lt;p&gt;In Angular CLI 1.x (Angular 5) you had &lt;a href="https://github.com/angular/angular-cli/wiki/1-x-eject"&gt;&lt;code&gt;ng eject&lt;/code&gt;&lt;/a&gt; command for this, which was ejecting the whole underlying webpack configuration and allowing you to modify it as you please.&lt;/p&gt;

&lt;p&gt;In Angular CLI 6 this command has been temporarily disabled, and I suspect that it will be deprecated soon due to the new concept called &lt;strong&gt;Builders&lt;/strong&gt;.&lt;br&gt;
With the new Angular CLI you can customize the build process by defining your own builders as well as using one of the builders provided by the community.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extending underlying webpack configuration
&lt;/h2&gt;

&lt;p&gt;So lets go ahead and customize our build by extending the underlying webpack configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Install &lt;a href="https://github.com/meltedspark/angular-builders/packages/custom-webpack"&gt;@angular-builders/custom-webpack&lt;/a&gt;: &lt;code&gt;npm i -D @angular-builders/custom-webpack&lt;/code&gt;. &lt;br&gt;
&lt;em&gt;Note that it requires version &lt;a href="https://npmjs.com/package/@angular-devkit/build-angular"&gt;@angular-devkit/build-angular&lt;/a&gt;&amp;gt;=0.7.0 so you might need to install it (if not yet installed)&lt;/em&gt;: &lt;br&gt;
&lt;code&gt;npm i -D @angular-devkit/build-angular&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;em&gt;angular.json&lt;/em&gt; change the &lt;code&gt;@angular-devkit/build-angular:browser&lt;/code&gt; builder to &lt;code&gt;@angular-builders/custom-webpack:browser&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;architect&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;builder&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="s2"&gt;@angular-builders/custom-webpack:browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;options&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;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;ul&gt;
&lt;li&gt;&lt;p&gt;If you build a universal app and would like to modify your server build configuration use &lt;code&gt;@angular-builders/custom-webpack:server&lt;/code&gt; instead of &lt;code&gt;@angular-builders/custom-webpack:browser&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code&gt;customWebpackConfig&lt;/code&gt; to the &lt;em&gt;build&lt;/em&gt; target options :&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;architect&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;builder&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="s2"&gt;@angular-builders/custom-webpack:browser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;options&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customWebpackConfig&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&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="s2"&gt;./extra-webpack.config.js&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the full description of &lt;code&gt;customWebpackConfig&lt;/code&gt; object &lt;a href="https://github.com/meltedspark/angular-builders/tree/master/packages/custom-webpack#custom-webpack-config-object"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create &lt;em&gt;extra-webpack.config.js&lt;/em&gt; in the root of your application (or whatever path you specified in &lt;em&gt;angular.json&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Fill it with extra configuration you need (plain webpack configuration).&lt;/li&gt;
&lt;li&gt;Note that in contrary to &lt;code&gt;ng eject&lt;/code&gt; this configuration will be &lt;em&gt;merged&lt;/em&gt; with the default Angular build configuration so you only have to configure the part you want to change/add.  
For example, if you want to add another webpack loader, your webpack config will look like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;rules&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="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;cool$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cool-loader&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;h2&gt;
  
  
  And what about ng serve?
&lt;/h2&gt;

&lt;p&gt;If you want to run &lt;code&gt;ng serve&lt;/code&gt; with custom webpack configuration (given you performed all the above steps) you should do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;a href="https://github.com/meltedspark/angular-builders/tree/master/packages/dev-server"&gt;@angular-builders/dev-server&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Replace &lt;code&gt;@angular-devkit/build-angular:dev-server&lt;/code&gt; inside the serve target with &lt;code&gt;@angular-builders/dev-server:generic&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;ng serve&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional sources
&lt;/h2&gt;

&lt;p&gt;You can check out this &lt;a href="https://github.com/meltedspark/electron-angular-native"&gt;electron-angular-native&lt;/a&gt; project for the example of Electron Angular application with &lt;em&gt;node addons&lt;/em&gt; built with Angular CLI 6.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is next
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/meltedspark/angular-cli-6-under-the-hood-builders-demystified-2975"&gt;next article&lt;/a&gt; we will learn how to create your own builder.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>build</category>
      <category>webpack</category>
    </item>
  </channel>
</rss>
