<?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: mmiask</title>
    <description>The latest articles on DEV Community by mmiask (@mmiask).</description>
    <link>https://dev.to/mmiask</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%2F413154%2F792e0076-9e08-4fb3-a00b-f93a0102d53f.jpeg</url>
      <title>DEV Community: mmiask</title>
      <link>https://dev.to/mmiask</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mmiask"/>
    <language>en</language>
    <item>
      <title>Career change to IT - things you wish you knew</title>
      <dc:creator>mmiask</dc:creator>
      <pubDate>Mon, 06 Dec 2021 12:48:53 +0000</pubDate>
      <link>https://dev.to/mmiask/career-change-to-it-things-you-wish-you-knew-34ek</link>
      <guid>https://dev.to/mmiask/career-change-to-it-things-you-wish-you-knew-34ek</guid>
      <description>&lt;p&gt;Hi!&lt;/p&gt;

&lt;p&gt;I'm Michał and I'm a self-taught web developer, who started working in IT as a manual QA in December 2019. Before that I worked in biotech industry, including a pharmaceutical company in Poland.&lt;/p&gt;

&lt;p&gt;I remember the very beginning of my career change and how much work it required (including some proper motivation). All of the doubt, roadblocks but also the excitement of learning stuff in a completely new (to me) field.&lt;/p&gt;

&lt;p&gt;If there are people here switching to IT, or who successfully did that - &lt;strong&gt;what is your experience? What questions did you have at the beggining of the road that you wish were answered back then?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I want to create an episode of a podcast on the above topic (a live Q&amp;amp;A) where me and a bunch of other people with a similiar experience answer the questions that you would like answered. Is there something you think should be covered in that kind of content? &lt;strong&gt;What confused you the most when switching to IT?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thanks in advance and (hopefully) see you soon! &lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>beginners</category>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>Yarn.lock: how it works and what you risk without maintaining yarn dependencies — deep dive</title>
      <dc:creator>mmiask</dc:creator>
      <pubDate>Fri, 03 Sep 2021 18:13:20 +0000</pubDate>
      <link>https://dev.to/mmiask/yarn-lock-how-it-works-and-what-you-risk-without-maintaining-yarn-dependencies-deep-dive-62a</link>
      <guid>https://dev.to/mmiask/yarn-lock-how-it-works-and-what-you-risk-without-maintaining-yarn-dependencies-deep-dive-62a</guid>
      <description>&lt;p&gt;Coding is fun, there's no doubt about it.&lt;/p&gt;

&lt;p&gt;Other things that are fun: Testing! Code maintenance! Keeping dependencies in sync!&lt;/p&gt;

&lt;p&gt;No? Only for me? Well, it might not be fun for many of you, but to keep your library/application working properly you'll need to adapt and at least try some of it.&lt;/p&gt;

&lt;p&gt;If you have written a JavaScript library and published it on NPM (Node Package Manager), at some point in its development lifecycle you have experienced inconsistent behavior and you didn’t know the root cause. It was working fine for you and some of your coworkers/contributors, but crashing for everybody else. What is going on here?&lt;/p&gt;

&lt;p&gt;There is a high chance it was caused by unhandled dependencies in your project. This article addresses that problem and focuses on a very specific task: lockfile maintenance. I'll show you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What &lt;code&gt;yarn.lock&lt;/code&gt; (lockfile) is&lt;/li&gt;
&lt;li&gt;Why do you need to do lockfile maintenance&lt;/li&gt;
&lt;li&gt;What is the possible solution&lt;/li&gt;
&lt;li&gt;What mistakes we've made and how you can avoid them&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: Everything mentioned below is based on true events. No developers were harmed during implementation and/or for the purposes of this article&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;For the last few months, I've been working at &lt;strong&gt;Stoplight&lt;/strong&gt;, as a part of &lt;strong&gt;11Sigma&lt;/strong&gt;, on an open-source library called &lt;a href="https://stoplight.io/open-source/elements/" rel="noopener noreferrer"&gt;Elements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;a href="https://github.com/stoplightio/elements/issues/989" rel="noopener noreferrer"&gt;issue&lt;/a&gt; emerged in our library integration that made us &lt;a href="https://github.com/stoplightio/json-schema-viewer/pull/121" rel="noopener noreferrer"&gt;challenge our belief&lt;/a&gt; that our dependencies are under control. In short, our app crashed because of a bug in a dependency’s dependency. Despite fixing the nested dependency, the issue remained to be unsolved.&lt;/p&gt;

&lt;p&gt;Fortunately, it turned out to be a non-issue on a fresh install of &lt;code&gt;Elements&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately, that meant that we weren't testing what users were using at a given moment.&lt;/p&gt;

