<?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: Ollie Bannister </title>
    <description>The latest articles on DEV Community by Ollie Bannister  (@olwiba).</description>
    <link>https://dev.to/olwiba</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%2F404107%2F553c3ac0-2ddf-4c4e-b88a-a4081c8e4653.jpg</url>
      <title>DEV Community: Ollie Bannister </title>
      <link>https://dev.to/olwiba</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/olwiba"/>
    <language>en</language>
    <item>
      <title>StudySpy: Building the new PublicApi v2</title>
      <dc:creator>Ollie Bannister </dc:creator>
      <pubDate>Sun, 15 Sep 2024 14:47:15 +0000</pubDate>
      <link>https://dev.to/olwiba/studyspy-building-the-new-publicapi-v2-4mn7</link>
      <guid>https://dev.to/olwiba/studyspy-building-the-new-publicapi-v2-4mn7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;How I built StudySpy's Public API from scratch: A solo developer's journey through tech choices, security challenges, and creating real value. Learn key strategies for your own API projects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This year, I embarked on an exciting journey to build a new Public API system for &lt;a href="https://studyspy.ac.nz/" rel="noopener noreferrer"&gt;StudySpy&lt;/a&gt;, one of my clients. The goal was to create a system that would allow StudySpy to sell access to their valuable dataset to external parties. This project wasn't just about opening up new revenue streams; it was about innovation and expanding the value StudySpy could offer to the New Zealand education sector.&lt;/p&gt;

&lt;p&gt;APIs play a crucial role in modern software systems, facilitating the flow of essential data across various components and platforms. By enabling third parties to build products on top of StudySpy's infrastructure, we were set to significantly increase the platform's value and reach.&lt;/p&gt;

&lt;p&gt;But our vision extended beyond external use. We aimed to create an API that would also serve as an internal standard for data access across the platform. This dual-purpose approach promised to streamline operations and set a new benchmark for efficiency within StudySpy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Infrastructure
&lt;/h2&gt;

&lt;p&gt;Starting such a project can be daunting, but I've learned that the act of beginning is often the most crucial milestone. Once you have something tangible, it becomes much easier to iterate and improve. However, before diving into coding, I knew that designing the right infrastructure from the start would be half the battle. The old adage "measure twice, cut once" came to mind.&lt;/p&gt;

&lt;p&gt;My focus was on three key areas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Technologies&lt;/strong&gt;: Choosing the right tech stack&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structure&lt;/strong&gt;: Ensuring maintainability through proper project organization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Implementing robust measures to protect the main platform&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Technologies
&lt;/h3&gt;

&lt;p&gt;Given that the main StudySpy platform runs on .NET 5/6+, I decided to leverage this technology as the foundation for the new API system. This decision immediately descoped a significant amount of effort – a critical consideration for a solo developer.&lt;/p&gt;

&lt;p&gt;I also wanted to incorporate Swagger with it'OpenAPI specification, tools I'd had positive experiences with in the past. These two key technologies formed the base upon which I built the rest of the stack.&lt;/p&gt;

&lt;p&gt;The final tech stack included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET&lt;/li&gt;
&lt;li&gt;Swagger + OpenAPI specification&lt;/li&gt;
&lt;li&gt;Microsoft SQL Server&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Microsoft entity framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz4izli9en0jnfqisnrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz4izli9en0jnfqisnrs.png" alt="Tech stack diagram" width="800" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;

&lt;p&gt;For project structure, I opted to create a new area within the existing solution rather than a separate .sln file. This approach maintains a cohesive view of the entire codebase, which is particularly beneficial for smaller teams.&lt;/p&gt;

&lt;p&gt;I started by defining the routes for the initial version of the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/api/v2/campuses
/api/v2/campuses/[id]
/api/v2/courses
/api/v2/courses/[id]
/api/v2/intakes
/api/v2/intakes/[id]
/api/v2/providers
/api/v2/providers/[id]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on these routes, I created the following directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PublicApi/
├── Controllers/
│   ├── CampusesController.cs
│   ├── CoursesController.cs
│   ├── IntakesController.cs
│   ├── ProviderController.cs
│   └── ScholarshipController.cs
├── Models/
│   ├── Campus.cs
│   ├── Course.cs
│   ├── Intake.cs
│   ├── Provider.cs
│   └── Scholarship.cs
└── Services/
    (initially empty, to be populated as needed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I began by defining the models, which shaped the API's response payloads. With these in place, I could then set up basic GET endpoints for both list and individual resource retrieval, initially returning dummy data.&lt;/p&gt;

&lt;p&gt;Here's a basic example of one of the domain-driven endpoints:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PublicApi/Models/Campus.cs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;StudySpy.Web.Areas.PublicApi.Models&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Course&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;SsId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;SsProviderId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LevelOfStudy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AreasOfStudy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SubjectsOfStudy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Details&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;EntryRequirements&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;LastUpdated&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;InternationalFlag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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;&lt;code&gt;PublicApi/Controllers/CoursesController.cs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.Mvc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;StudySpy.Web.Areas.PublicApi.Models&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;StudySpy.Web.Areas.PublicApi.Controllers&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PublicApi"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/v2/[controller]"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;ApiExplorerSettings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GroupName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"PublicApi"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CoursesController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Course&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetCourses&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Dummy data for illustration&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;courses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Course&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Course&lt;/span&gt; 
                &lt;span class="p"&gt;{&lt;/span&gt; 
                    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Computer Science"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;SsId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"CS101"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;SsProviderId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"UNIV001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;LevelOfStudy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Undergraduate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;AreasOfStudy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Technology"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mathematics"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="n"&gt;SubjectsOfStudy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Programming"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Algorithms"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Data Structures"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="n"&gt;Details&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"A comprehensive course covering the fundamentals of computer science."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;EntryRequirements&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"High school diploma with strong mathematics background"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"4 years"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Active&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;LastUpdated&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1630444800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Unix timestamp for September 1, 2021&lt;/span&gt;
                    &lt;span class="n"&gt;InternationalFlag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Course&lt;/span&gt; 
                &lt;span class="p"&gt;{&lt;/span&gt; 
                    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Business Administration"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;SsId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"BA201"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;SsProviderId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"UNIV001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;LevelOfStudy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Graduate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;AreasOfStudy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Business"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Management"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="n"&gt;SubjectsOfStudy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Finance"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Marketing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Operations"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="n"&gt;Details&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"An MBA program designed for aspiring business leaders."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;EntryRequirements&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bachelor's degree and 2 years of work experience"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2 years"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Active&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;LastUpdated&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1641024000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Unix timestamp for January 1, 2022&lt;/span&gt;
                    &lt;span class="n"&gt;InternationalFlag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;courses&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="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{id}"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Course&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetCourse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Dummy data for illustration&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;course&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Course&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Data Science"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;SsId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;SsProviderId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"UNIV001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;LevelOfStudy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Graduate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;AreasOfStudy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Technology"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Statistics"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;SubjectsOfStudy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Machine Learning"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Big Data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Statistical Analysis"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;Details&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"An advanced course in data science and analytics."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;EntryRequirements&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bachelor's degree in a quantitative field"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2 years"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Active&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;LastUpdated&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1651363200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Unix timestamp for May 1, 2022&lt;/span&gt;
                &lt;span class="n"&gt;InternationalFlag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;course&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;This setup allowed me to perform my first test using a Bruno client, and voila! I received my first response. Now we're getting somehwere 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;Before shipping anything, implementing security measures was crucial. I focused on two main concerns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Unauthorized access&lt;/strong&gt;: I implemented a rough-cut API key authentication strategy and added our new API pages to the robots.txt file to prevent search engine indexing. This would mean no-one would really stumble across our API accidentally, and if they did, they wouldn't be able to access our system without a valid API key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protection against DoS&lt;/strong&gt;: To mitigate the risk of database read operation overload (intentional or unintentional), I implemented API key rate limiting in combination with IP rate limits. I set a sensible limit of 120 requests per minute (2 requests per second) to maintain a reasonable SLA while protecting the system from accidental request floods.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these security measures in place, I was able to release the initial implementation of the new API routes to a production environment and take them for a spin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it a Product
&lt;/h2&gt;

&lt;p&gt;While I had a basic API in production, transforming it into a valuable product required several additional steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Business Logic
&lt;/h3&gt;

&lt;p&gt;We needed to get the routes wired up so they could start returning something valuable to the user. I used Microsoft's Entity Framework ORM to pull records from the SQL database and map them to the API response payloads. This process involved creating data access layers and implementing the necessary business logic in each controller.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Services for Reusable Logic
&lt;/h3&gt;

&lt;p&gt;To promote code reuse and maintain a clean separation of concerns, I abstracted common business logic into services. By the end of the project, I had created several utility services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Services/
├── AuthorityFormatter.cs
├── DateFormatCalculator.cs
├── DeliveryCalculator.cs
├── DurationCalculator.cs
├── HtmlHelper.cs
├── MacronRemover.cs
├── ProviderTypeFormatter.cs
├── RegionMapper.cs
├── StreetAddressFormatter.cs
├── StringFormatter.cs
└── SubjectTaxonomyMapper.cs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These provided me with a way I could share standarised business logic across various endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Pagination
&lt;/h3&gt;

&lt;p&gt;Pagination was crucial for allowing third parties to navigate through records at the API level efficiently. I created a pagination model and service:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PublicApi/Models/Pagination.cs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;StudySpy.Web.Areas.PublicApi.Models&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApiPaginatedResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Items&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Pagination&lt;/span&gt; &lt;span class="n"&gt;Pagination&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pagination&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Skip&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Limit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;NextPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;TotalCount&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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;I then wired this object up to all API response payloads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ApiPaginatedResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Campus&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Items&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CoursesPayload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Pagination&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pagination&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementing Correct HTTP Response Codes
&lt;/h3&gt;

&lt;p&gt;An often overlooked but crucial aspect of API design is the proper use of HTTP response codes. These codes provide immediate feedback to API consumers (and developers) about the status of their requests, making the API more intuitive and easier to work with.&lt;/p&gt;

&lt;p&gt;I made sure to implement a range of appropriate status codes in our API responses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;200 OK: For successful GET, PUT, or PATCH requests&lt;/li&gt;
&lt;li&gt;400 Bad Request: When the request is malformed or contains invalid parameters&lt;/li&gt;
&lt;li&gt;401 Unauthorized: When authentication is required but not provided or is invalid&lt;/li&gt;
&lt;li&gt;403 Forbidden: When the authenticated user doesn't have permission to access the requested resource&lt;/li&gt;
&lt;li&gt;404 Not Found: When the requested resource doesn't exist&lt;/li&gt;
&lt;li&gt;429 Too Many Requests: When the client has sent too many requests in a given amount of time (rate limiting)&lt;/li&gt;
&lt;li&gt;500 Internal Server Error: For unexpected server errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By consistently using these status codes across all endpoints, we ensure that our API communicates clearly with its consumers, delivering the best developer experience for uses of our API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing the UI
&lt;/h3&gt;

&lt;p&gt;To enhance the user experience and bring our brand to the API, I customized the Swagger UI by replacing the generic branding with StudySpy's logo and applying clean, consistent styling.&lt;/p&gt;

&lt;p&gt;I also added example response payloads for various endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Swagger/
└───Examples
    ├───CampusExamples
    │       CampusListResponseExample.cs
    │       CampusResponseExample.cs
    │
    ├───CourseExamples
    │       CourseListResponseExample.cs
    │       CourseResponseExample.cs
    │
    ├───IntakeExamplesse | Format-Tree                                                     [History]
    │       IntakeListResponseExample.cs
    │       IntakeResponseExample.cs
    │
    ├───ProviderExamples
    │       ProviderListResponseExample.cs
    │       ProviderResponseExample.cs
    │
    ├───ScholarshipExamples
    │       ScholarshipListResponseExample.cs
    │       ScholarshipResponseExample.cs
    │
    └───StatusCodes
            400ResponseExample.cs
            401ResponseExample.cs
            404ResponseExample.cs
            429ResponseExample.cs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8z29izymyf00w6yfx9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8z29izymyf00w6yfx9k.png" alt="Public API screenshot" width="800" height="402"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8fnxyo8g89nz0jtgile.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8fnxyo8g89nz0jtgile.png" alt="Example payload response screenshot" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Provisioning API Keys
&lt;/h3&gt;

&lt;p&gt;Before sharing the new Swagger documentation, I generated and distributed API keys to the third parties who would be using the new API. This process involved creating a secure system for generating, storing, and managing these keys.&lt;/p&gt;

&lt;p&gt;You don’t need to over-think this. We assigned API keys to a singleton and added code comments to identify the associated users. This simple system allowed for easy management and potential future revocation of access if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Building this project was an exciting challenge that taught me several valuable lessons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start small and iterate&lt;/strong&gt;: Beginning with a minimal viable product and improving it continuously proved to be an effective strategy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Define first, then build&lt;/strong&gt;: Having a clear understanding of the desired responses greatly simplified the process of writing business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't stress the small stuff&lt;/strong&gt;: Getting the service into users' hands quickly for feedback is crucial, even if it's not 100% polished.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage existing resources&lt;/strong&gt;: Choosing to use languages and frameworks already in play resulted in a more cohesive solution and easier future maintenance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Future Horizons
&lt;/h2&gt;

&lt;p&gt;The development of this API has not only expanded StudySpy's offerings but has also opened up new possibilities for innovation in the education sector for New Zealand. As more organizations recognize the power of APIs in driving growth and fostering ecosystems, projects like this will become increasingly vital.&lt;/p&gt;

&lt;p&gt;Whether you're considering building an API for your own project or looking to leverage existing APIs in your organization, remember that the journey of a thousand miles begins with a single step. Start small, focus on delivering value, and don't be afraid to iterate and improve as you go.&lt;/p&gt;

&lt;p&gt;If you’ve made it this far and are interested in viewing the swagger documentation on the live site, you can view it here:&lt;br&gt;
&lt;a href="https://studyspy.ac.nz/api/v2/documentation" rel="noopener noreferrer"&gt;https://studyspy.ac.nz/api/v2/documentation&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Like you, I'm always interested in learning more. If you have any feedback or questions about this project or API development in general, feel free to reach out to me on &lt;a href="https://twitter.com/olwiba" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>api</category>
      <category>swagger</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>JS Toolbox 2024: Essential Picks for Modern Developers Series Overview</title>
      <dc:creator>Ollie Bannister </dc:creator>
      <pubDate>Mon, 04 Mar 2024 04:07:46 +0000</pubDate>
      <link>https://dev.to/olwiba/js-toolbox-2024-essential-picks-for-modern-developers-series-overview-5cd1</link>
      <guid>https://dev.to/olwiba/js-toolbox-2024-essential-picks-for-modern-developers-series-overview-5cd1</guid>
      <description>&lt;h3&gt;
  
  
  Introducing JS Toolbox 2024
&lt;/h3&gt;

&lt;p&gt;Staying ahead of the curve in JavaScript development requires keeping on top of the &lt;a href="https://en.wikipedia.org/wiki/List_of_JavaScript_libraries" rel="noopener noreferrer"&gt;ever-evolving landscape&lt;/a&gt; of tools and technologies. As we head into 2024, the &lt;a href="https://raygun.com/blog/popular-javascript-frameworks/" rel="noopener noreferrer"&gt;sprawling&lt;/a&gt; &lt;a href="https://raygun.com/blog/javascript-unit-testing-frameworks/" rel="noopener noreferrer"&gt;world&lt;/a&gt; of JavaScript development tools will continue to transform, offering more refined, efficient, and user-friendly options.&lt;/p&gt;

&lt;p&gt;This series, &lt;strong&gt;JS Toolbox 2024&lt;/strong&gt;, is your one-stop for a comprehensive overview of the latest and most impactful tools in the JavaScript ecosystem.&lt;/p&gt;

&lt;p&gt;Across the series, we'll look at various tools, including runtime environments, package managers, frameworks, static site generators, bundlers, and test frameworks. This series will help you effectively choose the best available tools, analysing their functionalities, strengths, weaknesses, and how they fit into the modern JavaScript development process.&lt;/p&gt;

&lt;p&gt;Whether you're a seasoned developer or just starting out, this series will give you the necessary knowledge to select the right tools for your projects in 2024. Here’s what we’ll be getting into in this series.&lt;/p&gt;

&lt;h3&gt;
  
  
  Series overview:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Runtime Environments and Package Management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/olwiba/js-toolbox-2024-runtime-environments-package-management-2chg"&gt;first instalment, we explore runtime environments&lt;/a&gt;, focusing on &lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node&lt;/a&gt;, &lt;a href="https://deno.com/" rel="noopener noreferrer"&gt;Deno&lt;/a&gt; and &lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;Bun&lt;/a&gt;. We'll gain insights into their histories, performance metrics, community support, and ease of use.&lt;/p&gt;

&lt;p&gt;The segment on package management tools compares &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;, &lt;a href="https://yarnpkg.com/" rel="noopener noreferrer"&gt;yarn&lt;/a&gt;, and &lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;pnpm&lt;/a&gt;, highlighting their performance and security features. We provide tips for choosing the most suitable package manager for your project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Frameworks and Static Site Generators&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dev.to/olwiba/js-toolbox-2024-frameworks-and-static-site-generators-3ad0"&gt;next post in the series provides a thorough comparison of popular frameworks&lt;/a&gt; like &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt;, &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt;, &lt;a href="https://angularjs.org/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;, and &lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt;, focusing on their unique features and suitability for different project types.&lt;/p&gt;

&lt;p&gt;We also take a look into static site generators, covering &lt;a href="https://astro.build/" rel="noopener noreferrer"&gt;Astro&lt;/a&gt;, &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;, &lt;a href="https://gohugo.io/" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt;, &lt;a href="https://www.gatsbyjs.com/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt;, and &lt;a href="https://jekyllrb.com/" rel="noopener noreferrer"&gt;Jekyll&lt;/a&gt;. We take a detailed look into their usability, performance, and community support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Bundlers and Test Frameworks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/olwiba/js-toolbox-2024-bundlers-and-test-frameworks-30f9"&gt;In part 3 We jump into the world of bundlers&lt;/a&gt;, comparing &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;webpack&lt;/a&gt;, &lt;a href="https://esbuild.github.io/" rel="noopener noreferrer"&gt;esbuild&lt;/a&gt;, &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;vite&lt;/a&gt;, and &lt;a href="https://parceljs.org/blog/v2/" rel="noopener noreferrer"&gt;parcel 2&lt;/a&gt;. This section aims to guide developers through each bundler, focusing on their performance, compatibility, and ease of use.&lt;/p&gt;

&lt;p&gt;The test frameworks section provides an in-depth look at &lt;a href="https://mochajs.org/" rel="noopener noreferrer"&gt;MochaJS&lt;/a&gt;, &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;, &lt;a href="https://github.com/jasmine/jasmine" rel="noopener noreferrer"&gt;Jasmine&lt;/a&gt;, &lt;a href="https://pptr.dev/" rel="noopener noreferrer"&gt;Puppeteer&lt;/a&gt;, &lt;a href="https://www.selenium.dev/" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;, and &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;. We review each framework's ease of use, community support, and overall robustness, supplemented with example unit tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  What you'll take away
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;JS Toolbox 2024&lt;/strong&gt; provides an informed view of the current JavaScript development tools landscape. Through personal insights and industry observations, I’ve aimed to guide developers through a selection of the myriad tools available, helping you make educated decisions that meet your project needs and personal preferences. Be sure to check out the entire series for insights that could shape your development workflow and tool choices in 2024 and beyond.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Like you, I’m always curious and looking to learn. If I've overlooked a noteworthy tool or if you have any feedback to share, reach out on &lt;a href="https://twitter.com/Olwiba" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://linkedin.com/in/olwiba/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tooling</category>
      <category>frontend</category>
    </item>
    <item>
      <title>JS Toolbox 2024: Bundlers and Test Frameworks</title>
      <dc:creator>Ollie Bannister </dc:creator>
      <pubDate>Mon, 04 Mar 2024 04:07:28 +0000</pubDate>
      <link>https://dev.to/olwiba/js-toolbox-2024-bundlers-and-test-frameworks-30f9</link>
      <guid>https://dev.to/olwiba/js-toolbox-2024-bundlers-and-test-frameworks-30f9</guid>
      <description>&lt;p&gt;&lt;em&gt;JavaScript is bigger than ever, and the ecosystem is nothing short of overwhelming. In this JS toolbox 2024 series, we’ve selected and analyzed the most noteworthy JS tools, so that you don’t have to.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/olwiba/js-toolbox-2024-runtime-environments-package-management-2chg"&gt;part 1 of this series&lt;/a&gt;, we explored the foundations of any JavaScript project: Runtime environments and package management. In &lt;a href="https://dev.to/olwiba/js-toolbox-2024-frameworks-and-static-site-generators-3ad0"&gt;part 2&lt;/a&gt;, we focused on JavaScript frameworks and static site generators. Now, in part 3, we turn our attention to the tools that refine and optimize the development process: Bundlers and test frameworks. &lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;In this post:&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Bundlers&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Webpack&lt;/li&gt;
&lt;li&gt;EsBuild&lt;/li&gt;
&lt;li&gt;Vite&lt;/li&gt;
&lt;li&gt;Parcel 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test frameworks&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;MochaJS&lt;/li&gt;
&lt;li&gt;Jest&lt;/li&gt;
&lt;li&gt;Jasmine&lt;/li&gt;
&lt;li&gt;Puppeteer&lt;/li&gt;
&lt;li&gt;Selenium&lt;/li&gt;
&lt;li&gt;Playwright&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What to choose?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bundlers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In modern web development, bundlers play a pivotal role in getting your project production-ready. They are essential tools for combining multiple files and assets into streamlined, optimized bundles, effectively managing complex dependencies, and enhancing application performance.&lt;/p&gt;

&lt;p&gt;This section delves into the world of bundlers, focusing on popular tools such as &lt;a href="https://github.com/Webpack/Webpack" rel="noopener noreferrer"&gt;webpack&lt;/a&gt;, &lt;a href="https://github.com/evanw/esbuild" rel="noopener noreferrer"&gt;esbuild&lt;/a&gt;, &lt;a href="https://github.com/vitejs/vite" rel="noopener noreferrer"&gt;vite&lt;/a&gt;, and &lt;a href="https://github.com/parcel-bundler/parcel" rel="noopener noreferrer"&gt;parcel 2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4a8tmq8znnvgj0ido3ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4a8tmq8znnvgj0ido3ac.png" alt="Image description" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://star-history.com/#Webpack/Webpack&amp;amp;evanw/esbuild&amp;amp;vitejs/vite&amp;amp;parcel-bundler/parcel&amp;amp;Date" rel="noopener noreferrer"&gt;An overview&lt;/a&gt; of bundler popularity trends.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In 2023, Webpack has maintained its position as the most popular project bundler, but Vite is rapidly gaining ground and could soon challenge for the top spot. Meanwhile, Parcel and esbuild have also experienced steady growth, making the project bundler category even more competitive.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Webpack&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Webpack/Webpack" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt; is a powerful and widely-used module bundler for JavaScript applications. It’s known for its flexibility and extensive plugin system, making it a popular tool in complex web development projects.&lt;/p&gt;

&lt;p&gt;It also benefits from being a long-standing player in the JavaScript ecosystem. Over the years, Webpack has adapted to the evolving demands of web development, establishing itself as a reliable and robust tool.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extensive customization&lt;/strong&gt;: Webpack offers a highly configurable environment, allowing developers to tailor the bundling process to their specific needs through a vast array of plugins and loaders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong community and ecosystem&lt;/strong&gt;: With a large community backing it, Webpack benefits from a rich ecosystem of plugins, extensive documentation, and community support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized bundle handling&lt;/strong&gt;: It excels in handling various assets and dependencies, offering features like code splitting and lazy loading to optimize application performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Steep learning curve&lt;/strong&gt;: The complexity and vastness of Webpack’s configuration options can be overwhelming for beginners or simpler projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration overhead&lt;/strong&gt;: Setting up and maintaining a Webpack configuration can become cumbersome, especially in larger projects with more specific requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;EsBuild&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/evanw/esbuild" rel="noopener noreferrer"&gt;EsBuild&lt;/a&gt; is a relatively new, blazing-fast JavaScript bundler and minifier. It stands out for its high performance, significantly speeding up the build process in development pipelines.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exceptional speed&lt;/strong&gt;: EsBuild is known for its incredibly fast build times, often orders of magnitude quicker than traditional bundlers, which greatly enhances developer productivity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity and ease of use&lt;/strong&gt;: With a straightforward setup and minimal configuration, EsBuild is accessible and easy to integrate into development workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient bundling and minification&lt;/strong&gt;: It efficiently handles the tasks of bundling and minification, reducing the size of output files and improving application load times.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited plugin ecosystem&lt;/strong&gt;: Being newer in the market, EsBuild has a smaller range of plugins and integrations compared to more established bundlers like Webpack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less feature-rich&lt;/strong&gt;: While its simplicity is a strength, EsBuild may lack some of the advanced features and customizability found in other, more mature bundling tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Vite&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/vitejs/vite" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; is a modern front-end build tool that significantly improves the development experience with its fast cold server start and hot module replacement. It leverages native ES modules and is optimized for speed and efficiency.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rapid development cycle&lt;/strong&gt;: Vite offers a fast server start and quick updates with its hot module replacement, streamlining the development process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized for modern browsers&lt;/strong&gt;: Utilizing native ES modules, Vite is designed for modern browsers, reducing the need for extensive transpiling and bundling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of use&lt;/strong&gt;: With sensible defaults and minimal configuration, Vite simplifies setup and usage, making it accessible for new developers and efficient for experienced ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dependency on modern browser features&lt;/strong&gt;: Vite’s reliance on native ES modules means it may not be the best fit for projects needing to support older browsers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Growing ecosystem&lt;/strong&gt;: While rapidly evolving, Vite's ecosystem and range of plugins are still in the growth phase and may not yet match the breadth of more established tools like Webpack.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Parcel 2&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/parcel-bundler/parcel" rel="noopener noreferrer"&gt;Parcel 2&lt;/a&gt; emphasizes a zero-configuration approach to bundling web applications. It's a powerful tool that offers a hassle-free developer experience, focusing on simplicity and speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero configuration required&lt;/strong&gt;: Parcel 2 stands out for its no-config setup, allowing developers to get started quickly without the need for intricate configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast build times&lt;/strong&gt;: It offers rapid build and rebuild times, enhancing productivity and streamlining the development process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Out-of-the-box features&lt;/strong&gt;: Parcel 2 comes with many built-in features like code splitting, module replacement, and support for various languages and file types.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Less granular control&lt;/strong&gt;: The zero-configuration approach, while convenient, can limit developers who need more control over the bundling process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smaller community&lt;/strong&gt;: Compared to tools like Webpack, Parcel 2 has a smaller community, which might mean fewer resources and plugins available to developers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Test frameworks&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Test frameworks are crucial for ensuring the quality and reliability of JavaScript applications, particularly through comprehensive code coverage. These frameworks provide the structured environment needed for writing, executing, and managing tests, playing a pivotal role in validating code functionality and detecting bugs. As JavaScript is adopted in both front-end and back-end project stacks, the robustness of testing frameworks becomes more important, helping developers maintain high standards of code integrity and application performance.&lt;/p&gt;

&lt;p&gt;This section will introduce you to a variety of JavaScript test frameworks, each with unique attributes tailored to different testing requirements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhf3nqdo247252c45jvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhf3nqdo247252c45jvz.png" alt="Image description" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://star-history.com/#mochajs/mocha&amp;amp;jasmine/jasmine&amp;amp;jestjs/jest&amp;amp;puppeteer/puppeteer&amp;amp;SeleniumHQ/selenium&amp;amp;microsoft/playwright&amp;amp;Date" rel="noopener noreferrer"&gt;An overview&lt;/a&gt; of Framework popularity trends.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Over the past year, the JavaScript testing framework landscape has remained relatively solid. No major disruptor technologies have proven to challenge &lt;a href="https://github.com/puppeteer/puppeteer" rel="noopener noreferrer"&gt;Puppeteer&lt;/a&gt; for the top spot, although the rapid growth of &lt;a href="https://github.com/microsoft/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; gives us something to keep our eyes on through 2024.&lt;/p&gt;

&lt;p&gt;These technologies aren’t directly comparable however due to the varying niches that they fill. In this section, I will cover each technology to give you the context to help you make the right decision when choosing the testing framework for your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;MochaJS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/mochajs/mocha" rel="noopener noreferrer"&gt;MochaJS&lt;/a&gt; is a feature-rich JavaScript test framework running on Node.js, making it a popular choice for both backend and frontend testing. It's known for its flexibility and straightforward syntax, allowing for asynchronous testing and the use of any assertion library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example test case syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#indexOf()&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return -1 when the value is not present&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&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;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility and compatibility&lt;/strong&gt;: MochaJS is highly flexible, allowing developers to choose their preferred assertion libraries, mock/spy libraries, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich feature set&lt;/strong&gt;: It offers a wide range of features like asynchronous testing, test coverage reports, and hooks for setting up conditions before running tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Good documentation and community support&lt;/strong&gt;: MochaJS has comprehensive documentation and strong community support, making it easier for new users to get started and find solutions to common problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Global variables&lt;/strong&gt;: Mocha exposes global variables, which can be an issue for developers preferring a more modular approach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slower than some rivals&lt;/strong&gt;: While Mocha is versatile, it can be slow compared to some newer testing frameworks, particularly in large test suites.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Jest&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/jestjs/jest" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;, created and maintained by Facebook, is a JavaScript testing framework with a focus on simplicity. It is often recognized for its zero-configuration setup and seamless integration, especially with React applications, making it a favored choice for developers in both small-scale projects and large enterprise applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example test case syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;adds 1 + 2 to equal 3&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&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;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero-configuration&lt;/strong&gt;: Jest is designed for out-of-the-box usability with minimal setup, offering a smooth testing experience right from the start.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in mocking and assertions&lt;/strong&gt;: It comes with powerful mocking capabilities and a rich set of assertion APIs, eliminating the need for additional libraries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snapshot testing and coverage&lt;/strong&gt;: Jest provides snapshot testing, which is great for catching unexpected changes, and built-in coverage reports to keep track of your test suite's effectiveness.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance in large projects&lt;/strong&gt;: While generally fast, Jest can exhibit slower test execution times in very large projects or complex test suites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration complexity in advanced scenarios&lt;/strong&gt;: Despite its zero-config appeal, advanced use cases might require navigating through more complex configurations and setups.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Jasmine&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/jasmine/jasmine" rel="noopener noreferrer"&gt;Jasmine&lt;/a&gt; is a behavior-driven development framework for testing JavaScript code. It's known for its clean, straightforward syntax and does not rely on any other JavaScript frameworks or a Document Object Model (DOM). Jasmine is often praised for its simplicity and ease of use in both frontend and backend testing environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example test case syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A suite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contains spec with an expectation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clean, readable syntax&lt;/strong&gt;: Jasmine's syntax is designed to be easy to read and write, making it accessible for developers of all skill levels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent of other technologies&lt;/strong&gt;: It doesn't depend on any external software or browser DOM, making it suitable for testing any JavaScript application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Out-of-the-box functionality&lt;/strong&gt;: Jasmine comes with everything you need for testing your JavaScript code, including test doubles and asynchronous testing support.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited mocking capabilities&lt;/strong&gt;: Jasmine's mocking capabilities, while present, are not as extensive or straightforward as some other testing frameworks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slower performance with large test suites&lt;/strong&gt;: In scenarios involving large test suites, Jasmine can sometimes be slower compared to other modern testing frameworks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Puppeteer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/puppeteer/puppeteer" rel="noopener noreferrer"&gt;Puppeteer&lt;/a&gt; is a Node library that provides a high-level API to control headless Chrome or Chromium. It's primarily used for browser automation, making it a powerful tool for end-to-end testing of web applications, taking screenshots, and generating pre-rendered content from web pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example test case syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;puppeteer&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="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// other actions...&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&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;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser Automation&lt;/strong&gt;: Puppeteer excels in automating and testing browser environments, offering precise control over Chrome or Chromium.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich Feature Set for Testing&lt;/strong&gt;: It supports a wide array of testing needs, from capturing screenshots and generating PDFs to testing modern web applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-Level API&lt;/strong&gt;: Puppeteer's API abstracts away complexities, making it relatively easy to write scripts for browser-based testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited browser support&lt;/strong&gt;: Puppeteer primarily works with Chrome and Chromium, which might not be suitable for cross-browser testing needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Higher resource usage&lt;/strong&gt;: Being a full browser automation tool, it can be more resource-intensive compared to some lightweight testing frameworks, potentially leading to slower performance in resource-constrained environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Selenium&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/SeleniumHQ/selenium" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt; is an extensively used open-source automation framework for web applications. It allows for cross-browser testing by automating browser actions, making it a staple tool for end-to-end testing in diverse web development environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example test case syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;WebDriver&lt;/span&gt; &lt;span class="nx"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ChromeDriver&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;WebElement&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;q&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendKeys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Selenium WebDriver!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cross-browser compatibility&lt;/strong&gt;: Selenium supports testing across a wide range of browsers, including Chrome, Firefox, Safari, and Internet Explorer, making it ideal for cross-browser testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support for multiple programming languages&lt;/strong&gt;: It offers the flexibility to write tests in several programming languages, such as Java, Python, C#, and JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong community and ecosystem&lt;/strong&gt;: Being one of the oldest and most established testing frameworks, Selenium has a large community, extensive resources, and integration support.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complex setup and learning curve&lt;/strong&gt;: Setting up Selenium can be complex, and it requires a fair amount of learning, particularly for those new to testing automation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance issues&lt;/strong&gt;: Selenium tests can sometimes be slower compared to some modern testing frameworks, especially when running complex test suites or tests across multiple browsers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Playwright&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/microsoft/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; is a relatively new but powerful node library for browser automation. Developed by Microsoft, it enables cross-browser web automation that is ever-reliable for end-to-end testing. Playwright is compatible with all modern web browsers, including Chrome, Firefox, and Safari, and offers capabilities for both headless and non-headless browser testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example test case syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;playwright&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="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// other actions...&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&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;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cross-browser support&lt;/strong&gt;: Playwright supports automated testing across multiple browsers and platforms, enhancing its utility in diverse development scenarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern and robust API&lt;/strong&gt;: It offers a modern, feature-rich API that allows for advanced browser automation, including support for single-page applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast and reliable&lt;/strong&gt;: Playwright tests are generally faster and more reliable than those performed with older tools, offering improved stability and performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relatively new in the market&lt;/strong&gt;: As a newer tool, Playwright is still building its community and ecosystem, which can currently lack the extensiveness of more established frameworks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve&lt;/strong&gt;: While its API is user-friendly, there is still a learning curve, especially for developers new to browser automation and end-to-end testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What to choose?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Choosing the right tools for your JavaScript project, is a crucial decision that can significantly impact your development workflow and the quality of your final product. Each tool comes with its own set of strengths and drawbacks.&lt;/p&gt;

&lt;p&gt;For bundlers, the decision might hinge on factors like ease of configuration, build speed, and ecosystem support. In test frameworks, the decision could depend on the nature of your testing needs, ranging from unit and integration testing to end-to-end browser automation.&lt;/p&gt;

&lt;p&gt;Your choice should align with the specific needs of your project, the skill set of your team, and the nature of your development environment. It's about finding the right tool that not only addresses your current requirements but also adapts to the evolving demands of your project. A comprehensive understanding of each tool's capabilities and limitations is key to making an informed decision that enhances both your development process and the overall quality of your JavaScript applications. Remember, the right set of tools can empower your development team, streamline your processes, and lead to the creation of a robust, efficient, and maintainable codebase.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Like you, I’m always curious and looking to learn. If I've overlooked a noteworthy tool or if you have any feedback to share, reach out on &lt;a href="https://twitter.com/Olwiba" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/olwiba/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tooling</category>
      <category>frontend</category>
    </item>
    <item>
      <title>JS Toolbox 2024: Frameworks and static site generators</title>
      <dc:creator>Ollie Bannister </dc:creator>
      <pubDate>Mon, 04 Mar 2024 04:06:52 +0000</pubDate>
      <link>https://dev.to/olwiba/js-toolbox-2024-frameworks-and-static-site-generators-3ad0</link>
      <guid>https://dev.to/olwiba/js-toolbox-2024-frameworks-and-static-site-generators-3ad0</guid>
      <description>&lt;p&gt;In 2024, JavaScript is bigger than ever. The ecosystem is just as huge, and almost impossible to keep track of, so I’ve had a go at picking out 2024’s most essential JS tools for you.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/olwiba/js-toolbox-2024-runtime-environments-package-management-2chg"&gt;In part 1 of this series&lt;/a&gt;, we reviewed runtimes and package managers, the foundational building blocks of your software project. So in part 2, we're analyzing the tools which form the walls and roof that give your software project its structure: frameworks and static site generators.&lt;/p&gt;

&lt;p&gt;For this installment of JS Toolbox 2024, we explore various frameworks &amp;amp; generators available in the JavaScript &amp;amp; TypeScript ecosystem, analyzing their strengths, weaknesses, and ideal use cases.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can also check out &lt;a href="https://dev.to/olwiba/js-toolbox-2024-bundlers-and-test-frameworks-30f9"&gt;Part 3, covering bundlers and test frameworks, here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;In this post:&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Frameworks&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Vue&lt;/li&gt;
&lt;li&gt;Angular&lt;/li&gt;
&lt;li&gt;Svelte&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static Site/Server side Generators&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Astro&lt;/li&gt;
&lt;li&gt;Nuxt&lt;/li&gt;
&lt;li&gt;Hugo&lt;/li&gt;
&lt;li&gt;Gatsby&lt;/li&gt;
&lt;li&gt;Jekyll&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What to choose?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Frameworks&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://raygun.com/blog/popular-javascript-frameworks/" rel="noopener noreferrer"&gt;JavaScript frameworks&lt;/a&gt; are an essential part of modern web development, providing tried and tested tools for building scalable, interactive web applications. Many modern companies use frameworks as a standard part of their tooling, so understanding the current state of frameworks is crucial for projects old and new.&lt;/p&gt;

&lt;p&gt;In this section, we look at some of the most prominent JavaScript frameworks that shaped web development in 2023 and speculate on what 2024 will have in store.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favcnz52t7uvbaat2edaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favcnz52t7uvbaat2edaf.png" alt="Image description" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://star-history.com/#facebook/react&amp;amp;vuejs/vue&amp;amp;angular/angular&amp;amp;sveltejs/svelte&amp;amp;Date" rel="noopener noreferrer"&gt;An overview&lt;/a&gt; of framework popularity trends.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In 2023, &lt;a href="https://github.com/facebook/react" rel="noopener noreferrer"&gt;React&lt;/a&gt; and &lt;a href="https://github.com/vuejs/vue" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt; have continued to lead the pack. We’ve seen some consistent growth from both &lt;a href="https://github.com/angular/angular" rel="noopener noreferrer"&gt;Angular&lt;/a&gt; and &lt;a href="https://github.com/sveltejs/svelte" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt;; however, given Svelte’s trajectory I can see the gap closing on its competitors in 2024. Let’s get into what’s good and not-so-good about these leading frameworks.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;React&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Developed by Facebook, &lt;a href="https://github.com/facebook/react" rel="noopener noreferrer"&gt;React&lt;/a&gt; rapidly gained popularity as a framework for developing dynamic user interfaces for high-traffic web pages. Known for its efficiency, React utilizes a virtual DOM, which simplifies integration with various applications. This approach enables fast and smooth user experience, making it a favored choice for modern web development.&lt;/p&gt;

&lt;p&gt;React components are typically written using JSX, which allows you to write HTML-like syntax in your JavaScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Greeting&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Greeting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Component-based architecture&lt;/strong&gt;: React's design is centered around reusable components, allowing developers to build encapsulated components that manage their own state. This architecture makes it easier to manage and maintain large applications, as well as to reuse code, leading to more &lt;a href="https://raygun.com/blog/javascript-best-practices/" rel="noopener noreferrer"&gt;efficient development processes&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Virtual DOM for enhanced performance&lt;/strong&gt;: React employs a virtual DOM (Document Object Model) that optimizes rendering and improves application performance. This means React can update changes in an application's UI quickly and efficiently, leading to a smoother and more responsive user experience, especially for complex applications with dynamic content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strong community and ecosystem&lt;/strong&gt;: React has a large and active community, backed by Facebook's support. This vast ecosystem provides a wealth of resources, including libraries, tools, and third-party extensions. The strong community support also ensures regular updates, a wealth of learning resources, and a wide range of solutions for various development challenges.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Steep learning curve for beginners&lt;/strong&gt;: Despite its popularity, React can be challenging for beginners to grasp. Its component-based architecture, JSX syntax, and overall ecosystem can be overwhelming initially. Newcomers to React often need time to become comfortable with concepts like &lt;a href="https://react.dev/learn/managing-state" rel="noopener noreferrer"&gt;state management&lt;/a&gt;, lifecycle methods, and the &lt;a href="https://www.w3schools.com/react/react_props.asp" rel="noopener noreferrer"&gt;use of props&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rapid pace of development&lt;/strong&gt;: The fast evolution of React and its ecosystem can be a double-edged sword. While regular updates introduce new features and improvements, they also mean developers need to continuously adapt and learn. This rapid change can lead to challenges in keeping projects up-to-date and may require frequent refactoring or rewriting of existing code to align with the latest best practices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Vue&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/vuejs/vue" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt;, often simply referred to as Vue, has established itself as a highly adaptable and progressive JavaScript framework, primarily used for building user interfaces and &lt;a href="https://raygun.com/blog/spa-performance/" rel="noopener noreferrer"&gt;single-page applications&lt;/a&gt;. Its gentle learning curve and incrementally adoptable architecture have made it a popular choice among developers, particularly for its ease of integration into existing projects.&lt;/p&gt;

&lt;p&gt;Vue components are often structured with a template, script, and style section. This example uses the Vue 3 Composition API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello, {{ name }}!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vue User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intuitive and easy to learn&lt;/strong&gt;: Vue's straightforward and &lt;a href="https://vuejs.org/guide/introduction.html" rel="noopener noreferrer"&gt;clear documentation&lt;/a&gt; makes it accessible, especially for those new to JavaScript frameworks. Its template syntax and use of plain JavaScript make it easier to get started and become productive quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reactive and composable&lt;/strong&gt;: Vue's core feature is its reactivity system, which ensures efficient updates and rendering. The framework's focus on component composition allows for building complex interfaces while keeping the codebase organized and maintainable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versatile ecosystem&lt;/strong&gt;: Vue offers a rich ecosystem with solutions like &lt;a href="https://vuex.vuejs.org/" rel="noopener noreferrer"&gt;Vuex&lt;/a&gt; for state management and Vue Router for routing, providing developers with a comprehensive toolkit for modern web development. The framework is also compatible with a variety of other libraries and tools, making it versatile for different project needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Less market share and community size&lt;/strong&gt;: Compared to giants like React, Vue has a smaller community and market share. While growing, this can sometimes mean fewer resources, third-party libraries, and extensions than more widely adopted frameworks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk of over-flexibility&lt;/strong&gt;: Vue's flexibility, while a strength, can also be a drawback. The freedom in structuring applications can lead to inconsistencies in large projects or among different developers, potentially affecting maintainability and scalability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Angular&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/angular/angular" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;, maintained by Google, is a robust and feature-rich framework designed for building scalable and sophisticated single-page applications. It's widely recognized for its ability to create efficient, large-scale enterprise-grade web applications, offering a comprehensive solution with a powerful suite of tools.&lt;/p&gt;

&lt;p&gt;Angular components combine a TypeScript class with an HTML template, typically decorated with metadata.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&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="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-greeting&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;h1&amp;gt;Hello, {{ name }}!&amp;lt;/h1&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./greeting.component.css&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetingComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Angular User&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full-fledged framework&lt;/strong&gt;: Angular is a complete framework that includes everything needed for front-end development, from a powerful templating engine to integrated state management, making it a one-stop solution for complex applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced dependency injection&lt;/strong&gt;: &lt;a href="https://blog.angular-university.io/angular-dependency-injection/" rel="noopener noreferrer"&gt;Angular's advanced dependency injection&lt;/a&gt; system is a key feature that facilitates greater efficiency in building and managing applications. It simplifies the process of supplying components with the data and services they need, leading to more modular, flexible, and easily testable code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent code structure&lt;/strong&gt;: Angular enforces a consistent code structure and best practices through its opinionated nature. This uniformity is advantageous for team collaboration and when scaling up the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Steep learning curve&lt;/strong&gt;: Angular's extensive set of features and functionalities, while powerful, often presents a challenging learning curve, particularly for beginners or those accustomed to more straightforward frameworks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance overhead&lt;/strong&gt;: While powerful, Angular's complexity can lead to performance overhead in smaller projects. The framework is better suited for larger applications where the full feature set can be effectively utilized.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Svelte&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/sveltejs/svelte" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt; is an innovative component-based framework that shifts much of the work to compile time, offering a unique approach to building interactive web interfaces. Unlike traditional frameworks that apply updates to the DOM in response to state changes, Svelte compiles applications to highly efficient vanilla JavaScript at build time, resulting in faster and more responsive applications.&lt;/p&gt;

&lt;p&gt;Svelte components are written with HTML, JavaScript, and CSS in a single file, with reactive state updates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Svelte User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello, {name}!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compile-time innovation&lt;/strong&gt;: Svelte's unique compile-time approach leads to less boilerplate code and higher performance, as it generates optimized JavaScript code that directly updates the DOM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of learning and use&lt;/strong&gt;: With a syntax closer to vanilla JavaScript and HTML, Svelte is straightforward to learn, particularly for those with basic JavaScript knowledge. This simplicity also makes it easier to start building applications quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal runtime overhead&lt;/strong&gt;: Svelte applications do not carry the weight of a framework's runtime, resulting in smaller bundle sizes and faster load times, which is particularly advantageous for performance-sensitive applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smaller community and ecosystem&lt;/strong&gt;: Svelte’s community, while active and growing, is smaller than those of more established frameworks like React or Angular. This can mean fewer resources, libraries, and community support compared to its larger counterparts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less mainstream adoption&lt;/strong&gt;: Being relatively new and different, Svelte has not seen as widespread adoption in the industry as some other frameworks. This might pose challenges in finding experienced developers or integrating with certain existing technologies and tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Static site/Server-side generators&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Static_site_generator" rel="noopener noreferrer"&gt;Static site generators&lt;/a&gt; have become a cornerstone of modern web development, offering a streamlined approach to building fast and secure websites. These tools pre-render pages at build time, creating static HTML files which results in blazing-fast load times and improved performance. With the growing need for speed, &lt;a href="https://raygun.com/blog/js-security-vulnerabilities-best-practices/" rel="noopener noreferrer"&gt;security&lt;/a&gt;, and scalability in web development, static site generators are increasingly becoming a popular choice for both developers and businesses.&lt;/p&gt;

&lt;p&gt;In this section, we explore some of the leading static site generators that defined the 2023 web development landscape, and the ones we should keep on the radar for 2024.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xvuxw9uiywahpnf0817.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xvuxw9uiywahpnf0817.png" alt="Image description" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://star-history.com/#withastro/astro&amp;amp;nuxt/nuxt&amp;amp;gohugoio/hugo&amp;amp;gatsbyjs/gatsby&amp;amp;Jekyll/Jekyll&amp;amp;Date" rel="noopener noreferrer"&gt;An overview&lt;/a&gt; of Framework popularity trends.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s been an exciting year in the static site/server-side generation landscape, most notably for &lt;a href="https://github.com/withastro/astro" rel="noopener noreferrer"&gt;Astro&lt;/a&gt;, a relatively new contender that is taking the sector by storm. &lt;a href="https://github.com/gohugoio/hugo" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt; has maintained its lead, sitting over 15k stars ahead of &lt;a href="https://github.com/gatsbyjs/gatsby" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt;. &lt;a href="https://github.com/nuxt/nuxt" rel="noopener noreferrer"&gt;Nuxt’s&lt;/a&gt; steady growth has enabled it to win popularity over &lt;a href="https://github.com/Jekyll/Jekyll" rel="noopener noreferrer"&gt;Jekyll&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The popularity of these static site generators in 2023 sets the stage for further growth and innovation in 2024, as developers continue to prioritize speed, security, and scalability in web development on the server.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Astro&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/withastro/astro" rel="noopener noreferrer"&gt;Astro&lt;/a&gt; is a modern static site generator that allows developers to build fast, content-focused websites using a component-based architecture. It stands out for its ability to deliver lightning-fast performance by only sending essential JavaScript, leveraging partial hydration.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Optimized performance&lt;/strong&gt;: Astro optimizes loading performance by serving mostly static HTML and hydrating components with JavaScript only as needed, making sites faster and more efficient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible component architecture&lt;/strong&gt;: It supports various frontend frameworks within the same project, allowing developers to use the best tool for each specific component.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced developer experience&lt;/strong&gt;: Astro offers a streamlined developer experience with intuitive syntax, fast build times, and a focus on delivering high-quality content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relatively new in the market&lt;/strong&gt;: Being a newer entrant in the static site generator ecosystem, Astro might not have as extensive a community or as many resources as more established tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited plugins and integrations&lt;/strong&gt;: As it is still growing, Astro's ecosystem of plugins and integrations may be less developed compared to other static site generators, potentially limiting its out-of-the-box capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Nuxt&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/nuxt/nuxt" rel="noopener noreferrer"&gt;Nuxt.js&lt;/a&gt; is a powerful Vue.js framework that simplifies the development of universal or single-page Vue apps. Known for its versatility, Nuxt provides a streamlined development experience with its convention-over-configuration approach, offering a robust platform for both static site generation and server-side rendering.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic code splitting&lt;/strong&gt;: Nuxt.js automatically splits code into manageable bundles, improving load times and performance, especially for complex applications with many components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy to use with Vue.js&lt;/strong&gt;: Leveraging Vue.js, Nuxt offers an enjoyable development experience with a familiar, component-based architecture and an intuitive setup, ideal for both newcomers and experienced Vue developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server-side rendering and static site generation&lt;/strong&gt;: Nuxt's flexibility allows developers to choose between generating a static site or using server-side rendering, making it adaptable to various project requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve for non-Vue developers&lt;/strong&gt;: While Nuxt simplifies Vue.js development, those unfamiliar with Vue might face a learning curve in understanding its ecosystem and architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overhead for simple projects&lt;/strong&gt;: For smaller, less complex projects, the extensive features and structure of Nuxt.js could introduce unnecessary overhead, making simpler static site generators a more efficient choice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Hugo&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/gohugoio/hugo" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt; is a fast and flexible static site generator, &lt;a href="https://css-tricks.com/comparing-static-site-generator-build-times/" rel="noopener noreferrer"&gt;renowned for its incredible speed&lt;/a&gt; in building static websites and blogs. It stands out for its efficiency and ease of use, making it a popular choice for developers looking to quickly deploy high-performance sites.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exceptional build speed&lt;/strong&gt;: Hugo's most notable feature is its blazing-fast build time, efficiently handling even large sites with thousands of pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of use and setup&lt;/strong&gt;: Hugo is simple to set up and operate, with a straightforward structure that's easy to understand, making it accessible for both beginners and experienced developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robust content management&lt;/strong&gt;: It offers robust content organization, with a strong emphasis on content management that allows for a high degree of customization and flexibility in content presentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited plugin ecosystem&lt;/strong&gt;: Compared to other static site generators, Hugo has a more limited range of plugins and themes, which might restrict some customization options.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steep learning curve for advanced usage&lt;/strong&gt;: While basic usage of Hugo is straightforward, leveraging its more advanced features requires a steeper learning curve, particularly for those not familiar with GoLang, the language in which Hugo is written.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Gatsby&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/gatsbyjs/gatsby" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; is a modern static site generator based on React, known for creating fast and optimized web applications. It integrates seamlessly with various data sources, making it a popular choice for building complex, data-driven sites with rich interactive features.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance optimization&lt;/strong&gt;: Gatsby automatically optimizes site performance, implementing best practices like code splitting and lazy loading images, leading to fast-loading, efficient websites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich data integration&lt;/strong&gt;: Thanks to its powerful data layer, Gatsby can pull data from multiple sources (CMSs, APIs, databases, etc.), allowing for flexible and dynamic site generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robust plugin ecosystem&lt;/strong&gt;: Gatsby boasts a large collection of plugins, enabling developers to easily add functionality and integrate with various tools and services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexity for beginners&lt;/strong&gt;: Due to its reliance on React and &lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt;, Gatsby can be complex for beginners or for those unfamiliar with these technologies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build times&lt;/strong&gt;: For very large sites, Gatsby's build times can be longer than some other static site generators, which might impact development and deployment efficiency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Jekyll&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Jekyll/Jekyll" rel="noopener noreferrer"&gt;Jekyll&lt;/a&gt; is one of the earliest and most established static site generators, widely used for creating simple, blog-aware websites. Built in Ruby, it integrates seamlessly with GitHub Pages, making it a preferred choice for personal, project, or documentation sites.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple and easy to use&lt;/strong&gt;: Jekyll's straightforward setup and minimalistic approach make it ideal for beginners or for projects that require simple static sites without the need for complex features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong integration with GitHub Pages&lt;/strong&gt;: Jekyll offers seamless integration with &lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;GitHub Pages&lt;/a&gt;, providing an easy pathway to deploy and host websites directly from GitHub repositories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich theme ecosystem&lt;/strong&gt;: It has a robust ecosystem of themes, allowing for quick and easy customization of websites without extensive development.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited to simple use cases&lt;/strong&gt;: Jekyll is less suited for complex applications as it lacks the advanced features and flexibility offered by newer static site generators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruby dependency&lt;/strong&gt;: The need to have Ruby installed can be a barrier for those not familiar with the Ruby environment, potentially limiting its accessibility to a wider audience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What to choose?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each tool, with its unique features and drawbacks, caters to different requirements and preferences. Understanding these is crucial in making an informed decision that aligns with the specific needs and goals of your project.&lt;/p&gt;

&lt;p&gt;Whether it's the blazing-fast builds of Hugo, the robust data integration of Gatsby, the simplicity of Jekyll, the React-based architecture of Gatsby, or the sheer efficiency of Astro and Nuxt, each offers distinct advantages that are pivotal for certain types of projects. However, it's equally important to weigh these against their potential drawbacks, whether it’s complexity, build times, ecosystem limitations, or specific technology dependencies.&lt;/p&gt;

&lt;p&gt;In the end, the choice depends on a balance of factors: the complexity of your project, the scalability you need, your team's familiarity with the underlying technologies, and the specific features you require. By carefully assessing each tool's capabilities and how they match your project's requirements, you can choose a tool that not only meets your current needs but also supports the future growth and evolution of your project.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Like you, I’m always curious and looking to learn. If I've overlooked a noteworthy tool or if you have any feedback to share, reach out on &lt;a href="https://twitter.com/Olwiba" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/olwiba/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tooling</category>
      <category>frontend</category>
    </item>
    <item>
      <title>JS Toolbox 2024: Runtime environments &amp; package management</title>
      <dc:creator>Ollie Bannister </dc:creator>
      <pubDate>Mon, 04 Mar 2024 04:06:24 +0000</pubDate>
      <link>https://dev.to/olwiba/js-toolbox-2024-runtime-environments-package-management-2chg</link>
      <guid>https://dev.to/olwiba/js-toolbox-2024-runtime-environments-package-management-2chg</guid>
      <description>&lt;p&gt;&lt;em&gt;JavaScript is bigger than ever, and the ecosystem is nothing short of overwhelming. In this JS toolbox 2024 series, we’ve selected and analyzed the most noteworthy JS tools, so that you don’t have to.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Just as any durable structure needs a solid foundation, &lt;a href="https://raygun.com/blog/javascript-best-practices/" rel="noopener noreferrer"&gt;successful JavaScript projects&lt;/a&gt; rely heavily on starting with the right tools.&lt;/p&gt;

&lt;p&gt;This post, the first in our JS Toolbox 2024 series, explores the core pillars of the JavaScript &amp;amp; TypeScript ecosystem: Runtime environments, package management, and development servers. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;See &lt;a href="https://dev.to/olwiba/js-toolbox-2024-frameworks-and-static-site-generators-3ad0"&gt;part two, covering frameworks and static site generators, here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this post:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Runtime environments&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Deno&lt;/li&gt;
&lt;li&gt;Bun&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comparing JS runtimes&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Installation&lt;/li&gt;
&lt;li&gt;Performance, stability, and security&lt;/li&gt;
&lt;li&gt;Community&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Package managers&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;NPM&lt;/li&gt;
&lt;li&gt;Yarn&lt;/li&gt;
&lt;li&gt;pnpM&lt;/li&gt;
&lt;li&gt;Bun&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What to choose&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Runtime environments
&lt;/h3&gt;

&lt;p&gt;In JavaScript development, runtimes are the engines that drive advanced, server-centric projects beyond the limitations of a user's browser. This independence is pivotal in modern web development, allowing for more sophisticated and versatile applications. The JavaScript runtime market is more dynamic than ever, with several contenders competing for the top spot. &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;, the long-established leader in this space, now faces formidable competition from &lt;a href="https://deno.com/" rel="noopener noreferrer"&gt;Deno&lt;/a&gt; and &lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;Bun&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Deno is the brainchild of Ryan Dahl, the original creator of Node.js. It represents a significant step forward in runtime technology, emphasizing security through fine-grained access controls and modern capabilities like native TypeScript support.&lt;/p&gt;

&lt;p&gt;Bun has burst onto the scene, releasing version 1.0 in September 2023. Bun sets itself apart with exceptional speed, challenging the performance standards established by its predecessors. Bun's rapid execution capabilities, enabled by &lt;a href="https://en.wikipedia.org/wiki/Just-in-time_compilation" rel="noopener noreferrer"&gt;just-in-time (JIT) execution&lt;/a&gt;, make it a powerful alternative in the runtime environment space.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86w0i8i99kdbvz1j2u6q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86w0i8i99kdbvz1j2u6q.png" alt="Image description" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://star-history.com/#nodejs/node&amp;amp;denoland/deno&amp;amp;oven-sh/bun&amp;amp;Date" rel="noopener noreferrer"&gt;An overview&lt;/a&gt; of framework popularity trends.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The popularity of Node.js has continued to grow over 2023, and I anticipate this will continue into 2024. There has been a slight downtrend in growth trajectory, which I’d guess is due to the other tooling growing in market share.&lt;/p&gt;

&lt;p&gt;Deno has seen substantial growth over 2023. If the current trend continues I anticipate Deno to overtake Node.js in popularity in 2024, though it’s worth mentioning that star-based popularity doesn’t reflect usage in the field. Without a doubt, Node.js will retain its position as the lead environment for production systems throughout 2024.&lt;/p&gt;

&lt;p&gt;Bun has seen the largest growth in this category over the past year. I anticipate that Bun will find a steady foothold and continue its ascent, following the &lt;a href="https://bun.sh/blog/bun-v1.0" rel="noopener noreferrer"&gt;release of version 1.0&lt;/a&gt;. It’s early days for this new player, but comparing early stage growth to others in the category, it’s shaping up to be a high performer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Node.js
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;, acclaimed as the&lt;a href="https://survey.stackoverflow.co/2023/#section-most-popular-technologies-web-frameworks-and-technologies" rel="noopener noreferrer"&gt; leading web technology&lt;/a&gt; by StackOverflow developers, has been a significant player in the web development world since its inception in 2009. It revolutionized web development by enabling JavaScript for server-side scripting, thus allowing for the creation of complex, backend-driven applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60xoz4a65sqv5c7ut8i5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60xoz4a65sqv5c7ut8i5.jpg" alt="Image description" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Advantages
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous and event-driven&lt;/strong&gt;: Node.js operates on an asynchronous, event-driven architecture, making it efficient for scalable network applications. This model allows Node.js to handle multiple operations concurrently without blocking the main thread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich ecosystem&lt;/strong&gt;: With a diverse and extensive range of&lt;a href="https://github.com/topics/nodejs" rel="noopener noreferrer"&gt; tools, resources, and libraries&lt;/a&gt; available, Node.js offers developers an incredibly rich ecosystem, supporting a wide array of development needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized for performance&lt;/strong&gt;: Node.js is known for its low-latency handling of HTTP requests, which is optimal for web frameworks. It efficiently utilizes system resources, allowing for load balancing and the use of multiple cores through child processes and its cluster module.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve for asynchronous programming&lt;/strong&gt;: The non-blocking, asynchronous nature of Node.js can be challenging for developers accustomed to linear programming paradigms, leading to a steep learning curve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Callback hell&lt;/strong&gt;: While manageable, Node.js can lead to complex nested callbacks – often referred to as "callback hell" – which can make code difficult to read and maintain. However, this can be mitigated with modern features like async/await.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Deno&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://deno.com/" rel="noopener noreferrer"&gt;Deno&lt;/a&gt; represents a step forward in JavaScript and TypeScript runtimes, leveraging&lt;a href="https://v8.dev/" rel="noopener noreferrer"&gt; Google’s V8 engine&lt;/a&gt; and built in Rust for enhanced security and performance. Conceived by Ryan Dahl, the original creator of Node.js, Deno is positioned as a more secure and modern alternative, addressing some of the core issues found in Node.js, particularly around security.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fby92z4qnw1e5rghw5ycw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fby92z4qnw1e5rghw5ycw.png" alt="Image description" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced security&lt;/strong&gt;: Deno's secure-by-default approach requires explicit permissions for file, network, and environment access, reducing the risks associated with an all-access runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native TypeScript support&lt;/strong&gt;: It offers first-class support for TypeScript and TSX, allowing developers to use TypeScript out of the box without additional transpiling steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single executable compilation&lt;/strong&gt;: Deno can compile entire applications into a single, self-contained executable, simplifying deployment and distribution processes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Young ecosystem&lt;/strong&gt;: Being relatively new compared to Node.js, Deno’s ecosystem is still growing, which may temporarily limit the availability of third-party modules and tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adoption barrier&lt;/strong&gt;: For teams and projects deeply integrated with Node.js, transitioning to Deno can represent a significant change, posing challenges in terms of adoption and migration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bun&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;Bun&lt;/a&gt; emerges as a promising new contender in the JavaScript runtime space, positioning itself as a faster and more efficient alternative to Node.js. Developed using&lt;a href="https://ziglang.org/" rel="noopener noreferrer"&gt; Zig&lt;/a&gt; and powered by&lt;a href="https://developer.apple.com/documentation/javascriptcore" rel="noopener noreferrer"&gt; JavaScriptCore&lt;/a&gt;, Bun is designed to deliver significantly quicker startup times and lower memory usage, making it an attractive option for modern web development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffu5lqszsh4p1hyxbis1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffu5lqszsh4p1hyxbis1w.png" alt="Image description" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, Bun provides a &lt;em&gt;limited, experimental&lt;/em&gt; native build for Windows with full support for Linux and macOS. Hopefully, over 2024 we see full support for Windows released.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Advantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High performance&lt;/strong&gt;: Bun's main draw is its performance, offering faster execution and lower resource usage compared to traditional runtimes, making it particularly suitable for high-efficiency requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrated development tools&lt;/strong&gt;: It comes with an integrated suite of tools, including a test runner, script runner, and a Node.js-compatible package manager, all optimized for speed and compatibility with Node.js projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evolving ecosystem&lt;/strong&gt;: Bun is continuously evolving, with a focus on enhancing Node.js compatibility and broadening its integration with various frameworks, signaling its potential as a versatile and adaptable solution for diverse development needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Disadvantages&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relative newness in the market&lt;/strong&gt;: As a newer player, Bun's ecosystem is not as mature as Node.js, which might pose limitations in terms of available libraries and community support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compatibility challenges&lt;/strong&gt;: While efforts are being made to improve compatibility with Node.js, there may still be challenges and growing pains in integrating Bun into existing Node.js-based projects or workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Comparing JavaScript runtimes&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Installation&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Each JavaScript runtime has its unique installation process. Here's a brief overview of how to install Node.js, Deno, and Bun:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download&lt;/strong&gt;: Visit the&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt; Node.js website&lt;/a&gt; and download the installer suitable for your operating system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run installer&lt;/strong&gt;: Execute the downloaded file and follow the installation prompts. This process will install both Node.js and npm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify installation&lt;/strong&gt;: Open a terminal or command prompt and type &lt;code&gt;node -v&lt;/code&gt; and &lt;code&gt;npm -v&lt;/code&gt; to check the installed versions of Node.js and npm, respectively.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Managing different versions of Node.js has historically been a challenge for developers. To address this issue, tools like&lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt; NVM (Node Version Manager)&lt;/a&gt; and&lt;a href="https://github.com/coreybutler/nvm-windows" rel="noopener noreferrer"&gt; NVM Windows&lt;/a&gt; have been developed, greatly simplifying the process of installing and switching between various Node.js versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deno&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Shell Command&lt;/strong&gt;: You can install Deno using a simple shell command.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows: &lt;code&gt;irm https://deno.land/install.ps1 | iex&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Linux/macOS: &lt;code&gt;curl -fsSL https://deno.land/x/install/install.sh | sh&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Alternative methods&lt;/strong&gt;: Other methods like downloading a binary from the &lt;a href="https://github.com/denoland/deno/releases" rel="noopener noreferrer"&gt;Deno releases page&lt;/a&gt; are also available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify installation&lt;/strong&gt;: To ensure Deno is installed correctly, type &lt;strong&gt;&lt;code&gt;deno --version&lt;/code&gt;&lt;/strong&gt; in your terminal.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Bun&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Shell Command&lt;/strong&gt;: Similar to Deno, Bun can be installed using a shell command. For instance, on macOS, Linux, and WSL use the command &lt;code&gt;curl https://bun.sh/install | bash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alternative methods&lt;/strong&gt;: For detailed instructions or alternative methods, check the &lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;Bun installation guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify installation&lt;/strong&gt;: After installation, run &lt;code&gt;bun --version&lt;/code&gt; in your terminal to verify that Bun is correctly installed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Performance, stability and security
&lt;/h4&gt;

&lt;p&gt;In evaluating JavaScript runtimes, performance, stability, and &lt;a href="https://raygun.com/blog/js-security-vulnerabilities-best-practices/" rel="noopener noreferrer"&gt;security&lt;/a&gt; are the key factors to consider. Mayank Choubey's benchmark studies provide insightful comparisons among Node.js, Deno, and Bun:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/deno-the-complete-reference/node-js-vs-deno-vs-bun-express-hello-world-server-benchmarking-7bf44c197d2b" rel="noopener noreferrer"&gt;Node.js vs Deno vs Bun: Express hello world server benchmarking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/deno-the-complete-reference/node-js-vs-deno-vs-bun-native-http-hello-world-server-benchmarking-f48edd514513" rel="noopener noreferrer"&gt;Node.js vs Deno vs Bun: Native HTTP hello world server benchmarking&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d recommend giving the post a read if you’re interested in the specifics. Otherwise, I’ll do my best to summarize the results below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Historically, Node.js has been known for its efficient handling of asynchronous operations and has set a standard in server-side JavaScript performance.&lt;/li&gt;
&lt;li&gt;In the benchmark, Node.js displayed solid performance, reflective of its maturity and optimization over the years. However, it didn't lead the pack in terms of raw speed.&lt;/li&gt;
&lt;li&gt;As Node.js has been around for a long time and proven its reliability, it wins the category of &lt;strong&gt;stability&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deno&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deno, being a relatively newer runtime, has shown promising improvements in performance, particularly in the context of security and TypeScript support.&lt;/li&gt;
&lt;li&gt;The benchmark results for Deno were competitive, showcasing its capability to handle server requests efficiently, though it still trails slightly behind in raw processing speed compared to Bun.&lt;/li&gt;
&lt;li&gt;Given its emphasis on security features like explicit permissions for file, network, and environment access, Deno excels in the category of &lt;strong&gt;security&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bun&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bun made a significant impression with its performance in this benchmark. It leverages Zig and JavaScriptCore, which contributes to its faster startup times and lower memory usage.&lt;/li&gt;
&lt;li&gt;In the "Hello World" server test, Bun outperformed both Node.js and Deno in terms of request handling speed, showcasing its potential as a high-performance JavaScript runtime.&lt;/li&gt;
&lt;li&gt;With its significant speed improvements, Bun leads in the category of &lt;strong&gt;performance&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These results suggest that while Node.js remains a reliable and robust choice for many applications, Deno and Bun are catching up, offering competitive and sometimes superior performance metrics.&lt;/p&gt;

&lt;p&gt;Bun, in particular, demonstrates remarkable speed, which could be a game-changer for performance-critical applications. However, it's important to consider other factors such as stability, community support, and feature completeness when choosing a runtime for your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Community&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The community surrounding a JavaScript runtime is vital for its growth and evolution. It shapes development, provides support, and drives innovation. Let's briefly examine the community dynamics for Node.js, Deno, and Bun:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js&lt;/strong&gt;: Node.js has one of the largest, most diverse communities in software development, enriched by a wide array of libraries, tools, and resources. Its community actively contributes to its core and modules, bolstered by global events and forums for learning and networking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deno&lt;/strong&gt;: Deno's community is rapidly growing, drawing developers with its modern and security-centric features. It's characterized by active involvement in the runtime’s development and a strong online presence, particularly on platforms like GitHub and Discord.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bun&lt;/strong&gt;: Although newer, Bun’s community is dynamic and quickly expanding. Early adopters are actively engaged in its development and performance enhancement, with lively discussions and feedback exchanges on online platforms.&lt;/p&gt;

&lt;p&gt;Each of these communities, from Node.js’s well-established network to the emerging groups around Deno and Bun, plays a crucial role in the adoption and development of these runtimes. For developers, understanding the nuances of these communities can be key to leveraging the full potential of a chosen runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Package managers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you’ve ever worked on the front end of a modern web application or if you're a full-stack node engineer, you’ve likely used a package manager at some point. The package manager is responsible for managing the dependencies of your project, such as libraries, frameworks, and utilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;NPM&lt;/a&gt; is the default package manager that comes pre-installed with Node.js. Yarn and PNPM compete to take NPMs spot as the package management tool of choice for developers working in the JavaScript ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrh5vy7i1vva3rjlpzr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrh5vy7i1vva3rjlpzr7.png" alt="Image description" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://star-history.com/#npm/npm&amp;amp;yarnpkg/yarn&amp;amp;pnpm/pnpm&amp;amp;oven-sh/bun&amp;amp;Date" rel="noopener noreferrer"&gt;An overview&lt;/a&gt; of Framework popularity trends.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;NPM&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;Node Package Manager&lt;/a&gt; or NPM for short, is the default and most dominant package manager for JavaScript projects. It comes pre-installed with Node.js, providing developers with immediate access to the npm registry, allowing them to install, share, and manage package dependencies right from the start of their project.&lt;/p&gt;

&lt;p&gt;It was created in 2009 by Isaac Schlueter as a way to share and reuse code for Node.js projects. Since then, it has grown to become a huge repository of packages that can be used for both front-end and back-end development.&lt;/p&gt;

&lt;p&gt;NPM consists of two main components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;NPM CLI (Command Line Interface)&lt;/strong&gt;: This tool is used by developers to install, update, and manage packages (libraries or modules) in their JavaScript projects. It interacts with npm’s online repository, allowing developers to add external packages to their projects easily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPM registry&lt;/strong&gt;: An extensive online database of public and private JavaScript packages, the npm Registry is where developers can publish their packages, making them accessible to the wider JavaScript community. It's known for its vast collection of libraries, frameworks, and tools, contributing to the versatility and functionality of JavaScript projects.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This star graph doesn’t capture much in terms of the overall popularity of NPM CLI given that this tool comes pre-installed with Node.js. Knowing this, it’s worth also reviewing the &lt;a href="https://npmtrends.com/npm-vs-pnpm-vs-yarn" rel="noopener noreferrer"&gt;overall download count of these packages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foi43j44ob9c8pyph4whj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foi43j44ob9c8pyph4whj.png" alt="Image description" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NPM currently has 56,205,118,637 weekly downloads.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Woah, 56.2B! It’s safe to say NPM isn’t going anywhere. From the graphs we can see the steady incline in the overall popularity of this tool through 2023. I predict this growth will continue through 2024. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Yarn&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://yarnpkg.com/" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt; is a well-established open-source package manager created in 2016 by Facebook, Google, Exponent, and Tilde. It was designed to address some of the issues and limitations of NPM, such as speed, correctness, security, and developer experience.&lt;/p&gt;

&lt;p&gt;To improve these areas, Yarn incorporates a range of innovative features. These include workspaces for managing multiple packages within a single repository, offline caching for faster installs, parallel installations for improved speed, a hardened mode for enhanced security, and interactive commands for a more intuitive user interface. These features collectively contribute to Yarn’s robustness and efficiency.&lt;/p&gt;

&lt;p&gt;It features a command-line interface that closely resembles NPM's, but with several enhancements and differences. It utilizes the same package.json file as NPM for defining project dependencies. Additionally, Yarn introduces the yarn.lock file, which precisely locks down the versions of dependencies, ensuring consistent installs across environments. Like NPM, Yarn also creates a node_modules folder where it installs and organizes the packages for your project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38qs5otnwkm9r1r7m2ll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38qs5otnwkm9r1r7m2ll.png" alt="Image description" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Yarn currently has 4,396,069 weekly downloads.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Given that Yarn and pnpM require manual installs this does mean the download counts are un-comparable with NPM but it still gives us a glance at the overall trends.&lt;/p&gt;

&lt;p&gt;In 2023, Yarn appears to have lost some of it’s growth trajectory but still remains the most popular alternative to NPM for package management.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;pnpM&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/pnpm/pnpm" rel="noopener noreferrer"&gt;Performant NPM or pnpM&lt;/a&gt; for short, is another alternative package manager for JavaScript that was created in 2016 by Zoltan Kochan. It was designed to be faster, lighter, and more secure than both NPM and Yarn.&lt;/p&gt;

&lt;p&gt;It excels in saving disk space and speeding up the installation process. Unlike npm, where each project stores separate copies of dependencies, pnpm stores them in a content-addressable store. This approach means if multiple projects use the same dependency, they share a single stored copy, significantly reducing disk usage. When updating dependencies, pnpm only adds changed files instead of duplicating the entire package.&lt;/p&gt;

&lt;p&gt;The installation process in pnpm is streamlined into three stages: resolving dependencies, calculating the directory structure, and linking dependencies, making it faster than traditional methods. pnpm also creates a unique node_modules directory using symlinks for direct dependencies only, avoiding unnecessary access to indirect dependencies. This approach ensures a cleaner dependency structure, while still offering a traditional flat structure option through its &lt;strong&gt;&lt;code&gt;node-linker&lt;/code&gt;&lt;/strong&gt; setting for those who prefer it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpimfz1rfids8ydci0kj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpimfz1rfids8ydci0kj.png" alt="Image description" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;pnpM currently has 8,016,757 weekly downloads.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;pnpM's popularity surged in 2023, and I foresee this upward trend extending into 2024, as an increasing number of developers recognize its resource efficiency and streamlined project setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bun&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As Bun comes with an npm-compatible package manager, I felt it was worth mentioning here.&lt;/p&gt;

&lt;p&gt;I've covered Bun in the Runtime Environments section above.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to choose?
&lt;/h3&gt;

&lt;p&gt;Choosing the right tool for your project in 2024 depends on a variety of factors including your project's specific requirements, your team's familiarity with the technology, and the particular strengths of each tool. In the dynamic world of JavaScript development, having a clear understanding of these factors is crucial for making an informed decision.&lt;/p&gt;

&lt;p&gt;For those prioritizing stability and a proven track record, Node.js remains a top recommendation. It's well-established, supported by a vast ecosystem, and continues to be a reliable choice for a wide range of applications. Node.js's maturity makes it a safe bet, especially for projects where long-term viability and extensive community support are essential.&lt;/p&gt;

&lt;p&gt;On the other hand, if you're inclined towards experimenting with the latest advancements in the field and are operating in a Linux-based environment, Bun presents an exciting opportunity. It stands out for its impressive performance and is ideal for those looking to leverage the bleeding edge of JavaScript runtime technology. Bun’s rapid execution capabilities make it a compelling option for performance-driven projects.&lt;/p&gt;

&lt;p&gt;When it comes to package management, pnpm is an excellent choice. Its efficient handling of dependencies and disk space makes it ideal for developers managing multiple projects or large dependencies. With its growing popularity and focus on performance, pnpM is well-suited for modern JavaScript development.&lt;/p&gt;

&lt;p&gt;JavaScript tools in 2024 offer a massive range catered to different needs and preferences. Whether you opt for the stability of Node.js, the cutting-edge performance of Bun, or the efficient dependency management of pnpM, each tool brings unique strengths to the table. Carefully consider your project’s requirements and team’s expertise to make the best choice for your development journey in 2024.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Like you, I’m always curious and looking to learn. If I've overlooked a noteworthy tool or if you have any feedback to share, reach out on &lt;a href="https://twitter.com/Olwiba" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/olwiba/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tooling</category>
      <category>frontend</category>
    </item>
    <item>
      <title>The art of shipping and monitoring software with speed and confidence</title>
      <dc:creator>Ollie Bannister </dc:creator>
      <pubDate>Fri, 12 Jun 2020 00:55:48 +0000</pubDate>
      <link>https://dev.to/raygun/the-art-of-shipping-and-monitoring-software-with-speed-and-confidence-4b8j</link>
      <guid>https://dev.to/raygun/the-art-of-shipping-and-monitoring-software-with-speed-and-confidence-4b8j</guid>
      <description>&lt;p&gt;Software teams are under increasing pressure to ship code faster than ever before, but without the right workflow and tools in place, this can introduce unnecessary risk and headache. We wanted to share how to configure deployments, identify issues, and track performance gains using tools and process to get the best results and enable you to ship software with speed and confidence.&lt;/p&gt;

&lt;p&gt;The tools we will be using in today’s example include &lt;a href="https://jenkins.io/" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt;, &lt;a href="https://octopus.com/" rel="noopener noreferrer"&gt;Octopus&lt;/a&gt;, and &lt;a href="https://raygun.com/" rel="noopener noreferrer"&gt;Raygun&lt;/a&gt;. These are all available on a free trial so you can follow along.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(We partnered with Octopus to deliver a live demo of the whole process - &lt;a href="https://www.youtube.com/watch?v=aZqOAsuXdj0" rel="noopener noreferrer"&gt;you can watch the recording here&lt;/a&gt;)&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application lifecycle management (ALM)
&lt;/h2&gt;

&lt;p&gt;The power of using these tools in conjunction with one another brings confidence to your deployments, giving you the time to focus on the things that matter… &lt;em&gt;delivering great software to your customers&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Before we jump into the technicals, let’s take a quick look at the &lt;a href="https://en.wikipedia.org/wiki/Application_lifecycle_management" rel="noopener noreferrer"&gt;Application Lifecycle Management (ALM)&lt;/a&gt; process and see where Octopus and Raygun fit into this picture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5t6jd13fqep2m2mftjbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5t6jd13fqep2m2mftjbj.png" alt="Raygun's CI/CD process" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Octopus lives inside the &lt;strong&gt;Release&lt;/strong&gt;, &lt;strong&gt;Deploy&lt;/strong&gt;, and &lt;strong&gt;Operate&lt;/strong&gt; stages of this lifecycle, giving you the ability to reliably release software in a scalable manner. Once your website or application reaches the operation stage Raygun is able to continue this flow right through to the &lt;strong&gt;Monitor&lt;/strong&gt; and &lt;strong&gt;Planning&lt;/strong&gt; stages.&lt;/p&gt;

&lt;p&gt;Having the ability to collect metrics specific to each deployment  helps us &lt;strong&gt;detect&lt;/strong&gt; issues early, &lt;strong&gt;diagnose&lt;/strong&gt; the cause of the problem and make a plan to &lt;strong&gt;resolve&lt;/strong&gt; these issues by providing software teams with the information required and giving them confidence knowing no stone is left unturned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;Here’s a brief overview of some of the tools that we will be using today to ensure we’re all up to speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jenkins
&lt;/h3&gt;

&lt;p&gt;Jenkins is a free, open source automation server that helps automate the non-human part of the &lt;a href="https://raygun.com/blog/software-development-life-cycle/" rel="noopener noreferrer"&gt;software development lifecycle&lt;/a&gt;. This includes continuous integration and facilitating technical aspects of continuous delivery.&lt;/p&gt;

&lt;p&gt;Jenkins is highly customizable with &lt;a href="https://plugins.jenkins.io/" rel="noopener noreferrer"&gt;plugins&lt;/a&gt; to support almost any build pipeline. It supports version control tools and can execute a wide range of scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Octopus
&lt;/h3&gt;

&lt;p&gt;Octopus is an automated deployment and release management tool for managing releases, automating complex application deployments, and automating routine and emergency operations tasks.&lt;/p&gt;

&lt;p&gt;Octopus offers a large range of build server integrations along with a vast variety of deployment target options. It can perform custom steps making it flexible enough to fit any deployment pipeline.&lt;/p&gt;

&lt;p&gt;You can see a Sample Octopus application on &lt;a href="http://samples.octopus.app/" rel="noopener noreferrer"&gt;samples.octopus.app/&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Raygun
&lt;/h3&gt;

&lt;p&gt;Raygun is a software monitoring suite that gives you visibility into how users are really experiencing your software. It’s designed to provide you with actionable data you need to find and fix software issues and performance problems for your end-users.&lt;/p&gt;

&lt;p&gt;Raygun has providers for the most popular programming languages and frameworks, and offers a large range of integrations so you can tailor your monitoring to suit your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying, monitoring, and identifying a problematic deployment
&lt;/h2&gt;

&lt;p&gt;Now that we’ve covered off the tooling we are going to be using, let jump into the fun stuff!&lt;/p&gt;

&lt;p&gt;In this section, I’ll be introducing some issues into my demo website, running a build, deploying this out to our webserver then covering how we can detect and identify the problem quickly.&lt;/p&gt;

&lt;p&gt;Imagine this flow as introducing an unintended issue to your codebase and overlooking the problem. Even with the best processes in place, we can still introduce new errors into production. Perhaps you don’t have sufficient tests or maybe a method or utility was poorly named, whatever the case I’m sure you’ve come across something similar before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Healthy site
&lt;/h3&gt;

&lt;p&gt;First things first, let’s take a look at our healthy demo website. On this site, we have a customer signup form. We are able to successfully create a new user and we don’t exhibit any issues inside our developer console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jac5u464zaa64782or3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jac5u464zaa64782or3.gif" alt="Example signup process" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will serve as the base of our website state, now let’s go ahead and introduce some problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding bugs
&lt;/h3&gt;

&lt;p&gt;On this site, I’ve added an &lt;code&gt;errors.js&lt;/code&gt; script and set &lt;code&gt;enableErrors = true;&lt;/code&gt; - this will serve as our chaos monkey, causing errors to be thrown when the user fills out the signup form. This is to emulate us accidentally introducing bugs into production.&lt;/p&gt;

&lt;p&gt;Using git I’ve committed these changes and pushed up to our git repository, this will be picked up by our CI/CD pipeline in the next phase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jenkins
&lt;/h3&gt;

&lt;p&gt;After our changes have been pushed up, Jenkins will automatically trigger a build for us. This is done using Jenkins “Poll SCM” feature and linking this to our Github repository. This will perform a check every 60 seconds, looking for any changes and if these are found it will kick off our initial job “01_Raygun_CI”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12pbqb6kyu17pptv03io.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12pbqb6kyu17pptv03io.png" alt="Example signup process" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The purpose of this job is to take our &lt;code&gt;master&lt;/code&gt; branch, install any dependencies, run our task runner (Grunt) then generate a NuGet package for us to deploy using the generated distribution files.&lt;/p&gt;

&lt;p&gt;Once the “01_Raygun_CI” job has been completed this will then trigger downstream projects that have been set up to deploy the built package out to a dev environment “02_Raygun_DeployToDev”, test environment “03_Raygun_DeployToTest” and then onto our production environment “04_Raygun_DeployToProd”.&lt;/p&gt;

&lt;h3&gt;
  
  
  Octopus
&lt;/h3&gt;

&lt;p&gt;When Jenkins triggers our 03_Raygun_DeployToTest and 04_Raygun_DeployToProd jobs this will cause two deployments to be registered inside octopus under the specific build number. These kick-off a post-build action that will then deploy this package out to our Azure server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2dtpy422khvykd53f9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2dtpy422khvykd53f9s.png" alt="Octopus overview and filters UI" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For each deployment we have a 3 step process:&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Manual intervention
&lt;/h4&gt;

&lt;p&gt;The manual intervention step allows us to implement an additional check before the deployment goes live. This is perfect in situations where we want to approve any changes before Octopus continues with the deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2dtpy422khvykd53f9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2dtpy422khvykd53f9s.png" alt="Octopus overview and filters UI" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our demo flow today, we have configured this step to only run when we’re deploying out to our production environment. I have approved the deployment to emulate what might happen when a problem is overlooked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo71cd5r8rlfieodwe4k3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo71cd5r8rlfieodwe4k3.png" alt="Octopus overview and filters UI" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Deploy website
&lt;/h4&gt;

&lt;p&gt;Our deployment step is what will upload our files to our webserver. Depending on the type of deployment (test or production) this will change the deployment target respectively. This makes maintenance easy as we only have to define a single process for across multiple deployment options.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftso158my6695h5djc6z8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftso158my6695h5djc6z8.png" alt="Octopus overview and filters UI" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Register deployment
&lt;/h4&gt;

&lt;p&gt;Finally, once our site has been approved and deployed we want to notify Raygun that a deployment has gone out and provide any associated metadata to do with the deployment.&lt;/p&gt;

&lt;p&gt;To achieve this we just need to execute a simple PowerShell script that will fill our payload with some Octopus variables; like build number, user information and any deployment comments then post this off to our deployments endpoint, effectively timestamping our deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5tf40i5r87o09oalxmc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5tf40i5r87o09oalxmc.png" alt="Octopus overview and filters UI" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More information on how to set this up can be found in our &lt;a href="https://raygun.com/documentation/product-guides/deployment-tracking/overview/" rel="noopener noreferrer"&gt;deployment documentation&lt;/a&gt; and you can see and install the &lt;a href="https://library.octopus.com/step-templates/38dc63ed-0c93-4440-93aa-54d8cf6c29ff/actiontemplate-raygun-register-deployment" rel="noopener noreferrer"&gt;Raygun register deployment Octopus community step&lt;/a&gt; in your Octopus instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encounter problems
&lt;/h2&gt;

&lt;p&gt;Now that the errors we introduced have been released out to production, we can revisit our demo website and try completing the signup process again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11j1ram9aed8hfulbsjg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11j1ram9aed8hfulbsjg.gif" alt="Demo site encountering errors" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we filled out the form we triggered three different errors when filling and submitting the form, however, we were still able to proceed with the signup. This gave us the impression that everything was working as intended. This makes identifying issues with your software a difficult task without appropriate monitoring in place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Identifying issues and bad deployments using Raygun
&lt;/h2&gt;

&lt;p&gt;Making use of a monitoring tool such as Raygun makes it easy to detect issues early, diagnose the cause of the problem and come up with a plan to resolve these issues.&lt;/p&gt;

&lt;p&gt;Looking at the &lt;a href="https://raygun.com/platform/crash-reporting" rel="noopener noreferrer"&gt;Raygun Crash Reporting&lt;/a&gt; dashboard we can see that there was a deployment that correlated in a spike in errors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ll2uvh4t11p7cqqq866.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ll2uvh4t11p7cqqq866.png" alt="Raygun crash reporting" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can drill into the specific deployment and see information such as new errors caused since the deployment, any regressions (issues that have reappeared) and also any issues that are still occurring. Making use of our Slack integration and email alerts ensures you can pick up on problems quickly and resolve them before they start impacting customers and costing you revenue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdx3nvi4yr0i05wm5sgrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdx3nvi4yr0i05wm5sgrd.png" alt="Raygun Crash Reporting" width="800" height="453"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Our latest build version introduced 3 new errors.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In addition to this, by making use of our &lt;a href="https://raygun.com/documentation/product-guides/real-user-monitoring/for-web/filters/" rel="noopener noreferrer"&gt;top-level filters feature&lt;/a&gt; in conjunction with &lt;a href="https://raygun.com/platform/real-user-monitoring" rel="noopener noreferrer"&gt;Real User Monitoring&lt;/a&gt; we can also gain visibility into specific performance metrics associated with each build version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj65rr419vl7hov5v6d5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj65rr419vl7hov5v6d5g.png" alt="Raygun Crash Reporting" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comparing two versions against each other can also highlight any positive or negative impacts our changes have had on our website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgktoqclxn4tra3cvg1l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgktoqclxn4tra3cvg1l.png" alt="Raygun Crash Reporting" width="800" height="453"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Our latest build version made things slower.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolving issues
&lt;/h3&gt;

&lt;p&gt;Now that we’ve identified that our latest deployment wasn’t desirable, we can jump in and fix the problems. To do this I’m simply going to revert my previous change setting &lt;code&gt;enableErrors = false;&lt;/code&gt;, committing and pushing up my changes and letting the build pipeline work it’s magic.&lt;/p&gt;

&lt;p&gt;We’re fairly certain we resolved the errors captured by Raygun but often at times, it can be hard to be 100% sure. This is where our “Resolved in version” status comes in handy. Resolving these errors and setting the build version to match our latest deployment gives us peace of mind that if these errors arise after this has gone out we will be notified once again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74nsg3rc0fxf6zhbl46y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74nsg3rc0fxf6zhbl46y.png" alt="Raygun crash reporting" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Rolling forwards vs Rolling back
&lt;/h3&gt;

&lt;p&gt;One approach within Octopus to fix any bad deployments is to re-deploy the previous version. So, for instance, if you deployed version 2020.3.16, which caused issues, you could re-deploy the previous version and be back stable while you figure out what the problem is with your new release so you can then roll forward to a new version with the required features. &lt;/p&gt;

&lt;p&gt;Rolling back doesn't scale to systems that have a data layer, which is what almost all applications have in one way or another. In this approach, you probably have about 1-2 minutes during which you can rollback, and not many bugs, if any, are caught in Production in that time frame, and if you're past this point, it is the point of no return for that release. Your only option is to roll forward with a new version that contains the bug fix, which is affecting your Production systems as you're looking at a considerable amount of data loss. &lt;/p&gt;

&lt;p&gt;One approach to help mitigate these issues is &lt;a href="https://octopus.com/docs/deployment-patterns/blue-green-deployments" rel="noopener noreferrer"&gt;blue-green deployments&lt;/a&gt;. Blue-green deployments are a pattern whereby we reduce downtime during production deployments by having two production environments ("blue" and "green"). You could deploy different releases to different environments, and test this before switching them over at the Load Balancer level. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xerfhcg95v5kcry3r2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xerfhcg95v5kcry3r2i.png" alt="Blue green deployments" width="586" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blue/Green is not without its issues. With Blue/Green, you need to keep the data layer consistent for both releases and requires a lot of discipline from database developers. You can use &lt;a href="http://blog.dixo.net/2015/02/blue-turquoise-green-deployment/" rel="noopener noreferrer"&gt;Turquoise Database Development&lt;/a&gt; to stick to predefined development rules that will help keep your data layer consistent and flexible enough to deal with different releases. &lt;/p&gt;

&lt;p&gt;The real issue here is that you haven't tested or monitored enough. The recommendation is to test and monitor more in your Dev, Test &amp;amp; Pre-Production to catch any of these bugs before they become bugs affecting mission-critical applications. The issue is that data layers are almost impossible to roll back to unless in a situation where there is a system-wide failure and it becomes a necessity. &lt;/p&gt;

&lt;p&gt;The one key take away from this section is to ensure that you have a fully automated CI/CD process with monitoring to allow you to get fast feedback on your application and rollback or roll forward based on your and your applications requirement. &lt;/p&gt;

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

&lt;p&gt;Setting up the correct tooling to build, deploy, and monitor your website plays a key role in ensuring your users are left feeling confident in your service. Hopefully today I’ve demonstrated that using Jenkins, Octopus and Raygun in conjunction with one another can make this process easy for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources mentioned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live recording&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/aZqOAsuXdj0"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=aZqOAsuXdj0" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blog posts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/raygun/confidently-ship-code-using-continuous-integration-ci-and-continuous-delivery-cd-3nlc"&gt;Inside look at Raygun’s CI/CD workflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://octopus.com/docs/" rel="noopener noreferrer"&gt;Octopus documentation&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://raygun.com/documentation/" rel="noopener noreferrer"&gt;Raygun documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Videos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://octopus.com/videos" rel="noopener noreferrer"&gt;Octopus&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/raygunio" rel="noopener noreferrer"&gt;Raygun&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tooling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://octopus.com/trial" rel="noopener noreferrer"&gt;Free Starter edition for Octopus Server&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://raygun.com/signup" rel="noopener noreferrer"&gt;14-day free Raygun Platform trial&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Previous webinar recordings and upcoming webinars&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://octopus.com/events" rel="noopener noreferrer"&gt;Octopus&lt;/a&gt;&lt;br&gt;
&lt;a href="https://raygun.com/webinars" rel="noopener noreferrer"&gt;Raygun&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Samples&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/OctopusSamples/" rel="noopener noreferrer"&gt;Octopus sample repositories&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Olwiba/Webinar-website-example" rel="noopener noreferrer"&gt;Problematic website example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://samples.octopus.app/" rel="noopener noreferrer"&gt;Octopus sample apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://jenkinssample.octopus.com/" rel="noopener noreferrer"&gt;Jenkin sample projects&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://teamcitysample.octopus.com/" rel="noopener noreferrer"&gt;Team city sample projects&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.azure.com/octopussamples/OctoFX" rel="noopener noreferrer"&gt;Azure sample apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>deployments</category>
      <category>jenkins</category>
      <category>octopus</category>
    </item>
    <item>
      <title>Confidently ship code using Continuous Integration (CI) and Continuous Delivery (CD)</title>
      <dc:creator>Ollie Bannister </dc:creator>
      <pubDate>Fri, 12 Jun 2020 00:18:57 +0000</pubDate>
      <link>https://dev.to/raygun/confidently-ship-code-using-continuous-integration-ci-and-continuous-delivery-cd-3nlc</link>
      <guid>https://dev.to/raygun/confidently-ship-code-using-continuous-integration-ci-and-continuous-delivery-cd-3nlc</guid>
      <description>&lt;p&gt;We all want to ship code on a daily basis.&lt;/p&gt;

&lt;p&gt;As developers, we want the faster feedback cycle that comes with continuous delivery, and we know it's better for our team and product in the long run. So why do so many development teams still have such long release cycles?&lt;/p&gt;

&lt;p&gt;While long release cycles are tried and true and can be seen as more stable, teams sacrifice much more than faster feedback cycles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Break the habit of slow releases
&lt;/h2&gt;

&lt;p&gt;When a company is in its infancy, it needs to establish many processes, one of them being the release cycle that it wishes to implement. Although this process can mature over time and can be improved upon, more often than not, it usually remains the same as new updates are released. Years can go by, and release cycles stay the same.&lt;/p&gt;

&lt;p&gt;Historically longer release cycles have been the status quo—teams that follow waterfall methodology will be familiar with this. But, with the rise of Agile practices, more software teams are breaking away from longer cycles and replacing them with shorter, incremental alternatives.&lt;/p&gt;

&lt;p&gt;Longer release cycles do have their strengths; they are well-tested, predictable, and stable. But these benefits come at a cost. With longer release cycles, teams are able to release large, press-worthy updates that can leave big impressions on customers, potential customers and competitors. However, many startups are able to out-gun their larger competitors by adopting shorter release cycles, which enables them to move rapidly, react to change, and focus on innovation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dyklwv0h7hvlfrp6i3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dyklwv0h7hvlfrp6i3m.png" alt="Waterfall vs Agile" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By choosing not to adapt and leaving your longer release cycles to stagnate, you are giving your competition the opportunity to get the upper hand.&lt;/p&gt;

&lt;p&gt;It’s time to break the habit using continuous delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of continuous delivery
&lt;/h2&gt;

&lt;p&gt;Continuous delivery comes with many benefits for all areas of your organization; as a software developer I have listed my top five that make the biggest impact on a daily basis below:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Shorter issue resolution times
&lt;/h3&gt;

&lt;p&gt;When writing software, there’s always a risk that the new feature or piece of functionality you’ve created will introduce bugs to your application or website. Shorter release cycles, make it much easier for you to react and fix problems when they arise.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Focus on innovation
&lt;/h3&gt;

&lt;p&gt;Shorter release cycles also enable you to release new features to customers as soon as they are ready. Depending on your method of delivery, this means that you can go from the conceptual stage of an idea to delivery within a matter of weeks.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Market responsiveness
&lt;/h3&gt;

&lt;p&gt;Market conditions change constantly. Whether you’ve just discovered a new product is losing money, or that more customers are visiting your site from smartphones than laptops, it’s much easier to make a quick change if you are already practicing continuous delivery.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Faster feedback
&lt;/h3&gt;

&lt;p&gt;Releasing new features early and often means you get more frequent feedback, giving you the ability to iterate and learn from your customers. This ensures you’re prioritizing the right kind of work that will make your customers happy.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Developer QOL
&lt;/h3&gt;

&lt;p&gt;Continuous delivery means the responsibility of deployment is spread widely around the organization. Releasing smaller, incremental deployments to your software helps alleviate the stress that can come from one or two people having to deploy a massive piece of work.&lt;/p&gt;

&lt;p&gt;Best of all, a successful release becomes a shared success amongst stakeholders—one you can all celebrate together.&lt;/p&gt;

&lt;p&gt;Here at Raygun, we celebrated the release of our &lt;a href="https://raygun.com/platform/apm" rel="noopener noreferrer"&gt;new Application Performance Monitoring tool&lt;/a&gt; with a Pizza party! It was a great opportunity to congratulate everyone involved in the project and, like, who doesn’t love Pizza?! 🍕&lt;/p&gt;

&lt;h2&gt;
  
  
  Raygun’s CI/CD workflow
&lt;/h2&gt;

&lt;p&gt;Creating a CI/CD pipeline requires the development, test, and operations teams to work together to create a cohesive release process—and the key is &lt;strong&gt;automation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At Raygun, we use a range of different tools and processes to ensure a smooth deployment and minimize impact while also being able to move rapidly and deploy often.&lt;/p&gt;

&lt;p&gt;By using this process, we have been able to make over 365 releases in the past year to a range of different areas of our product. That’s one deployment every day! The below graphic shows our workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftu25fv63idtlcvoi3efv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftu25fv63idtlcvoi3efv.png" alt="Raygun's CI/CD workflow example" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Raygun's process starts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue and project tracking
&lt;/h3&gt;

&lt;p&gt;Firstly, before we can start deploying anything, we need to know what pieces of work we are going to be completing. Having an issue tracking tool makes it easy to create, manage and prioritize items of work to give you a complete overview of the current roadmap and what's coming up.&lt;/p&gt;

&lt;p&gt;At Raygun we use &lt;a href="https://www.atlassian.com/software/jira" rel="noopener noreferrer"&gt;Atlassian's Jira tool&lt;/a&gt; — this provides the level of granularity that we require and makes splitting up pieces of work a breeze.&lt;/p&gt;

&lt;p&gt;There are other great solutions out there, so it’s worth checking them out for yourself and choosing one that best suits your needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Possible alternatives (there are many others):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://trello.com/" rel="noopener noreferrer"&gt;Trello&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://asana.com/" rel="noopener noreferrer"&gt;Asana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pivotaltracker.com/" rel="noopener noreferrer"&gt;Pivotal Tracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sprint.ly/" rel="noopener noreferrer"&gt;Sprintly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://taiga.io/" rel="noopener noreferrer"&gt;Taiga&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Development
&lt;/h3&gt;

&lt;p&gt;Once we know what we are going to be working on, we then need an appropriate IDE for the work to be completed. Depending on what languages &amp;amp; frameworks your project uses the requirements needed from the IDE can differ.&lt;/p&gt;

&lt;p&gt;The choice of IDE is down to developer preference, but I choose to use &lt;a href="https://www.jetbrains.com/rider/" rel="noopener noreferrer"&gt;Rider&lt;/a&gt; when working in-app and &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt; when working on other areas of our product.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version control
&lt;/h3&gt;

&lt;p&gt;When working in a team, having good source control is a must. This enables teams to view historical changes made to the codebase, identifies who made those changes and enables developers the ability to work in parallel on the same files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt; has become the major player in the version control space. As for hosting, there are many version control hosting solutions out there, but we use &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When we’re ready for our work to be merged and deployed we push up our code to GitHub and create a pull request. This then gets peer reviewed and once approved, merged.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqo7pqzwx5d8h9rek7tq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqo7pqzwx5d8h9rek7tq.png" alt="Raygun's peer review process" width="627" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Possible alternatives:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://about.gitlab.com/" rel="noopener noreferrer"&gt;GitLab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bitbucket.org/" rel="noopener noreferrer"&gt;Bitbucket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azure.microsoft.com/en-us/services/devops/repos/" rel="noopener noreferrer"&gt;Azure DevOps repos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Build management
&lt;/h3&gt;

&lt;p&gt;Build management is the first part of the CI/CD pipeline where we can introduce automation. In this step of the process, we can set up triggers to initiate a build when someone pushes code up to the GitHub repository. You can customize your build script to execute the required tasks to build your application and run a variety of integration tests on the updated build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmlselv5miac26kr0lo77.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmlselv5miac26kr0lo77.png" alt="Using Team City to update the build" width="800" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the build has completed and all the tests have finished running, we will now have a passed or failed build. If desired you can then have it automatically post into a notification service like Slack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjr9t8sd32938nx0bk0h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjr9t8sd32938nx0bk0h.png" alt="Using SLack to be notified of the build" width="642" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running this every time someone pushes code brings two main benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It’s easy to know if you have unintentionally impacted another part of the application causing unexpected or broken behavior.&lt;/li&gt;
&lt;li&gt;You always have a build ready for deployment to either test or release without needing to do anything.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We use &lt;a href="https://www.jetbrains.com/teamcity/" rel="noopener noreferrer"&gt;TeamCity&lt;/a&gt; as our build management server and write our tests using &lt;a href="https://nunit.org/" rel="noopener noreferrer"&gt;NUnit&lt;/a&gt; and &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Possible alternatives to TeamCity:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://travis-ci.com/" rel="noopener noreferrer"&gt;Travis CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jenkins.io/" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azure.microsoft.com/en-us/services/devops/" rel="noopener noreferrer"&gt;Azure DevOps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alternatives for testing tools depends on your technology stack and requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5au1hddqhve8hnkck5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5au1hddqhve8hnkck5p.png" alt="Raygun's deployment process" width="195" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gone are the days of manual deployment &lt;em&gt;(well, to a degree)&lt;/em&gt;. Automating your deployment process can severely decrease the complexity of making a release and ensures that certain processes are followed precisely. By using a tool such as &lt;a href="https://octopus.com/" rel="noopener noreferrer"&gt;Octopus Deploy&lt;/a&gt;, we are able to create releases at the click of a button.&lt;/p&gt;

&lt;p&gt;We are able to log information around each release, view the dashboard of what releases have been deployed to which environments and historical deployment information for each project you have set up.&lt;/p&gt;

&lt;p&gt;The best part is—if you needed to roll back to a previous stable release for whatever reason it's as simple as choosing one of the releases from the history and hitting deploy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s not all machines, we want humans involved too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We intentionally remove some of the automation from this part of the process so that we can mitigate some of the risks that come with the continuous delivery model.&lt;/p&gt;

&lt;p&gt;We’ve automated everything up to the point of hitting the deploy button, this is because we want a human to be in control of this. By requiring the developer responsible for the changes to deploy out their work brings many benefits to the deployment process.&lt;/p&gt;

&lt;p&gt;Because they are more involved in the process, they get to see their changes go live and get to be the first one to test it out in beta or production environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrhvu423nqf7saxcyc8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrhvu423nqf7saxcyc8d.png" alt="Using Slack to be notified of the build" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Possible alternatives to Octopus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://travis-ci.com/" rel="noopener noreferrer"&gt;Travis CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jenkins.io/" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azure.microsoft.com/en-us/services/devops/" rel="noopener noreferrer"&gt;Azure DevOps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Alerts
&lt;/h3&gt;

&lt;p&gt;After deployment, it’s often hard to gain visibility on any issues your users come across. Using an error monitoring tool such as &lt;a href="https://raygun.com/" rel="noopener noreferrer"&gt;Raygun&lt;/a&gt; you can pick up on these problems in real-time and fix them before they impact any further users.&lt;/p&gt;

&lt;p&gt;Implementing this with our Slack integration you can be assured that bad deployments are caught early and resolved.&lt;/p&gt;

&lt;p&gt;We have many other great integrations for a variety of different tools that I will cover in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolution
&lt;/h3&gt;

&lt;p&gt;Now that the update has been shipped we can now close off the work item by going back into our issue management tool and updating the status to resolved.&lt;/p&gt;

&lt;p&gt;It’s worth notifying stakeholders that this has been completed before looking at the backlog and starting on the next piece of work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Success
&lt;/h3&gt;

&lt;p&gt;Now that the work has been released it’s worth celebrating a little!&lt;/p&gt;

&lt;p&gt;Announcing new features to customers via the what’s new section or product newsletters is a great place to start. You can then move on to doing things like NPS surveys and talking to customers through messaging tools such as &lt;a href="https://www.intercom.com/" rel="noopener noreferrer"&gt;Intercom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Internal celebrations are also a great way to educate your colleagues about new features in your product. Here at Raygun, every week we get the time to demo things we have released to the rest of the team and congratulate one another.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feedback
&lt;/h3&gt;

&lt;p&gt;Feedback helps to close the loop on your CI/CD pipeline, and although you might not be involved with the customer feedback side, your product team will be listening and informing the product direction. While collecting feedback using tools like Intercom and AskNicely for NPS—we also use our knowledge that only 1% of customers will report issues, which is why we monitor everything for problems using crash reporting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrations
&lt;/h2&gt;

&lt;p&gt;If you’re looking at setting up your CD/CI pipeline, and you’re interested in adding an error tracking tool like Raygun, we have a range of integrations for a variety of different tools so Raygun can fit seamlessly into most tool stacks.&lt;/p&gt;

&lt;p&gt;Our most popular integrations include:&lt;/p&gt;

&lt;h3&gt;
  
  
  Team collaboration
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Slack&lt;/li&gt;
&lt;li&gt;Campfire&lt;/li&gt;
&lt;li&gt;Flowdock&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For sending error notification messages to notify team members&lt;/p&gt;

&lt;h3&gt;
  
  
  Version control
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Bitbucket&lt;/li&gt;
&lt;li&gt;GitLab&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Connect Raygun error groups to issues, resolve Raygun errors from closing issues and view lines of code that caused certain errors to occur inside Raygun.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue and project tracking
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Jira&lt;/li&gt;
&lt;li&gt;Azure DevOps&lt;/li&gt;
&lt;li&gt;Trello&lt;/li&gt;
&lt;li&gt;Zendesk&lt;/li&gt;
&lt;li&gt;FogBugz&lt;/li&gt;
&lt;li&gt;Lighthouse&lt;/li&gt;
&lt;li&gt;Assembla&lt;/li&gt;
&lt;li&gt;YouTrack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create new issues from inside Raygun and link errors groups to work items inside your issue tracking tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service bus
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Azure service bus&lt;/li&gt;
&lt;li&gt;Amazon SQS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Configure your own custom service pipeline with Raygun integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incident response
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;PagerDuty&lt;/li&gt;
&lt;li&gt;VictorOps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On-call support for Raygun error rate monitoring.&lt;/p&gt;

&lt;p&gt;But that’s not all, you can check our full list of integrations &lt;a href="https://raygun.com/features/plugins" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Continuous integration and continuous deployment is modern development practice, and it’s worth the effort to implement. Raygun not only helps strengthen the CI/CD process, it also provides your team with visibility into software errors anywhere in the SDLC, including production. &lt;a href="https://raygun.com/platform/crash-reporting" rel="noopener noreferrer"&gt;See how it works here.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ci</category>
      <category>cd</category>
      <category>process</category>
    </item>
    <item>
      <title>Common front-end mistakes that cause layout problems</title>
      <dc:creator>Ollie Bannister </dc:creator>
      <pubDate>Thu, 11 Jun 2020 22:50:57 +0000</pubDate>
      <link>https://dev.to/raygun/common-front-end-mistakes-that-cause-layout-problems-8fo</link>
      <guid>https://dev.to/raygun/common-front-end-mistakes-that-cause-layout-problems-8fo</guid>
      <description>&lt;p&gt;Successful online services like marketing and e-commerce websites rely on exceptional customer experiences. As a front-end developer, it’s your job to create flawless layouts, so your customer can complete necessary actions (like submit a sign-up form or purchase a Christmas gift). As you probably know, layout issues cause the mistrust of your website, so you’ll want to fix them up ASAP.&lt;/p&gt;

&lt;p&gt;These are some of the most common front-end mistakes that cause layout problems on websites, using examples from our website, &lt;a href="https://raygun.com/blog/" rel="noopener noreferrer"&gt;Raygun.com.&lt;/a&gt; (In a test environment, of course!)&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Stylesheet 404
&lt;/h2&gt;

&lt;p&gt;When experiencing rendering issues, checking to see if the stylesheet is even loading is the first things I look for. By opening your &lt;a href="https://developer.chrome.com/devtools" rel="noopener noreferrer"&gt;developer tools&lt;/a&gt; in the browser and taking a look at the console, you will quickly be able to see if there has been an error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xz0EPS5S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image3.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot of the developer tools window showing a mistake" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xz0EPS5S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image3.png" alt="Common front-end mistakes: developer tools are showing an error" width="800" height="158"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;My developer tools are showing an error on the homepage&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the example above, without the stylesheet loading, the browser doesn’t know how the page should be displayed. Rendering issues usually result in a long list of elements running down the left of the page with nothing but default styles being applied:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tVwCQ2sb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image1.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing a long list of options down the left of the page" src="https://res.cloudinary.com/practicaldev/image/fetch/s--tVwCQ2sb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image1.png" alt="Common front-end mistakes: the browser doesn't know how to apply the style" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The result: the browser doesn’t know how to apply the styles creating a long list down the left of the page&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Style specificity
&lt;/h2&gt;

&lt;p&gt;Sometimes we generate more general styles that will be applied to multiple elements. General styles work well in some cases. However, if you don’t fully understand the order of precedence, styles can be accidentally applied to unintended elements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aKBzHPq6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image9.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing styles being applied to unintended elements" src="https://res.cloudinary.com/practicaldev/image/fetch/s--aKBzHPq6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image9.png" alt="General styles have been applied to unintended elements" width="405" height="299"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Here, general styles have been applied to unintended elements&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not being specific with your styles can cause things to look broken, and if the selector is broad enough, it can even break styles across the whole site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jMuak1JJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image5.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing a header that is hard to use due to layout issues" src="https://res.cloudinary.com/practicaldev/image/fetch/s--jMuak1JJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image5.png" alt="Common front-end mistakes can make the header bar impossible to use" width="800" height="34"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Layout issues in the header make it impossible to navigate around the website&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Missing media queries
&lt;/h2&gt;

&lt;p&gt;Media queries are used to manipulate element styles depending on a set of conditions. The most common example of this would be the (max-width: ) or (min-width: ) condition to change the way the page is rendered on different screen sizes.&lt;/p&gt;

&lt;p&gt;If you are missing a media query or don’t have any to begin with this can make your webpage look broken on screens different to that it was created on.&lt;/p&gt;

&lt;p&gt;Below I compare a desktop view of the Raygun homepage compared to what it would look like on mobile without any media queries to change the styles.&lt;/p&gt;

&lt;h4&gt;
  
  
  Desktop:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--krX6uSPq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image2.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing the homepage without layout problems" src="https://res.cloudinary.com/practicaldev/image/fetch/s--krX6uSPq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image2.png" alt="Without any media queries to change the styles, the desktop version looks fine" width="800" height="355"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Without any media queries to change the styles, the desktop version looks fine&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Mobile:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TyX8LVsi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image4.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing the mobile version looking compressed" src="https://res.cloudinary.com/practicaldev/image/fetch/s--TyX8LVsi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image4.png" alt="Screenshot showing the front-end problems impacting mobile navigation" width="329" height="886"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Mobile, however, is a different story&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Incorrect stack order
&lt;/h2&gt;

&lt;p&gt;When building more complex components such as a navigation you often need to overlap various elements to achieve the desired effect. These elements are layered by applying a z-index property to them to instruct the browser where elements sit in the hierarchy.&lt;/p&gt;

&lt;p&gt;If the z-index property for an element is wrong, it can easily make a page feel broken causing users to leave your website.&lt;/p&gt;

&lt;p&gt;Below I’ve created an example of what can happen if the z-index property is set incorrectly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xG_WvIBi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image10.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing the z-index set incorrectly and is causing stacking" src="https://res.cloudinary.com/practicaldev/image/fetch/s--xG_WvIBi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image10.png" alt="The z-index is set incorrectly and is causing stacking" width="800" height="274"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Here, the z-index is set incorrectly and is causing stacking&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Incorrect field validation
&lt;/h2&gt;

&lt;p&gt;Forms are often used to collect data from your users and are often crucial steps in the user journey. Areas like the signup page or checkout often need to validate the user input to make sure that it matches what’s expected. This validation is often a good thing. However, if the validation rules are incorrect it can lead to users getting unnecessary error messages and can even block users from completing the signup or order. We talk more about how this can affect your business here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0J44Ss45--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image8.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing the Raygun signup form affected by a front-end error" src="https://res.cloudinary.com/practicaldev/image/fetch/s--0J44Ss45--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image8.png" alt="Here, the signup form is falling victim to a common front end mistake" width="584" height="902"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Here, my inputs are correct, but I can’t submit the form – frustrating!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Without the data matching the validation rules, users are usually blocked from submitting the form. There’s now a high chance that the user is going to abandon ship and leave your website.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Browser incompatibility
&lt;/h2&gt;

&lt;p&gt;Choosing which browsers to support is often a challenge. In the ideal world, you would have support for all browsers and versions. But, in doing this, you would also have to make a trade-off with which browser features you can use around your website. If your users are using an old version of IE, for example, and you don’t take this into account when creating the site, things could look broken causing people to leave. Here’s what happened when we applied it to Raygun’s homepage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xzrGD_pj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image11.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing Raygun's homepage affected by browser incompatibility" src="https://res.cloudinary.com/practicaldev/image/fetch/s--xzrGD_pj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image11.png" alt="Common website problems can cause layout issues" width="800" height="435"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;In IE9, the Raygun homepage looks broken&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Understanding your users is critical in choosing which browsers to support. Luckily if you use a tool like Raygun, you can get insight into both the browser and version. This makes choosing which browsers to support much easier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qISQoY0y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image7.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing the Browser performance in real user monitoring" src="https://res.cloudinary.com/practicaldev/image/fetch/s--qISQoY0y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image7.png" alt="" width="800" height="520"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Real User Monitoring shows Browser performance&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Cache busting
&lt;/h2&gt;

&lt;p&gt;Caching assets on your website is always a good idea to help improve load times, and this includes your styles. Don’t forget to update the CSS cache buster after updating your styles, or you will cause many display issues. (Unless you have already automated the process.)&lt;/p&gt;

&lt;p&gt;This is because the browser thinks it already has the file in its cache so doesn’t need to re-fetch it. Depending on the updates you made to your styles, this can have a big impact on your website.&lt;/p&gt;

&lt;p&gt;An easy way to add a cache buster to style links is to add &lt;code&gt;?_=1512598593150&lt;/code&gt; to the &lt;code&gt;href&lt;/code&gt; on your tag, swapping out the UNIX epoch value with the current one.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Native resolution
&lt;/h2&gt;

&lt;p&gt;When using responsive values on images, you need to make sure that you also set the max width and height of the image. This way, the image will never surpass the native resolution. If you stretch an image past its original size, the best case scenario is that you will start to see pixelation. Worst case scenario, you could break it’s aspect ratio depending on the styles applied.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_GPCnh1U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image6.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing pixelation on the homepage" src="https://res.cloudinary.com/practicaldev/image/fetch/s--_GPCnh1U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/12/image6.png" alt="" width="800" height="380"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;SURPASSING AN IMAGES NATIVE RESOLUTION CAN CAUSE PIXELATION, WHICH IS EASILY MISSED&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Surpassing native resolution is probably one of the most common front-end mistakes because it doesn’t look too bad and is easily missed, but fix it up, and it will make your website look professional and polished.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid these front-end mistakes for happier customers
&lt;/h2&gt;

&lt;p&gt;These are just a few of the common front-end mistakes I’ve come across, but hopefully, they provided a good start to detecting and solving them in your applications. Do you have a common issue that you wanted to share? Let me know in the comments!&lt;/p&gt;

&lt;p&gt;Thanks for reading! – Ollie&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>webdev</category>
      <category>css</category>
      <category>html</category>
    </item>
    <item>
      <title>Sass tutorial: A first look at writing more maintainable styles</title>
      <dc:creator>Ollie Bannister </dc:creator>
      <pubDate>Thu, 11 Jun 2020 21:22:15 +0000</pubDate>
      <link>https://dev.to/raygun/sass-tutorial-a-first-look-at-writing-more-maintainable-styles-2nah</link>
      <guid>https://dev.to/raygun/sass-tutorial-a-first-look-at-writing-more-maintainable-styles-2nah</guid>
      <description>&lt;p&gt;Learning how to use HTML, CSS and the basics of JavaScript can be fairly simple. Almost anyone can produce a small, functional website providing you know how to use Google and have some patience.&lt;/p&gt;

&lt;p&gt;However, if you bump the scale of that website up about 10x, add in another developer and create multiple variants – each with their own unique functionality and styles – your code is going to become a hassle to maintain and new hires are going to have a nightmare trying to figure out your codebase.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raygun.com/javascript-error-monitoring" rel="noopener noreferrer"&gt;&lt;br&gt;
    Writing more maintainable code is just the first step. Get the ultimate guide to JavaScript error monitoring here.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using a CSS preprocessor like Sass (Syntactically awesome style sheets) effectively will help modularize your CSS code making it more &lt;a href="https://raygun.com/" rel="noopener noreferrer"&gt;maintainable, understandable and reusable&lt;/a&gt;. Sass consists of two syntaxes, the original syntax called “the indented syntax” and the newer “SCSS”. The examples I give in this post use the SCSS syntax as this is my personal preference, but you can use either. In this Sass tutorial, we’ll walk through the setup process and what you need to know for writing more maintainable and reusable code.&lt;/p&gt;
&lt;h1&gt;
  
  
  Setting up Sass in your new project
&lt;/h1&gt;

&lt;p&gt;Firstly, before we dive into writing any Sass, make sure you have checked out the Sass documentation on &lt;a href="http://sass-lang.com/install" rel="noopener noreferrer"&gt;installation&lt;/a&gt; and the &lt;a href="http://sass-lang.com/guide" rel="noopener noreferrer"&gt;Sass basics&lt;/a&gt; section to get the Sass compiler working on your system.&lt;/p&gt;

&lt;p&gt;Once you have Sass successfully set up for your project, we can now start setting up the file structure for our stylesheet partials and master files.&lt;/p&gt;

&lt;p&gt;I like to create a &lt;code&gt;sass/&lt;/code&gt; directory to hold all our precompiled code and a &lt;code&gt;css/&lt;/code&gt; directory to hold all the output. For easier maintenance on large projects, I would recommend creating extra directories within the &lt;code&gt;sass/&lt;/code&gt; directory to hold different types of partials. As a basic example, I will create the following folder structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7lG5OScl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7lG5OScl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image18.png" alt="" width="301" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in my example colors, components, layout, and typography have been separated into their own directories. This enables us and anyone else digging around in our codebase to easily find files later on.&lt;/p&gt;
&lt;h1&gt;
  
  
  Sass variables and style modularization
&lt;/h1&gt;

&lt;p&gt;Adding Sass to your project brings many advantages. One of the biggest is the ability to set and use variables. When it comes to writing maintainable styles the use of variables is a no-brainer. To create a variable we just need to add a &lt;code&gt;$&lt;/code&gt; before the variable name then just assign the variable a value.&lt;/p&gt;

&lt;p&gt;As an example, I’ll create a &lt;code&gt;_colors.scss&lt;/code&gt; stylesheet partial within our &lt;code&gt;sass/colors/&lt;/code&gt; directory that will hold all our color values. Note that I prefixed the partial with an underscore. This lets Sass know that the file is only a partial file and that it should not be generated into a CSS file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SHHgXXg3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SHHgXXg3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image13.png" alt="" width="298" height="76"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// _colors.scss

$white: #FFFFFF;
$black: #000000;

$red: #C62828;
$blue: #3b88ad;
$green: #2E7D32;
$yellow: #F9A825;
$grey: #424242;
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the &lt;code&gt;_colors&lt;/code&gt; partial we are going to need to import it to the master &lt;code&gt;screen.scss&lt;/code&gt; file found in the &lt;code&gt;sass/&lt;/code&gt; directory. Sass offers the ability to reference other stylesheet partials using the &lt;code&gt;@import&lt;/code&gt; keyword, so, using this, I’ll import the &lt;code&gt;_colors.scss&lt;/code&gt; into &lt;code&gt;screen.scss&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// screen.scss

// Colors
@import "colors/_colors.scss";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now any style partial added to &lt;code&gt;screen.scss&lt;/code&gt; will have visibility of the color variables. I’ll go ahead and create a navigation partial inside of &lt;code&gt;components/&lt;/code&gt; , add it to &lt;code&gt;screen.scss&lt;/code&gt;  and use a color variable as one of the properties:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--14suB_5U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--14suB_5U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image11.png" alt="" width="300" height="104"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// screen.scss

// Colors
@import "colors/_colors.scss";

// Components
@import "components/_navigation.scss";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// _navigation.scss

.navigation {
  position: fixed;
  top: 0;
  width: 100%;
  height: 50px;
  color: $white;
  background: $grey;
  box-shadow: 0 0 5px rgba($grey, 0.8);
  text-align: center;
  line-height: 50px;

  ul {
    display: inline-flex;
    margin: 0;

    li {
      list-style: none;
      padding: 0 50px;
      height: 100%;

      &amp;amp;:hover {
        background: rgba($blue, 0.5);
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see &lt;code&gt;.navigation&lt;/code&gt;  now has a background color of &lt;code&gt;$grey&lt;/code&gt;  and a text color of &lt;code&gt;$white&lt;/code&gt;. This will match the value we assigned in the &lt;code&gt;_colors.scss&lt;/code&gt; partial compiling to &lt;code&gt;background: #424242; color: #FFFFFF;&lt;/code&gt; after running it through the Sass precompiler:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SunF8jih--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image7.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing the result of the precompiler" src="https://res.cloudinary.com/practicaldev/image/fetch/s--SunF8jih--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image7.png" alt="the Sass precompiler will show the following result" width="800" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have this all set up, say we wanted to change the color of &lt;code&gt;$blue&lt;/code&gt; to a new color, all we need to change is the value in &lt;code&gt;_colors.scss&lt;/code&gt; and recompile the Sass. The new value will be assigned to all $blue references:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fdbc54WJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image5.png" class="article-body-image-wrapper"&gt;&lt;img title="Screenshot showing link 1, link 2 and link 3 " src="https://res.cloudinary.com/practicaldev/image/fetch/s--fdbc54WJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image5.png" alt="This Sass tutorial shows the precompiler in blue" width="800" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Mixins and control directives
&lt;/h1&gt;

&lt;p&gt;When it comes to writing maintainable styles it’s always a good idea to keep your code as DRY as possible. Utilizing Sass mixins is a great way to minimize the amount of code you write and helps make it easier for others to read.&lt;/p&gt;

&lt;p&gt;Mixins are essentially blocks of code that let you group together style declarations that we can then reuse throughout our site. Mixins can be used in various ways. I would recommend checking out the &lt;a href="http://sass-lang.com/documentation/file.SASS_REFERENCE.html#defining_a_mixin" rel="noopener noreferrer"&gt;docs&lt;/a&gt; for a more comprehensive look at these.&lt;/p&gt;

&lt;p&gt;Another great feature of &lt;a href="http://sass-lang.com/" rel="noopener noreferrer"&gt;Sass&lt;/a&gt; is the ability to generate styles by using control directives. These include &lt;code&gt;@if&lt;/code&gt;, &lt;code&gt;@for&lt;/code&gt;, &lt;code&gt;@each&lt;/code&gt; and &lt;code&gt;@while&lt;/code&gt;. If you have used another programming language in the past you may already be familiar with these but they are basically a way to generate multiple styles based on a given expression.&lt;/p&gt;

&lt;p&gt;Let’s create some font-size classes using the &lt;code&gt;@each&lt;/code&gt; control directive…&lt;/p&gt;

&lt;p&gt;Firstly we need to create a &lt;code&gt;_font-sizes.scss&lt;/code&gt; partial and import it to &lt;code&gt;screen.scss&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;img title="Screenshot showing that the folder structure and font sizes are important " src="https://res.cloudinary.com/practicaldev/image/fetch/s--uS6YSpbu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image14.png" alt="Sass tutorial : the folder structure and font sizes is important " width="299" height="150"&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// screen.scss

// Colors
@import "colors/_colors.scss";

// Font sizes
@import "typography/_font-sizes.scss";

// Components
@import "components/_navigation.scss";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now specify all the font sizes we want to use, as a variable in &lt;code&gt;_font-sizes.scss&lt;/code&gt;. We can then use this variable to create classes for each value using @each.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// _font-sizes.scss

$font-sizes: 8px 10px 12px 14px 18px 24px;

@each $font-size in $font-sizes {
  .font-size-#{$font-size} {
    font-size: $font-size;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the Sass has been run through the precompiler you will see that we now have a class for each value in your output file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* style.css */

.font-size-8px {
  font-size: 8px;
}

.font-size-10px {
  font-size: 10px;
}

.font-size-12px {
  font-size: 12px;
}

.font-size-14px {
  font-size: 14px;
}

.font-size-18px {
  font-size: 18px;
}

.font-size-24px {
  font-size: 24px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that our font sizes are handled by the $font-sizes variable to add, delete or update a value we just need to edit the variable and Sass will update all the styles for us.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@each&lt;/code&gt; is great when you have a set of values you wish to create styles from. However when dealing with a range of values &lt;code&gt;@for&lt;/code&gt; is better suited. &lt;/p&gt;

&lt;p&gt;To demonstrate the &lt;code&gt;@for&lt;/code&gt; control directive let’s create a simple grid layout. I have already created a _grid.Scss partial in the layout directory and included it in &lt;code&gt;screen.scss&lt;/code&gt;. Now let’s add a &lt;code&gt;$grid-columns&lt;/code&gt; variable, this will be equal to the number of columns you want the grid to have. Using &lt;code&gt;@for&lt;/code&gt; in conjunction with &lt;code&gt;$grid-columns&lt;/code&gt; will generate all the grid classes that we need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// _grid.scss

$grid-columns: 12; // Will be a 12 column grid

.grid-column { // Default grid-column styles
  position: relative;
  float: left;
  width: 100%;
}

@mixin grid-classes($column) {
  $width: (100% / $grid-columns) * $column;

  .grid-column-#{$column} {
    width: $width;
  }

  .grid-column-offest-#{$column} {
    margin-left: $width;
  }
}

@for $column from 0 through $grid-columns {
  @include grid-classes($column);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see from the example we have 12 grid columns, some default styles for &lt;code&gt;.grid-column&lt;/code&gt; class, a mixin to create the grid-classes and the &lt;code&gt;@for&lt;/code&gt; control directive. The &lt;code&gt;@for&lt;/code&gt; loop will run from &lt;code&gt;0&lt;/code&gt; through to whatever you set your &lt;code&gt;$grid-columns&lt;/code&gt; variable as calling the &lt;code&gt;grid-classes()&lt;/code&gt; mixin each time with the &lt;code&gt;$column&lt;/code&gt; number being passed into it.&lt;/p&gt;

&lt;p&gt;Then the mixin will create the &lt;code&gt;.grid-column-{number}&lt;/code&gt; and also &lt;code&gt;.grid-column-offset-{number}&lt;/code&gt; classes for us. After running this code through the precompiler this is what it produced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* style.css */

.grid-column {
  position: relative;
  float: left;
  width: 100%;
}

.grid-column-0 {
  width: 0%;
}

.grid-column-offest-0 {
  margin-left: 0%;
}

.grid-column-1 {
  width: 8.33333%;
}

.grid-column-offest-1 {
  margin-left: 8.33333%;
}

.grid-column-2 {
  width: 16.66667%;
}

.grid-column-offest-2 {
  margin-left: 16.66667%;
}

.grid-column-3 {
  width: 25%;
}

.grid-column-offest-3 {
  margin-left: 25%;
}
/* ...... */
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now use these classes in our markup and will work as expected:&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;img title="Screenshot showing the desired result of the Sass tutorial" src="https://res.cloudinary.com/practicaldev/image/fetch/s--3kvv3TyG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raygun.com/blog/wp-content/uploads/2017/06/image1.png" alt="The classes in our markup and will work as expected for the purpose of this Sass tutorial" width="800" height="86"&gt;
&lt;/h5&gt;

&lt;p&gt;As we have automated the generation of our custom grid, say we wanted to change from 12 columns to 24. We can easily just update the &lt;code&gt;$grid-column&lt;/code&gt; value and recompile our SASS code and everything else is done for us!&lt;/p&gt;

&lt;h1&gt;
  
  
  Wrapping up this Sass tutorial
&lt;/h1&gt;

&lt;p&gt;Writing maintainable styles can easily be accomplished by using Sass, however, this is not the only language out there to do this. Other languages like &lt;a href="http://lesscss.org/" rel="noopener noreferrer"&gt;LESS&lt;/a&gt; and &lt;a href="http://stylus-lang.com/" rel="noopener noreferrer"&gt;Stylus&lt;/a&gt; offer similar features and I would recommend checking them out to find the preprocessor that works for you. If you want to see a full list of all CSS preprocessors &lt;a href="https://www.slant.co/topics/217/~best-css-preprocessors-postprocessors" rel="noopener noreferrer"&gt;Slant’s page&lt;/a&gt; has a list of all options with reviews on each one.&lt;/p&gt;

&lt;p&gt;Thanks for reading, and hope you enjoyed this Sass tutorial on writing more maintainable and reusable code. &lt;/p&gt;

&lt;p&gt;(Source code is available on &lt;a href="https://github.com/Olwiba/raygun-maintainable-sass-example" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.)&lt;/p&gt;

</description>
      <category>sass</category>
      <category>webdev</category>
      <category>maintainable</category>
      <category>demo</category>
    </item>
  </channel>
</rss>