&lt;p&gt;In order to understand this issue fully, we first need to learn about the lockfile itself and how dependencies are installed in a project.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a lockfile?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are familiar with how a lockfile works, feel free to skip to &lt;em&gt;“Problem - A Second Look”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand why the topic of this article is important to you, it is necessary to know what a lockfile is and how it works. Although it can have different names depending on whether you use &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;yarn&lt;/code&gt;, the premise is pretty much the same. I'm using &lt;code&gt;yarn&lt;/code&gt; so I'll use &lt;code&gt;yarn.lock&lt;/code&gt; as an example in this article.&lt;/p&gt;

&lt;p&gt;When you run &lt;code&gt;yarn&lt;/code&gt; in your project, two things can happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A lockfile (&lt;code&gt;yarn.lock&lt;/code&gt;) is generated (if there isn't any) according to the contents of &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Packages are installed according to contents of an existing &lt;code&gt;yarn.lock&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; When you install dependencies in your application or library, only the top-level &lt;code&gt;yarn.lock&lt;/code&gt; file is respected. Lockfiles within your dependencies will be ignored.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When present in the project, &lt;code&gt;yarn.lock&lt;/code&gt; is the main source of information about the current versions of dependencies in a project. &lt;code&gt;Yarn&lt;/code&gt; uses that information to check if it needs to update anything - it compares dependency versions currently installed in a project (listed in &lt;code&gt;yarn.lock&lt;/code&gt;) to version restrictions in &lt;code&gt;package.json&lt;/code&gt; and updates packages if needed. Information from the lockfile can be further used by other users to create a repeatable environment elsewhere.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Generating &lt;code&gt;yarn.lock&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Whenever you run &lt;code&gt;yarn&lt;/code&gt; (which is the equivalent of running &lt;code&gt;yarn install&lt;/code&gt;) upon a fresh install, a &lt;code&gt;yarn.lock&lt;/code&gt; file is generated. It lists the versions of dependencies that are used at the time of the installation process. That means it looks into your &lt;code&gt;package.json&lt;/code&gt; and depending on the versioning syntax, it will install your project dependencies, then their dependencies, then their dependencies, and so on...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For more info about dependency versioning check &lt;a href="https://docs.npmjs.com/cli/v7/configuring-npm/package-json#dependencies" rel="noopener noreferrer"&gt;this link&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's say your project uses two dependencies: &lt;code&gt;chicken&lt;/code&gt; and &lt;code&gt;farm&lt;/code&gt;. Both of these are external packages, over which we don't have any control:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;project)&lt;/span&gt;&lt;span class="w"&gt;

 &lt;/span&gt;&lt;span class="err"&gt;dependencies:&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;"chicken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"farm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.3.0"&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;and &lt;code&gt;farm&lt;/code&gt; package uses a pinned (specific) version of &lt;code&gt;chicken&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(`farm`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package)&lt;/span&gt;&lt;span class="w"&gt;

 &lt;/span&gt;&lt;span class="err"&gt;dependencies:&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;"chicken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&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;This will result in your project requiring two versions of &lt;code&gt;chicken&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1.0.0 for the &lt;code&gt;farm&lt;/code&gt; dependency&lt;/li&gt;
&lt;li&gt;^1.2.0 as defined in your project's &lt;code&gt;package.json&lt;/code&gt;. This will vary upon a fresh install depending on whatever the latest version after &lt;code&gt;1.2.0&lt;/code&gt; is - the &lt;code&gt;^&lt;/code&gt; symbol allows changes that do not modify the left-most non-zero element in the version number. For this particular version range, it means 1.2.0 &amp;lt;= installed version &amp;lt; 2.0.0. To give an example - if &lt;code&gt;v1.2.4&lt;/code&gt; is available at the moment of (fresh) installation of your project, it will be installed. Same for &lt;code&gt;v1.5.8&lt;/code&gt;, &lt;code&gt;v1.7.2&lt;/code&gt;, &lt;code&gt;v1.9.9&lt;/code&gt;, but not for &lt;code&gt;v2.0.0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of these versions will be present in the &lt;code&gt;yarn.lock&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The folder structure will look like this:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6hss6500xussviv59i7.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6hss6500xussviv59i7.png" alt="folder-structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, you have probably noticed that this isn’t a perfect situation - if a sub-dependency (&lt;code&gt;chicken&lt;/code&gt;) has a bug introduced in one of its versions, and dependency that uses it (‘farm’) doesn’t pin the version - it could introduce a bug to your project.&lt;/p&gt;

&lt;p&gt;There is a bright side though - if your project requires &lt;code&gt;chicken&lt;/code&gt; and uses that same/matching version range, e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;dependencies:&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;"chicken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&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;you won’t install two versions of the &lt;code&gt;chicken&lt;/code&gt; package. This decreases the size of your project and prevents potential conflicts between different versions of the same package.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating the lockfile
&lt;/h3&gt;

&lt;p&gt;Updating the lockfile is a bit easier to explain. An update can happen in 3 situations: When the dependency is added, removed, or modified.&lt;/p&gt;

&lt;p&gt;This can happen in two ways:  Automagically or manually. You can trigger an update via &lt;code&gt;yarn&lt;/code&gt; CLI (which updates both &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;yarn.lock&lt;/code&gt;) using the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# adding dependencies&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; yarn add PACKAGE-NAME

&lt;span class="c"&gt;# removing dependencies&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; yarn remove PACKAGE-NAME

&lt;span class="c"&gt;# upgrading all dependencies&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; yarn upgrade

&lt;span class="c"&gt;# upgrading a specific package&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; yarn upgrade PACKAGE-NAME

&lt;span class="c"&gt;# Adding the `--latest` flag at the end of ‘upgrade’ commands makes yarn ignore the specified version range and install the latest version(s).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to go the manual update route, you modify the contents of &lt;code&gt;package.json&lt;/code&gt; and then run &lt;code&gt;yarn install&lt;/code&gt;. If &lt;code&gt;yarn&lt;/code&gt; doesn't detect any differences between versions in &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;yarn.lock&lt;/code&gt;, it won't install anything new and/or update &lt;code&gt;yarn.lock&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question&lt;/strong&gt;: &lt;em&gt;You installed project dependencies at some point. Time has passed, maybe a few of your project dependencies released a new version. You have also added some additional dependencies. What will happen if you run &lt;code&gt;yarn&lt;/code&gt;?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer&lt;/strong&gt;: Well, &lt;code&gt;yarn&lt;/code&gt; will of course install dependencies freshly added to &lt;code&gt;package.json&lt;/code&gt; that are not yet installed and/or not present in &lt;code&gt;yarn.lock&lt;/code&gt;. But if you have &lt;code&gt;”dependency_A”:“v1.3.5”&lt;/code&gt; already in your &lt;code&gt;yarn.lock&lt;/code&gt;, latest version available on NPM is &lt;code&gt;”dependency_A”:“v.1.4.0”&lt;/code&gt; and version range in &lt;code&gt;package.json&lt;/code&gt; is &lt;code&gt;^1.2.0&lt;/code&gt; - will &lt;code&gt;yarn&lt;/code&gt; upgrade to the latest version? No, it won’t. &lt;code&gt;v1.3.5&lt;/code&gt; falls into the requirement of being &lt;code&gt;^1.2.0&lt;/code&gt;, so &lt;code&gt;yarn&lt;/code&gt; doesn’t see the need of upgrading the package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem - A Second Look
&lt;/h2&gt;

&lt;p&gt;Let’s come back to the original issue for a moment:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;An integration of &lt;code&gt;Elements&lt;/code&gt; in &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; (a tool for building an testing UI components) was broken because of a bug present in the &lt;code&gt;Elements&lt;/code&gt; dependency, &lt;code&gt;JSV&lt;/code&gt; (&lt;a href="https://github.com/stoplightio/json-schema-viewer" rel="noopener noreferrer"&gt;JSON Schema Viewer&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;JSV&lt;/code&gt; was using a dependency called &lt;code&gt;JST&lt;/code&gt; (&lt;a href="https://github.com/stoplightio/json-schema-tree" rel="noopener noreferrer"&gt;JSON Schema Tree&lt;/a&gt;), which is effectively a sub-dependency of &lt;code&gt;Elements&lt;/code&gt;, with a non-pinned (non-specified) version (&lt;code&gt;^1.1.0&lt;/code&gt;) listed in its package.json.&lt;/li&gt;
&lt;li&gt;A new version of JST (&lt;code&gt;1.1.2&lt;/code&gt;), which falls into the requirement of being &lt;code&gt;^1.1.0&lt;/code&gt;, included a fix that would solve our problem&lt;/li&gt;
&lt;li&gt;Even though the &lt;code&gt;JST&lt;/code&gt; version could be &lt;code&gt;1.1.0&lt;/code&gt; &lt;strong&gt;or above&lt;/strong&gt;, &lt;code&gt;Elements&lt;/code&gt; itself would still hang for us. Installing dependencies (by running &lt;code&gt;yarn&lt;/code&gt; within the &lt;code&gt;Elements&lt;/code&gt; directory) didn’t help either. Why?&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer at this point is actually pretty simple - even though both of the &lt;code&gt;JSV&lt;/code&gt; and &lt;code&gt;JST&lt;/code&gt; versions are not pinned and should update upon a fresh install, our local &lt;code&gt;yarn.lock&lt;/code&gt; file was blocking these updates, having &lt;code&gt;v1.1.0&lt;/code&gt; of &lt;code&gt;JST&lt;/code&gt; in itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maybe we should just deploy the lockfile alongside other files?
&lt;/h2&gt;

&lt;p&gt;As explained in the paragraphs above - when present, &lt;code&gt;yarn.lock&lt;/code&gt; serves as the main source of information about which versions of packages should be installed. If that’s the case, can we just deploy it with the rest of the package when releasing a new version?&lt;/p&gt;

&lt;h3&gt;
  
  
  tl;dr(too long, didn’t read) - no you don't (sometimes)
&lt;/h3&gt;

&lt;p&gt;That depends on what your project is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is your project an application? &lt;strong&gt;Then: Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Is your project a library? &lt;strong&gt;If so: No&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why should you care about lockfile maintenance for libraries?
&lt;/h3&gt;

&lt;p&gt;There seems to be an agreement as to whether the lockfile should be committed. There's an &lt;a href="https://classic.yarnpkg.com/blog/2016/11/24/lockfiles-for-all/" rel="noopener noreferrer"&gt;excellent post on yarnpkg&lt;/a&gt; covering this topic (both for applications and libraries) if you want to understand the reasoning behind it.&lt;/p&gt;

&lt;p&gt;We'll focus on libraries, such as &lt;code&gt;Elements&lt;/code&gt;. Plus, committing the lockfile alongside the application pretty much solves the issue of unwanted updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling lockfile in libraries
&lt;/h3&gt;

&lt;p&gt;Because only the top-level lockfile is respected (the one form users project root directory), &lt;code&gt;yarn&lt;/code&gt; will look into the used library's &lt;code&gt;package.json&lt;/code&gt; and install the packages with versions described there. Unless you pin each dependency in your library to an exact version, users' projects might end up having different sub-dependencies depending on the time of installation.&lt;/p&gt;

&lt;p&gt;So are we doomed? Kind of. Users will always be the first people to discover a breaking change in a dependency (and hopefully file a bug report). To give you some perspective:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let’s assume your library has 20 external, sub-dependencies&lt;/li&gt;
&lt;li&gt;Each of these sub-dependencies can get a new release anytime&lt;/li&gt;
&lt;li&gt;Thousands (potentially) of users install your library each day&lt;/li&gt;
&lt;li&gt;Each such installation will fetch the latest sub-dependencies&lt;/li&gt;
&lt;li&gt;If any of those sub-dependencies introduce a bug, your users might be affected&lt;/li&gt;
&lt;li&gt;The above will happen, unless your development team has a way to regularly test that sub-dependency upgrades don’t break your library&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to keep dependencies up to date?
&lt;/h2&gt;

&lt;p&gt;By now, we’ve established that &lt;code&gt;yarn.lock&lt;/code&gt; left alone without any maintenance can introduce confusion about the current state of the project/library, as developers might end up having different versions of dependencies installed locally on their machines.&lt;/p&gt;

&lt;p&gt;Let’s take a look at possible solutions for keeping the lockfile up to date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependabot
&lt;/h3&gt;

&lt;p&gt;The first approach we looked at was &lt;a href="https://dependabot.com" rel="noopener noreferrer"&gt;Dependabot&lt;/a&gt; - a well-known tool for bumping dependencies. It checks for possible updates, opens Pull Requests with them, and allow users to review and merge (if you're confident enough with your test suite you can even set auto-merge)&lt;/p&gt;

&lt;p&gt;We'd been already using Dependabot for security updates and it served the purpose really well!&lt;/p&gt;

&lt;p&gt;Why did we decide not to go with it?&lt;/p&gt;

&lt;p&gt;Unfortunately, it &lt;a href="https://github.com/dependabot/dependabot-core/issues/2390" rel="noopener noreferrer"&gt;misses&lt;/a&gt; (at least at the time of writing this article) the ability to have duplicate updates for different &lt;code&gt;allow&lt;/code&gt; types. That means you can't have e.g. daily updates for &lt;code&gt;dependencies&lt;/code&gt; and weekly updates for &lt;code&gt;devDependencies&lt;/code&gt; in the same project. In our case, it was about not being able to daily update to versions that include security-related changes and all of the other changes (features, fixes, major updates) on a weekly basis using the same tool.&lt;/p&gt;

&lt;p&gt;Also, as it turned out, later on, having new PR for each dependency update is a bit of a pain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Renovate
&lt;/h3&gt;

&lt;p&gt;After figuring out that &lt;code&gt;Dependabot&lt;/code&gt; does not allow us to do the above, we've decided to look for alternatives. One of the most promising ones (and open-source!) was &lt;a href="https://github.com/renovatebot/renovate" rel="noopener noreferrer"&gt;Renovate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even though the basic principle of bumping dependencies is the same, the tool itself seems very powerful and customizable. It has 3 applications (Github, Gitlab, and self-hosted), highly granular settings (you can even set custom rules for auto-merging of PR), and allows opening a PR for a batch of dependencies, instead of for each one.&lt;/p&gt;

&lt;p&gt;As we are using GitHub for version control, the supported application for it was an obvious choice. Because our usage was a bit unorthodox - updating only &lt;code&gt;yarn.lock&lt;/code&gt; and not &lt;code&gt;package.json&lt;/code&gt; in order to have a representation of current users environments and at the same controlling the version ranges - we wanted to test it on the self-hosted version first, to avoid unnecessary PRs created by Renovate, or even worse - unwanted merges.&lt;/p&gt;

&lt;p&gt;This is where we hit a wall with Renovate - even though it has a great range of options, we didn't manage to configure it the way we wanted - update &lt;strong&gt;ONLY&lt;/strong&gt; &lt;code&gt;yarn.lock&lt;/code&gt; once a week and create a single PR.&lt;/p&gt;

&lt;p&gt;Because of that, we decided to not spend more time on publicly available solutions, and handle the lockfile maintenance ourselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your own CI job
&lt;/h3&gt;

&lt;p&gt;You may ask: &lt;em&gt;"Why did you even bother with setting those dependency management systems? Isn't it easier to just run &lt;code&gt;yarn upgrade&lt;/code&gt; on everything and call it a day?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And you would be partially right. The thing is that these systems probably do the exact same thing under the hood but put more attention to the possible failures and corner cases. And just because they are already battle-tested, we decided to check them first. Custom solutions built from scratch, in general, tend to be more fragile than the commercially available ones.&lt;/p&gt;

&lt;p&gt;Since neither Dependabot nor Renovate met our needs at a time though, our way out was writing a custom CI job that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Would bump dependencies for us&lt;/li&gt;
&lt;li&gt;Run some basic tests against those changes&lt;/li&gt;
&lt;li&gt;Create a PR&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our toolchain was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CircleCI&lt;/code&gt; for CI/CD&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git&lt;/code&gt; and &lt;code&gt;GitHub&lt;/code&gt; for VCS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Yarn&lt;/code&gt; as a package manager&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Jest&lt;/code&gt; for testing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Coffee®&lt;/code&gt; for energy&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Custom command&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;### bash&lt;/span&gt;

 &lt;span class="nv"&gt;$ &lt;/span&gt;git checkout main
 &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;feat/lockfile-maintenance-ci-job-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%m-%d-%Y"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;
 &lt;span class="nv"&gt;$ &lt;/span&gt;yarn upgrade
 &lt;span class="nv"&gt;$ &lt;/span&gt;git add yarn.lock
 &lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: weekly lockfile maintenance"&lt;/span&gt;
 &lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin &lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;
 &lt;span class="nv"&gt;$ BODY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"head":''"'&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'"'',"base":"main","title":"Weekly lockfile maintenance"}'&lt;/span&gt;
     &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST
     &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept:application/vnd.github.v3+json"&lt;/span&gt;
     &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$GIT_AUTHOR_NAME&lt;/span&gt;:&lt;span class="nv"&gt;$GH_TOKEN&lt;/span&gt; https://api.github.com/repos/stoplightio/elements/pulls
     &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BODY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The premise of this is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get the latest changes from main (no need to &lt;code&gt;git fetch&lt;/code&gt; as this is being run in a fresh CI job each time) and create a feature branch with a name corresponding to the lockfile maintenance
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;git checkout main

 &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;feat/lockfile-maintenance-ci-job-&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%m-%d-%Y"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Upgrade all of the dependencies in &lt;code&gt;yarn.lock&lt;/code&gt; according to &lt;code&gt;package.json&lt;/code&gt; - this mimics what happens for users upon a fresh install
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;yarn upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Push changes to remote
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;git add yarn.lock
 &lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: weekly lockfile maintenance"&lt;/span&gt;
 &lt;span class="nv"&gt;$ &lt;/span&gt;git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin &lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a PR using GitHub API (more details in &lt;a href="https://docs.github.com/en/rest/reference/pulls" rel="noopener noreferrer"&gt;GitHub API Documentation&lt;/a&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nv"&gt;$ BODY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"head":''"'&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'"'',"base":"main","title":"Weekly lockfile maintenance"}'&lt;/span&gt;
     &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST
       &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept:application/vnd.github.v3+json"&lt;/span&gt;
       &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$GIT_AUTHOR_NAME&lt;/span&gt;:&lt;span class="nv"&gt;$GH_TOKEN&lt;/span&gt; https://api.github.com/repos/stoplightio/elements/pulls
       &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BODY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;$GIT_AUTHOR_NAME&lt;/code&gt; and &lt;code&gt;$GH_TOKEN&lt;/code&gt; are secrets from &lt;code&gt;CircleCI&lt;/code&gt; - make sure you don't hard code your credentials in the CI config file and/or the command itself.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;CI configuration&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
 &lt;span class="na"&gt;test-and-release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="s"&gt;...&lt;/span&gt;
 &lt;span class="na"&gt;perform-lockfile-maintenance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;triggers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
           &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
           &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
             &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
               &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
   &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;lockfile-maintenance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you define the job as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;lockfile-maintenance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;circleci/node:12&lt;/span&gt;
   &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;checkout&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
         &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
           &lt;span class="s"&gt;### THIS IS A PLACE FOR THE COMMAND FROM PREVIOUS PARAGRAPH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, CircleCI runs workflows against all commits from all branches. This is definitely not the behavior we want to have for lockfile maintenance. The desired outcome is that it will run once a week against the &lt;code&gt;main&lt;/code&gt; branch. We also don't run any tests at this stage, as the PR created against the &lt;code&gt;main&lt;/code&gt; branch will trigger the &lt;code&gt;test-and-release&lt;/code&gt; workflow that is being run for each branch and contains a test suite, checks linting, and builds a project to see if there are no crashes.&lt;/p&gt;

&lt;p&gt;That's where &lt;code&gt;cron&lt;/code&gt; jobs come in handy. We first define that our &lt;code&gt;perform-lockfile-maintenance&lt;/code&gt; workflow will be triggered by one (test yours using &lt;a href="https://crontab.guru" rel="noopener noreferrer"&gt;this online tool&lt;/a&gt;) by putting cron job description in the &lt;code&gt;triggers/schedule&lt;/code&gt; section. Then we apply an additional filter to it, so it only targets &lt;code&gt;main&lt;/code&gt; at any given moment.&lt;/p&gt;

&lt;p&gt;As for scheduling, we decided to go with Monday before work (Central European Time), so it is the first thing we look into at the beginning of the week. A contributor opens a PR containing changes made to &lt;code&gt;yarn.lock&lt;/code&gt;, approves if it looks right, and merges the change to &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And that's it! You've just set up your first lockfile maintenance flow!&lt;/p&gt;

&lt;h2&gt;
  
  
  Possible improvements / aftermath
&lt;/h2&gt;

&lt;p&gt;There are few more things you can do to improve your confidence even more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you include examples of usage for your library like us (an integration for GatsbyJS, Angular, CRA) you can bump their dependencies as well. This will assure that your library not only is properly tested internally but doesn't crash when applied to a real-life scenario&lt;/li&gt;
&lt;li&gt;Serve an environment containing these integrations for each PR e.g. using Netlify. That will make the whole testing process much quicker as you won't need to check out the changes and run them locally on your own&lt;/li&gt;
&lt;li&gt;Strengthen your CI pipeline in general: the more that is covered by your testing suite, the less you will have to check&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;So there you go, we have just gone to a dependency hell and came back alive!&lt;/p&gt;

&lt;p&gt;I believe that what I have described above will help you encounter fewer issues when developing your library, especially if you don't have a full team dedicated to testing bugs.&lt;/p&gt;

&lt;p&gt;But even if I didn't convince you to do a weekly/monthly/whatever dependency bump I hope that this article gave you a strong understanding of the lockfile itself, why it is important when talking about compatibility across different machines, and seeing that lockfile maintenance does not have to be a terrible chore that takes an unreasonable amount of time.&lt;/p&gt;

&lt;p&gt;If you feel like this article added some value to your current skill set though, please consider resharing it on your social media and following me on Twitter &lt;a href="https://twitter.com/m_miaskowski" rel="noopener noreferrer"&gt;@m_miaskowski&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’d like to learn more about our open-source tool, Elements, which was a basis for this article, visit &lt;a href="https://stoplight.io/open-source/" rel="noopener noreferrer"&gt;our website&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@judesaf?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Jude Al-Safadi&lt;/a&gt; on &lt;a href="https://unsplash.com/@judesaf?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>yarn</category>
      <category>dependencies</category>
    </item>
    <item>
      <title>7 Approaches I Took While Learning Web Dev From Scratch</title>
      <dc:creator>mmiask</dc:creator>
      <pubDate>Tue, 04 May 2021 18:24:20 +0000</pubDate>
      <link>https://dev.to/mmiask/7-approaches-i-took-while-learning-web-dev-from-scratch-3imo</link>
      <guid>https://dev.to/mmiask/7-approaches-i-took-while-learning-web-dev-from-scratch-3imo</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://11sigma.com/blog/2020/11/30/7-approaches-i-took-while-learning-web-dev-from-scratch/"&gt;11sigma.com/blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;What this article is&lt;/strong&gt;: a starting point for people that seek knowledge in a digestible fashion + my personal summary of the best ways to learn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this article is not&lt;/strong&gt;: a guide on how to plan your self-development path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's code!
&lt;/h2&gt;

&lt;p&gt;Do you want to start programming but are not sure how to do it? Or maybe you already know some things but feel stuck?&lt;/p&gt;

&lt;p&gt;A little over a year ago, I switched my career path from biotechnology and became a manual QA. It was a huge unknown for me at that time - a year passed, though, and I'm now programming alongside super-talented engineers as a full-fledged member of a Team Undefined (awesome name, I know) in &lt;a href="//stoplight.io"&gt;Stoplight's&lt;/a&gt; &lt;a href="//11sigma.com"&gt;11Sigma&lt;/a&gt; crew.&lt;/p&gt;

&lt;p&gt;During that time, I was (and still am) simultaneously working and learning. It was never easy, I had my ups and downs, but now I can confidently say I improved a lot. If only I knew at the beginning what I know now, it would save me a lot of time and stress.&lt;/p&gt;

&lt;p&gt;Along the way, I used various learning materials of different kinds. Not all of them might fit you, but it's good to know about their pros and cons - which is why I prepared this summary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Theory
&lt;/h3&gt;

&lt;p&gt;This part of learning resources is pretty straightforward - it makes you sit and do a lot of reading. No shortcuts, just learning everything by yourself. It can give you a lot of satisfaction, but sometimes an equal amount of frustration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation &amp;amp; handbooks - per task, when you need to understand complex stuff quickly: &lt;a href="https://www.typescriptlang.org/docs"&gt;TypeScript&lt;/a&gt;, &lt;a href="https://visjs.github.io/vis-network/docs/network/"&gt;vis.js - network&lt;/a&gt; + its &lt;a href="https://visjs.github.io/vis-network/examples/"&gt;examples&lt;/a&gt;, &lt;a href="https://docs.cypress.io/api/api/table-of-contents.html"&gt;Cypress&lt;/a&gt;, &lt;a href="https://yarnpkg.com/"&gt;Yarn&lt;/a&gt;, &lt;a href="https://blueprintjs.com/docs/"&gt;Blueprint&lt;/a&gt;, &lt;a href="https://tailwindcss.com/docs"&gt;Tailwind CSS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/"&gt;MDN&lt;/a&gt; for the win - a ton of useful information on multiple topics for both beginners and advanced.&lt;/li&gt;
&lt;li&gt;Online courses w/o progress verification (&lt;a href="https://www.internetingishard.com/"&gt;Interneting is Hard&lt;/a&gt;) - they can give a sense of direction and structured material.&lt;/li&gt;
&lt;li&gt;Books: &lt;a href="https://eloquentjavascript.net/"&gt;Eloquent Javascript&lt;/a&gt;, &lt;em&gt;"Clean Code: A Handbook of Agile Software Craftsmanship"&lt;/em&gt; by Robert C. Martin.&lt;/li&gt;
&lt;li&gt;Websites / guides - like &lt;a href="https://www.atlassian.com/git"&gt;Getting Git Right&lt;/a&gt; by Atlassian or &lt;a href="https://css-tricks.com/"&gt;CSS-tricks&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reliable sources of knowledge.&lt;/li&gt;
&lt;li&gt;Allows us to understand both core concepts and dig deeper into specific details.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can get bored very easily if you don't use the gained knowledge parallel to reading.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real-life problems
&lt;/h3&gt;

&lt;p&gt;Let's say you understand the basics of the topic you have chosen. You are either working in a real team or doing some coding on your own. In both scenarios, at some point, you will face a blocker. That's when you should reach for these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dev.to, Medium, StackOverflow - tips &amp;amp; tricks for specific cases.&lt;/li&gt;
&lt;li&gt;Read somebody else's code / understand the product you are working on - because it's not necessary to reinvent the wheel, but good to understand how it works.&lt;/li&gt;
&lt;li&gt;Write something simple and let people judge it - good criticism is one of the best teachers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quick progress.&lt;/li&gt;
&lt;li&gt;Working with code that is used somewhere will give you a real-life experience.&lt;/li&gt;
&lt;li&gt;Access to great ideas and solutions that you could potentially spend hours on when doing them by yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires a basic understanding of the topic.&lt;/li&gt;
&lt;li&gt;Easy to forget what you've learned if you only copy-paste.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practice makes perfect
&lt;/h3&gt;

&lt;p&gt;You don't like spending hours reading books or documentation? Then learn by doing!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interactive tutorials - &lt;a href="https://flexboxfroggy.com/"&gt;Flexbox Froggy&lt;/a&gt; by &lt;a href="https://codepip.com/"&gt;Codepip&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Courses that involve practical tasks (&lt;a href="https://www.codecademy.com"&gt;Codecademy&lt;/a&gt;) - you can use your knowledge/skills in real-life problems. Also &lt;a href="https://www.udemy.com/"&gt;Udemy&lt;/a&gt; and &lt;a href="https://www.coursera.org/"&gt;Coursera&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Review code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Difficulty level increases with each lesson (suitable for complete beginners).&lt;/li&gt;
&lt;li&gt;It's easier to remember new concepts when you use them.&lt;/li&gt;
&lt;li&gt;Good courses provide you with quizzes and pet projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard to find any cons, actually.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Verify progress
&lt;/h3&gt;

&lt;p&gt;Because it's good to know how far you have come.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Online tests verifying your skills and knowledge.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.fullstack.cafe/"&gt;Answer interview questions&lt;/a&gt; for the desired role (online tests).&lt;/li&gt;
&lt;li&gt;Work journal - recap on what you've learned so far. I strongly recommend starting one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can evaluate your progress.&lt;/li&gt;
&lt;li&gt;Knowledge and skills that are used repeatedly stick better.&lt;/li&gt;
&lt;li&gt;If you don't feel like you make good progress, it's a perfect way to check if that's true. A lot of times, it turns out that you've learned more than you thought you did.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Focusing too much on quiz points and external expectations can decrease your internal motivation and remove the fun.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Collaborate / teach
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pair programming / mentoring - for when you get stuck or are very unfamiliar with a topic. A good mentor will point you in the right direction, not only in a matter of specific task but also unblock you if you feel unproductive or that your progress is too slow.&lt;/li&gt;
&lt;li&gt;Asking coworkers or friends that are programming/programming communities for solutions (async a lot of times).&lt;/li&gt;
&lt;li&gt;Do a webinar, teach somebody else - that will force you to learn as well. You will also understand the topic better and more in-depth (Lunch &amp;amp; learn style). I did one on best practices for e2e in Cypress.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Working with more experienced people will allow you to avoid common mistakes.&lt;/li&gt;
&lt;li&gt;A ton of great ideas emerge during discussions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires a big-time commitment.&lt;/li&gt;
&lt;li&gt;Huge impostor syndrome might happen at the beginning when you expose your ideas to other people.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Challenges/problems to solve - &lt;a href="https://www.hackerrank.com/"&gt;HackerRank&lt;/a&gt;, &lt;a href="https://codepen.io"&gt;Codepen&lt;/a&gt;, variety of coding games.&lt;/li&gt;
&lt;li&gt;YT videos - for motivation, fun &amp;amp; interesting stuff that stimulate your curiosity (Coding Train).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It keeps learning fun!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting distracted from the actual learning ;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Choose the learning method that feels best at the moment. You may have some underlying preferences that are based on your character, but changing context will also add freshness to the entire learning process.&lt;/li&gt;
&lt;li&gt;Consolidate your knowledge.&lt;/li&gt;
&lt;li&gt;Keep learning. If you don't grow as a programmer, you risk using the same solutions all the time (which will probably work but may not be the best possible).&lt;/li&gt;
&lt;li&gt;Don't try to be perfect, nobody is.&lt;/li&gt;
&lt;li&gt;Don't over-engineer stuff, do the best you can at the moment.&lt;/li&gt;
&lt;li&gt;Don't approach learning as another chore, do what is fun.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;If you liked the article, consider following me on &lt;a href="https://twitter.com/m_miaskowski"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@seefromthesky?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Ishan @seefromthesky&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/Jt9syHEhrPE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
