<?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: Accreditly</title>
    <description>The latest articles on DEV Community by Accreditly (@accreditly).</description>
    <link>https://dev.to/accreditly</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%2F1045142%2Fa534ea30-7b1e-4199-b7e1-87688d0761db.png</url>
      <title>DEV Community: Accreditly</title>
      <link>https://dev.to/accreditly</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/accreditly"/>
    <language>en</language>
    <item>
      <title>How to use Tailwinds `safelist` to handle dynamic classes</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Fri, 23 Aug 2024 09:25:00 +0000</pubDate>
      <link>https://dev.to/accreditly/how-to-use-tailwinds-safelist-to-handle-dynamic-classes-4o16</link>
      <guid>https://dev.to/accreditly/how-to-use-tailwinds-safelist-to-handle-dynamic-classes-4o16</guid>
      <description>&lt;p&gt;&lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; is a popular utility-first CSS framework that allows developers to create custom designs quickly and efficiently. By default, Tailwind CSS generates a wide range of utility classes, which can lead to large file sizes. To address this issue, Tailwind CSS comes with a built-in feature called PurgeCSS that removes unused styles from the production build, making the final CSS file smaller and more performant. However, this automatic removal may sometimes cause issues when certain styles are used dynamically or conditionally in your application. In this article, we'll dive deep into the &lt;code&gt;safelist&lt;/code&gt; feature in Tailwind CSS, learn how to whitelist specific styles, and explore various scenarios where using &lt;code&gt;safelist&lt;/code&gt; can be helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understanding PurgeCSS in Tailwind CSS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://purgecss.com/" rel="noopener noreferrer"&gt;PurgeCSS&lt;/a&gt; is a powerful tool that scans your project files for any class names used and removes the unused ones from the final CSS file. This significantly reduces the size of the generated CSS, making your application load faster. &lt;/p&gt;

&lt;p&gt;By default, Tailwind CSS includes PurgeCSS configuration that scans your HTML, JavaScript, and Vue files for any class names. You can easily tweak what files are picked up within the &lt;code&gt;content&lt;/code&gt; array of the config file.&lt;/p&gt;

&lt;p&gt;In some situations, you might need to prevent specific styles from being removed, even if they're not detected in your files. This is where the &lt;code&gt;safelist&lt;/code&gt; feature comes into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Introducing Safelist
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Safelist&lt;/code&gt; is a feature in Tailwind CSS that allows you to whitelist certain styles so they don't get removed during the purging process. This is particularly useful when you have dynamic class names generated through JavaScript or applied based on user interaction. Another very common use-case for &lt;code&gt;safelist&lt;/code&gt; is when colors or styles are driven from a CMS or backend framework. One such example might be a system that allows a website admin to edit the color of a category in a CMS, which in turn changes the color of the nav items for that category. Tailwind won't see the actual class name as the file will contain server-side code that outputs the color.&lt;/p&gt;

&lt;p&gt;By adding these class names to the safelist, you ensure that they will always be included in your final CSS file, regardless of whether PurgeCSS can find them in your project files or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Configuring Safelist in &lt;code&gt;tailwind.config.js&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;To configure the &lt;code&gt;safelist&lt;/code&gt; in your Tailwind CSS project, you need to modify the &lt;code&gt;tailwind.config.js&lt;/code&gt; file. The &lt;code&gt;safelist&lt;/code&gt; is an array of class names that you want to keep in your final CSS file, even if they're not found in your project files. Here's an example of how to add class names to the &lt;code&gt;safelist&lt;/code&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="c1"&gt;// tailwind.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// your content files here&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;safelist&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;bg-red-500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hover:bg-red-700&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 configurations&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;bg-red-500&lt;/code&gt;, &lt;code&gt;text-white&lt;/code&gt;, and &lt;code&gt;hover:bg-red-700&lt;/code&gt; classes are added to the &lt;code&gt;safelist&lt;/code&gt;. These classes will always be included in your final CSS file, even if PurgeCSS doesn't find them in your project files.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. More advanced configurations
&lt;/h2&gt;

&lt;p&gt;If you have a lot of classes to manage within &lt;code&gt;safelist&lt;/code&gt;, perhaps due to multiple colors and the need to support variants/modifiers such as &lt;code&gt;:hover&lt;/code&gt;, &lt;code&gt;:focus&lt;/code&gt;, &lt;code&gt;:active&lt;/code&gt; and &lt;code&gt;dark:&lt;/code&gt; then it can quickly become very challenging to manage these within &lt;code&gt;safelist&lt;/code&gt;. The list will become huge very quickly.&lt;/p&gt;

&lt;p&gt;That's where patterns come in. Tailwind support regex within the &lt;code&gt;safelist&lt;/code&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;safelist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/from-&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;blue|green|indigo|pink|orange|rose&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;-200/&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/to-&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;blue|green|indigo|pink|orange|rose&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;-100/&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;With these 2 entries we are effectively adding 12 classes. &lt;code&gt;from-{color}-200&lt;/code&gt; and &lt;code&gt;to-{color}-100&lt;/code&gt;, where &lt;code&gt;{color}&lt;/code&gt; is all of the colors in the list. It makes it much easier to manage the lists. Remember that &lt;code&gt;tailwind.config.js&lt;/code&gt; is just a JavaScript file, so you can manage variables at the top of the file if you're managing lists of colors that are repeated heavily.&lt;/p&gt;

&lt;p&gt;It's also possible to define variants for everything within the list without needing to explicitly list them in regex:&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;safelist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/text-&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;blue|green|indigo|pink|orange|rose&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;600|400&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;variants&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;hover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/from-&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;blue|green|indigo|pink|orange|rose&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;-200/&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/to-&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;blue|green|indigo|pink|orange|rose&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;-100/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Safelist Examples and Use Cases
&lt;/h2&gt;

&lt;p&gt;There are several scenarios where using the &lt;code&gt;safelist&lt;/code&gt; feature can be helpful:&lt;/p&gt;

&lt;p&gt;Dynamic class names: If you're generating class names dynamically based on some data or user input, PurgeCSS may not detect these classes and remove them from the final CSS file. By adding these dynamic classes to the &lt;code&gt;safelist&lt;/code&gt;, you can ensure they're always available in your application.&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="c1"&gt;// Example of a dynamic class name based on user input&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This value might come from an API or user input&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alertClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`alert-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Generated class name: 'alert-success'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;alertClass&lt;/code&gt; variable generates a class name based on user input or data from an API. Since PurgeCSS can't detect this dynamic class name, you should add it to the &lt;code&gt;safelist&lt;/code&gt; in your &lt;code&gt;tailwind.config.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Conditional styles: If you have styles that only apply under specific conditions, such as a dark mode or a mobile view, you can use the &lt;code&gt;safelist&lt;/code&gt; to ensure those styles are always included in your final CSS file.&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="c1"&gt;// Example of a conditional style based on a media query&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;767&lt;/span&gt;&lt;span class="nx"&gt;px&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="nx"&gt;hidden&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;mobile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&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;In this example, the hidden-mobile class is only applied when the viewport width is less than 768 pixels. Since this class might not be detected by PurgeCSS, you should add it to the &lt;code&gt;safelist&lt;/code&gt; in your &lt;code&gt;tailwind.config.js&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Best Practices for Safelisting
&lt;/h2&gt;

&lt;p&gt;When using the &lt;code&gt;safelist&lt;/code&gt; feature in Tailwind CSS, keep the following best practices in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only add classes to the &lt;code&gt;safelist&lt;/code&gt; that are truly necessary. Adding too many classes can bloat your final CSS file and negate the benefits of PurgeCSS.&lt;/li&gt;
&lt;li&gt;If you have many dynamic class names or a complex application, consider using a function or regular expression to generate the safelist array. This can help keep your configuration cleaner and more maintainable.&lt;/li&gt;
&lt;li&gt;Test your production build to ensure that all required styles are included. This can help you catch any issues early on and avoid surprises when deploying your application.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The &lt;code&gt;safelist&lt;/code&gt; feature in Tailwind CSS provides a powerful way to whitelist specific styles and ensure they are included in your final CSS file, even if they are not detected by PurgeCSS. By understanding how to configure the &lt;code&gt;safelist&lt;/code&gt; and use it effectively in various scenarios, you can make your Tailwind CSS projects more robust and maintainable. Remember to follow best practices when using the &lt;code&gt;safelist&lt;/code&gt; to ensure your final CSS file remains lean and performant.&lt;/p&gt;

&lt;p&gt;Feel free to look over the &lt;a href="https://tailwindcss.com/docs/content-configuration#safelisting-classes" rel="noopener noreferrer"&gt;Tailwind Docs on Safelist&lt;/a&gt; usage.&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>css</category>
      <category>frontend</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Send email from WordPress the right way</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Tue, 20 Aug 2024 09:14:46 +0000</pubDate>
      <link>https://dev.to/accreditly/send-email-from-wordpress-the-right-way-4jok</link>
      <guid>https://dev.to/accreditly/send-email-from-wordpress-the-right-way-4jok</guid>
      <description>&lt;p&gt;Sending emails is a critical feature for many WordPress websites, whether it’s for account confirmations, notifications, or customized alerts. While many developers might default to using PHP’s &lt;code&gt;mail()&lt;/code&gt; function, WordPress offers more robust and reliable alternatives. Let's explore the best practices for sending both plaintext and HTML emails within WordPress.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Avoid PHP’s &lt;code&gt;mail()&lt;/code&gt; Function?
&lt;/h2&gt;

&lt;p&gt;While PHP’s &lt;code&gt;mail()&lt;/code&gt; function is straightforward, it has several drawbacks, particularly in terms of flexibility and reliability. It lacks support for SMTP authentication, which can lead to emails being flagged as spam. WordPress's built-in functions are designed to overcome these limitations, offering better formatting options and more consistent delivery rates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending Plaintext Emails with WordPress
&lt;/h2&gt;

&lt;p&gt;WordPress makes it easy to send plaintext emails using the &lt;code&gt;wp_mail()&lt;/code&gt; function, which is more versatile than PHP’s native &lt;code&gt;mail()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Here’s a basic example of how you can use &lt;code&gt;wp_mail()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$recipient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'user@example.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Welcome to Our Platform!'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Thank you for joining us.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;wp_mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$recipient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to add headers, such as a custom "From" address or "Reply-To," you can do so with an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'From: Support Team &amp;lt;support@example.com&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Reply-To: support@example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;wp_mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$recipient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach ensures that your emails are sent with the correct headers, improving deliverability and reducing the likelihood of your emails being marked as spam.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crafting HTML Emails in WordPress
&lt;/h2&gt;

&lt;p&gt;If you want to send emails that are more visually engaging, such as newsletters or account information emails, HTML is the way to go. To send HTML emails in WordPress, you’ll need to set the content type to &lt;code&gt;text/html&lt;/code&gt;. This can be achieved by using the &lt;code&gt;wp_mail_content_type&lt;/code&gt; filter.&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;set_html_mail_content_type&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="s1"&gt;'text/html'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;add_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'wp_mail_content_type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'set_html_mail_content_type'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$recipient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'user@example.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Your Account Information'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;h1&amp;gt;Welcome to Our Platform!&amp;lt;/h1&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;p&amp;gt;Here are your account details.&amp;lt;/p&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;wp_mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$recipient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Reset content type to avoid affecting other emails&lt;/span&gt;
&lt;span class="nf"&gt;remove_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'wp_mail_content_type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'set_html_mail_content_type'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we first define a function to set the content type to HTML and then add it as a filter. After sending the email, the filter is removed to ensure that subsequent emails are not inadvertently sent as HTML.&lt;/p&gt;

&lt;p&gt;For a more in-depth discussion on the best practices for sending emails from WordPress, including additional code examples and troubleshooting tips, check out our &lt;a href="https://accreditly.io/articles/how-to-send-email-from-wordpress-the-right-way-html-and-plaintext" rel="noopener noreferrer"&gt;full article here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enhance Your WordPress Skills
&lt;/h2&gt;

&lt;p&gt;If you're looking to deepen your understanding of WordPress, including how to handle email functionality more effectively, consider pursuing our &lt;a href="https://accreditly.io/certifications/wordpress-development" rel="noopener noreferrer"&gt;WordPress Development Certification&lt;/a&gt;. It’s a comprehensive program designed to take your skills to the next level, covering everything from basic setup to advanced customization techniques.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Differences Between "Test Coverage" and "Code Coverage"</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Thu, 13 Jun 2024 08:06:54 +0000</pubDate>
      <link>https://dev.to/accreditly/the-differences-between-test-coverage-and-code-coverage-20fc</link>
      <guid>https://dev.to/accreditly/the-differences-between-test-coverage-and-code-coverage-20fc</guid>
      <description>&lt;p&gt;As developers, we often hear terms like "test coverage" and "code coverage" thrown around in discussions about software quality. While they may sound similar, they represent different aspects of testing and development. Understanding the nuances between these two concepts is essential for improving code quality and ensuring robust software.&lt;/p&gt;

&lt;p&gt;In this article, we’ll delve into what test coverage and code coverage mean, their importance, how they differ, and how you can effectively use them to enhance your development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Test Coverage
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Test coverage&lt;/strong&gt; is a metric that helps us understand how much of our application has been tested. It focuses on the completeness of the testing effort and is usually expressed as a percentage. Test coverage metrics can include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensuring all user requirements have corresponding test cases, known as 'requirements coverage'.&lt;/li&gt;
&lt;li&gt;Verifying that all functions or methods are tested, known as 'functional coverage'.&lt;/li&gt;
&lt;li&gt;Confirming that every branch (e.g., if-else conditions) in the code has been tested, known as 'branch coverage'.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Test Coverage Matters
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Test coverage helps identify untested parts of your application, pointing out areas that may need more thorough testing.&lt;/li&gt;
&lt;li&gt;By ensuring all aspects of your application are tested, you can catch bugs early, leading to higher quality software.&lt;/li&gt;
&lt;li&gt;High test coverage can give developers and stakeholders confidence that the application has been thoroughly vetted. This is especially true when introducing new developers to the project who may not understand some intricacies.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Measuring Test Coverage
&lt;/h2&gt;

&lt;p&gt;Tools like &lt;strong&gt;JUnit&lt;/strong&gt; for Java, &lt;strong&gt;NUnit&lt;/strong&gt; for .NET, and &lt;strong&gt;pytest&lt;/strong&gt; for Python, &lt;strong&gt;PHPUnit&lt;/strong&gt; and the newer &lt;strong&gt;Pest&lt;/strong&gt; for PHP provide features for measuring test coverage. These tools generate reports that show which parts of the application were executed during tests, helping developers identify untested sections.&lt;/p&gt;

&lt;p&gt;Here's a simple example using pytest in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# test_example.py
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;add&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="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;add&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="c1"&gt;# To run the test and measure coverage
# Use the following command:
# pytest --cov=.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;pytest-cov&lt;/code&gt; plugin generates a report showing the percentage of code covered by the tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Code Coverage
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Code coverage&lt;/strong&gt;, on the other hand, measures the extent to which your code has been executed. It's about ensuring that your codebase has been thoroughly exercised by tests. Key metrics for code coverage include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The percentage of lines of code executed, known as 'line coverage'.&lt;/li&gt;
&lt;li&gt;The percentage of executable statements run, known as 'statement coverage'.&lt;/li&gt;
&lt;li&gt;The percentage of possible execution paths tested, known as 'path coverage'.&lt;/li&gt;
&lt;li&gt;The percentage of functions executed, known as 'function coverage'.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Code Coverage Matters
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Code coverage can help identify dead or redundant code that’s never executed, allowing you to clean up your codebase.&lt;/li&gt;
&lt;li&gt;Well-covered code is often easier to maintain because it’s more likely to have fewer hidden bugs.&lt;/li&gt;
&lt;li&gt;High code coverage ensures that changes or refactors don’t introduce new bugs since most paths and lines are tested.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Measuring Code Coverage
&lt;/h2&gt;

&lt;p&gt;Popular tools for measuring code coverage include &lt;strong&gt;Istanbul&lt;/strong&gt; for JavaScript, &lt;strong&gt;Jacoco&lt;/strong&gt; for Java, and &lt;strong&gt;coverage.py&lt;/strong&gt; for Python and PHPUnit (with XDebug, PCOV and phpdbg support) for PHP. These tools integrate with CI/CD pipelines to ensure continuous monitoring of code coverage.&lt;/p&gt;

&lt;p&gt;Here's an example using coverage.py with a Python script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# example.py
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot divide by zero&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="c1"&gt;# test_example.py
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;divide&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_multiply&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;multiply&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="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_divide&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# To run the coverage report
# Use the following command:
# coverage run -m pytest
# coverage report
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;coverage&lt;/code&gt; tool will produce a report showing how much of the code has been executed during the tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Differences Between Test Coverage and Code Coverage
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Focus
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test Coverage&lt;/strong&gt;: Focuses on the extent to which the testing suite covers the application's functionality, requirements, and conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Coverage&lt;/strong&gt;: Concentrates on the extent to which the actual lines of code have been executed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Measurement
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test Coverage&lt;/strong&gt;: Measures how well the tests cover the requirements and functionality of the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Coverage&lt;/strong&gt;: Measures how well the tests execute the code itself, identifying which lines or branches have been run.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Purpose
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test Coverage&lt;/strong&gt;: Ensures all user scenarios and requirements are tested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Coverage&lt;/strong&gt;: Ensures the written code is exercised and validated, uncovering dead or untested code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using Test Coverage and Code Coverage Together
&lt;/h2&gt;

&lt;p&gt;While both metrics provide valuable insights, relying solely on one can be misleading. High test coverage doesn't guarantee that all the code has been executed, and high code coverage doesn’t mean all functional requirements are tested. Combining both gives a more comprehensive view of your testing effectiveness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Showing Off Coverage
&lt;/h2&gt;

&lt;p&gt;If you run an open source project (or even closed source, I suppose), it is common to show badges on the &lt;code&gt;README.md&lt;/code&gt; file of your project that show off the coverage of your project. Check out the very popular &lt;a href="https://github.com/dwyl/repo-badges"&gt;&lt;code&gt;repo-badges&lt;/code&gt;&lt;/a&gt; GitHub repo for a bunch of examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Workflow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Write Tests&lt;/strong&gt;: Write comprehensive tests covering all functional requirements and edge cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure Test Coverage&lt;/strong&gt;: Use tools like pytest or JUnit to measure and report on test coverage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure Code Coverage&lt;/strong&gt;: Use tools like coverage.py or Istanbul to measure code execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combine Reports&lt;/strong&gt;: Analyze combined reports to ensure all aspects are covered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactor and Improve&lt;/strong&gt;: Refactor code and tests based on coverage insights to improve overall quality.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;We go into more detail about &lt;a href="https://accreditly.io/articles/whats-the-difference-between-test-coverage-and-code-coverage"&gt;test coverage vs code coverage&lt;/a&gt; on our own article base. Additionally you can take a look at the following articles for some more info.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://martinfowler.com/bliki/TestCoverage.html"&gt;Understanding Test Coverage&lt;/a&gt; by Martin Fowler&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.softwaretestinghelp.com/code-coverage-vs-test-coverage/"&gt;Code Coverage vs Test Coverage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pytest-cov.readthedocs.io/en/latest/"&gt;pytest-cov Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://coverage.readthedocs.io/en/coverage-5.5/"&gt;Coverage.py Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>DRY: What is it and how to implement it. Don't Repeat Yourself</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Tue, 07 May 2024 13:44:35 +0000</pubDate>
      <link>https://dev.to/accreditly/dry-what-is-it-and-how-to-implement-it-dont-repeat-yourself-59fj</link>
      <guid>https://dev.to/accreditly/dry-what-is-it-and-how-to-implement-it-dont-repeat-yourself-59fj</guid>
      <description>&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY (Don't Repeat Yourself) principle&lt;/a&gt; is a key concept in software development that focuses on reducing code duplication and improving maintainability. By following the DRY principle, developers can create cleaner, more efficient, and less error-prone codebases. In this article, we will discuss the importance of the DRY principle and illustrate its application in JavaScript with two practical examples.&lt;/p&gt;

&lt;p&gt;If you're looking for an example of writing DRY code then check out our &lt;a href="https://accreditly.io/articles/how-to-use-tailwinds-safelist-to-handle-dynamic-classes#content-4-more-advanced-configurations"&gt;article about safelist classes in Tailwind&lt;/a&gt;, which rewrites the ruleset to make them DRY.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 1: Understanding the DRY Principle
&lt;/h2&gt;

&lt;p&gt;The DRY principle states that each piece of logic in a codebase should have a single, unambiguous representation. In other words, you should avoid duplicating code and extract repetitive parts into reusable components or functions. This approach ensures that when you need to make changes or fix bugs, you only have to do it in one place, making your code more maintainable and less prone to errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 2: Benefits of the DRY Principle
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Improved maintainability: With less duplicated code, it is easier to understand, modify, and extend your codebase.&lt;/li&gt;
&lt;li&gt;Reduced likelihood of bugs: By centralizing logic, you reduce the chances of introducing inconsistencies and errors when updating your code.&lt;/li&gt;
&lt;li&gt;Enhanced readability: DRY code is generally more concise and easier to read, making it simpler for other developers to understand and work with your code.&lt;/li&gt;
&lt;li&gt;Easier debugging: When logic is centralized, it's simpler to track down and fix issues, as you only need to investigate one location instead of multiple instances of the same logic.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Section 3: DRY Principle in JavaScript – Example 1
&lt;/h2&gt;

&lt;p&gt;Consider the following code that calculates the price of items after applying a discount:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before applying DRY:&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;function&lt;/span&gt; &lt;span class="nf"&gt;getPriceAfterDiscountA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&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;discountA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&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="nx"&gt;discountA&lt;/span&gt;&lt;span class="p"&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;getPriceAfterDiscountB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&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;discountB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&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="nx"&gt;discountB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getPriceAfterDiscountA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 90&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getPriceAfterDiscountB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we have two functions with nearly identical logic, except for the discount values. This code is repetitive and not DRY.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After applying DRY:&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;function&lt;/span&gt; &lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discount&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="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&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="nx"&gt;discount&lt;/span&gt;&lt;span class="p"&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;getPriceAfterDiscountA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&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;discountA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&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;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discountA&lt;/span&gt;&lt;span class="p"&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;getPriceAfterDiscountB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&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;discountB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.2&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;applyDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discountB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getPriceAfterDiscountA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 90&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getPriceAfterDiscountB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've extracted the common logic into an &lt;code&gt;applyDiscount()&lt;/code&gt; function, which is now used by both &lt;code&gt;getPriceAfterDiscountA()&lt;/code&gt; and &lt;code&gt;getPriceAfterDiscountB()&lt;/code&gt;. This change makes our code DRY and more maintainable.&lt;/p&gt;

&lt;p&gt;As an of maintainability, imagine we have 10 discounts instead of the 2 above, and we have a change to this code where we want to apply some kind of pre or post-tax discount across all available discounts. Using the original method we would have to make that change in 10 places, but in the DRY code we just change the &lt;code&gt;applyDiscount&lt;/code&gt; function. The extra layer of abstraction will result in less code, less bugs, easier to read code and more maintainable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 4: DRY Principle in JavaScript – Example 2
&lt;/h2&gt;

&lt;p&gt;Let's look at another example where we want to calculate the area of different shapes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before applying DRY:&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;function&lt;/span&gt; &lt;span class="nf"&gt;calculateCircleArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;radius&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&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;calculateRectangleArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&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="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&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;calculateTriangleArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&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;(&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After applying DRY:&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;function&lt;/span&gt; &lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;circle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rectangle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;triangle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dimensions&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;base&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&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="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid shape&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;circle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 78.53981633974483&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rectangle&lt;/span&gt;&lt;span class="dl"&gt;"&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="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 24&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;triangle&lt;/span&gt;&lt;span class="dl"&gt;"&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="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 10.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we've extracted the logic for calculating the area of different shapes into a single &lt;code&gt;calculateArea()&lt;/code&gt; function. This function takes the shape and its dimensions as arguments and uses a switch statement to determine the appropriate calculation. By doing so, we've made our code DRY and easier to maintain.&lt;/p&gt;

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

&lt;p&gt;Embracing the DRY principle in JavaScript is an essential practice for writing clean, maintainable, and efficient code. By identifying repetitive code patterns and extracting them into reusable functions, you can reduce the likelihood of bugs and make your codebase more readable and easier to understand. Remember to always be on the lookout for opportunities to apply the DRY principle in your projects, as doing so will significantly improve the quality of your code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please note:&lt;/em&gt; This article was originally posted on &lt;a href="https://accreditly.io/articles/dry-what-is-it-and-how-to-implement-it-dont-repeat-yourself"&gt;Accreditly&lt;/a&gt;, the home of web development certifications for &lt;a href="https://accreditly.io/certifications/php-fundamentals"&gt;PHP&lt;/a&gt;, &lt;a href="https://accreditly.io/certifications/javascript-fundamentals"&gt;JavaScript&lt;/a&gt;, &lt;a href="https://accreditly.io/certifications/wordpress-development"&gt;WordPress&lt;/a&gt; and &lt;a href="https://accreditly.io/certifications/database-fundamentals"&gt;Database Design&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Don't nest ternary operators. Please!</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Thu, 25 Jan 2024 13:27:00 +0000</pubDate>
      <link>https://dev.to/accreditly/dont-nest-ternary-operators-please-1g08</link>
      <guid>https://dev.to/accreditly/dont-nest-ternary-operators-please-1g08</guid>
      <description>&lt;p&gt;In JavaScript, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator"&gt;ternary operator&lt;/a&gt; (also known as the "conditional operator") is a concise and handy tool for conditional logic. However, when it comes to nesting these operators, you might be stepping into a tangled web of complexity. Let's discuss why nesting ternaries can be problematic and explore alternative approaches for cleaner code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Understanding Ternary Operators&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A ternary operator in JavaScript is a one-liner alternative to an if-else statement. It takes three operands: a condition, a result upon the condition being true, and a result if it's false.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;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;condition&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;exprIfTrue&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;exprIfFalse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example:&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;let&lt;/span&gt; &lt;span class="nx"&gt;isAdult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Yes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;The Temptation of Nesting Ternaries&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Nesting ternary operators means using one ternary inside another. It's often seen as a shortcut to handle multiple conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of Nested Ternaries:&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;let&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Senior&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adult&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Minor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this might seem like an efficient use of space, it introduces several issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Readability Concerns&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Nested ternaries can quickly become hard to read and understand, especially for someone new to the code. What seems straightforward to you now might be a puzzle for future-you or other developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hard-to-Read Example:&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;let&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasPremium&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome, premium user!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome, 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;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please log in.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Debugging Difficulties&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Debugging nested ternaries can be challenging. Isolating which part of the ternary chain is causing an issue is more complex than debugging a simple if-else statement or a switch case.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Maintainability Issues&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As your codebase grows and evolves, maintaining nested ternaries becomes problematic. Any modification might require a significant unraveling and reworking of the logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Performance Misconception&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Some developers might think nesting ternaries is faster or more efficient. However, any performance gains are negligible and certainly not worth the trade-off in readability and maintainability.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Alternatives to Nested Ternaries&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;1. &lt;strong&gt;Simple If-Else Statements:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;   For clarity and ease of understanding, a traditional if-else structure is often best.&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Senior&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adult&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Minor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;2. &lt;strong&gt;Switch Statements:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;   For multiple conditions, a switch statement can be more readable.&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;switch &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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Senior&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adult&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Minor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;3. &lt;strong&gt;Function Abstraction:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;   Encapsulate complex logic in a function for better abstraction and reusability.&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Senior&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adult&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Minor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;While ternary operators are a useful feature of JavaScript, nesting them can lead to code that's hard to read, debug, and maintain. Opting for clearer, more straightforward alternatives like if-else statements, switch statements, or function abstraction makes your code more accessible and maintainable. Remember, in programming, clarity should almost always trump cleverness. Production code isn't code golf, shorter isn't always better.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>How to use Generators in JavaScript</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Fri, 10 Nov 2023 11:17:52 +0000</pubDate>
      <link>https://dev.to/accreditly/how-to-use-generators-in-javascript-jol</link>
      <guid>https://dev.to/accreditly/how-to-use-generators-in-javascript-jol</guid>
      <description>&lt;p&gt;JavaScript, a language that has been consistently evolving, introduced a powerful feature in its ES6 (ECMAScript 2015) iteration: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator"&gt;Generators&lt;/a&gt;. While they might seem daunting at first, generators are invaluable tools for handling asynchronous operations and creating custom iterable sequences. Let's unwrap the mystique behind JavaScript generators.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Generators?
&lt;/h2&gt;

&lt;p&gt;Generators are special functions in JavaScript that allow you to yield (or produce) multiple values on a per-request basis. They pause their execution when yielding a value and can resume from where they left off. This "pausing" capability makes generators versatile for many scenarios, particularly asynchronous tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Syntax of Generators
&lt;/h2&gt;

&lt;p&gt;Generators are defined similarly to regular functions but with an asterisk (&lt;code&gt;*&lt;/code&gt;). The &lt;code&gt;yield&lt;/code&gt; keyword is used to produce a sequence of values.&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;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;myGenerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;first value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;second value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;third value&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;h2&gt;
  
  
  Using a Generator
&lt;/h2&gt;

&lt;p&gt;To use a generator, you must first call it, which returns a generator object:&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;gen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;myGenerator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This object follows the iterator protocol and has a &lt;code&gt;next()&lt;/code&gt; method:&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// { value: 'first value', done: false }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// { value: 'second value', done: false }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// { value: 'third value', done: false }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// { value: undefined, done: true }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits of Generators
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Unlike traditional functions that might build and return a huge array, generators produce values on the fly. This means you're not storing large data structures in memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Together with Promises, generators offer a smoother way to handle asynchronous operations. This synergy gave birth to async/await, which is essentially syntactic sugar over generators and promises.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Beyond producing a sequence of values, generators can be used to define custom iteration behaviors.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Yielding Other Generators
&lt;/h2&gt;

&lt;p&gt;Generators can yield other generators, making them composable:&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;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;generatorA&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A2&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="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;generatorB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;generatorA&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;B1&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;genB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generatorB&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// { value: 'A1', done: false }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generators and Error Handling
&lt;/h2&gt;

&lt;p&gt;You can handle errors in generators with try-catch blocks. If an error is thrown inside a generator, it will set the &lt;code&gt;done&lt;/code&gt; property of the generator to &lt;code&gt;true&lt;/code&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;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;errorGenerator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all good&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Problem occurred&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-world Use Cases
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Fetching chunks of data lazily, such as paginated API results or reading large files in segments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generating infinite sequences, like an endless series of unique IDs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pausing and resuming functions, allowing for more complex flow control.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Generators offer an alternative and often cleaner approach to handling asynchronous operations and generating sequences in JavaScript. While they've been somewhat overshadowed by the rise of async/await, understanding generators gives a deeper insight into the language's capabilities. With generators in your JS toolkit, you're better equipped to tackle a wider range of programming challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Lazy Loading of Data
&lt;/h3&gt;

&lt;p&gt;Imagine you have an application that needs to load large sets of data from a server, like a list of products in an e-commerce site. Instead of loading all data at once, which can be inefficient and slow, you can use a generator to lazily load the data as needed.&lt;/p&gt;

&lt;p&gt;Scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have an API endpoint that returns a list of products.&lt;/li&gt;
&lt;li&gt;The API supports pagination, allowing you to fetch a limited number of products per request.&lt;/li&gt;
&lt;li&gt;You want to display these products in batches on the user interface, loading more as the user scrolls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JavaScript Generator Implementation:&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;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;dataFetcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hasMoreData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasMoreData&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?limit=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;offset=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;hasMoreData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Using the generator&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&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;apiUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dataFetcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageSize&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;loadMore&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;nextBatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;nextBatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Update UI with new batch of products&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Initial load&lt;/span&gt;
&lt;span class="nf"&gt;loadMore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Subsequent loads, e.g., triggered by scrolling&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll&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="c1"&gt;// Load more data when the user scrolls down&lt;/span&gt;
  &lt;span class="nf"&gt;loadMore&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;h3&gt;
  
  
  Example: Multi-Step Form Navigation
&lt;/h3&gt;

&lt;p&gt;In a web application, you might have a multi-step form where the user needs to complete several steps in sequence. Using a generator, you can create a smooth and controlled navigation flow through these steps.&lt;/p&gt;

&lt;p&gt;Scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The application has a form divided into multiple steps (e.g., personal details, address information, payment details).&lt;/li&gt;
&lt;li&gt;The user should be able to move forward and backward between steps.&lt;/li&gt;
&lt;li&gt;The application should keep track of the current step and display it accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JavaScript Generator Implementation:&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;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;formWizard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;currentStep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;while &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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentStep&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;currentStep&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;currentStep&lt;/span&gt;&lt;span class="o"&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;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;currentStep&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;currentStep&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Define the steps of the form&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt; &lt;span class="o"&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;Step 1: Personal Details&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Step 2: Address Information&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Step 3: Payment Details&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Create an instance of the form wizard&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wizard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formWizard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Function to move to the next step&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nextStep&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;wizard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentStep&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Update UI to show the current step&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Function to move to the previous step&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;prevStep&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;wizard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentStep&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Update UI to show the current step&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Initial step&lt;/span&gt;
&lt;span class="nf"&gt;nextStep&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>DOM traversal in JavaScript</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Mon, 21 Aug 2023 13:39:03 +0000</pubDate>
      <link>https://dev.to/accreditly/dom-traversal-in-javascript-3b00</link>
      <guid>https://dev.to/accreditly/dom-traversal-in-javascript-3b00</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The Document Object Model (DOM) represents the structure of an HTML document. Navigating or "traversing" this structure is a fundamental aspect of web development, enabling developers to select, modify, delete, or add content on a webpage. This comprehensive guide delves deep into the art of DOM traversal using JavaScript, equipping you with a robust toolkit for handling various traversal scenarios.&lt;/p&gt;

&lt;p&gt;We've done a more comprehensive version of this article over on &lt;a href="https://accreditly.io"&gt;Accreditly's website&lt;/a&gt;: &lt;a href="https://accreditly.io/articles/a-guide-to-dom-traversal-in-javascript"&gt;A guide to DOM traversal in JavaScript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An remember, if you're interested in showcasing your JavaScript skills then be sure to check out our &lt;a href="https://accreditly.io/certifications/javascript-fundamentals"&gt;JavaScript Fundamentals certification&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Basic DOM Selectors
&lt;/h2&gt;

&lt;p&gt;Before we jump into traversal, let's review some fundamental DOM selectors.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  getElementById(): Returns a reference to the first element with the specified ID.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  getElementsByClassName(): Returns a live HTMLCollection of elements with the given class name.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByClassName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  getElementsByTagName(): Returns a live HTMLCollection of elements with the given tag name.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paragraphs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  querySelector(): Returns the first element that matches a specified CSS selector.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mainImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.main-image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  querySelectorAll(): Returns a static NodeList representing elements that match a specified CSS selector.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Parent, Child, and Sibling Relationships
&lt;/h2&gt;

&lt;p&gt;At the core of DOM traversal are the relationships between nodes.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1. Parent Nodes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  parentNode: Returns the parent node of a specified element.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parentOfButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.2. Child Nodes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  firstChild &amp;amp; lastChild: Return the first and last child of a node, respectively.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstChildOfDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;firstChild&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;lastChildOfDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;lastChild&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  children: Returns an HTMLCollection of an element's child elements (excludes text and comment nodes).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divChildren&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  firstElementChild &amp;amp; lastElementChild: Similar to &lt;code&gt;firstChild&lt;/code&gt; and &lt;code&gt;lastChild&lt;/code&gt;, but strictly return element nodes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstElementChildOfDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;firstElementChild&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.3. Sibling Nodes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  nextSibling &amp;amp; previousSibling: Return the next and previous sibling of an element, respectively.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextToButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;nextSibling&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;prevToButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;previousSibling&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  nextElementSibling &amp;amp; previousElementSibling: Similar to &lt;code&gt;nextSibling&lt;/code&gt; and &lt;code&gt;previousSibling&lt;/code&gt;, but strictly for element nodes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextElementToButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;nextElementSibling&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Traversal Methods
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1. Node Iteration
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  childNodes: Returns a NodeList of child nodes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listNodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;childNodes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.2. Filtering Elements
&lt;/h3&gt;

&lt;p&gt;Utilize &lt;code&gt;Array.prototype.filter&lt;/code&gt; to filter nodes based on conditions.&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;listItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;children&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;redItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;listItems&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. DOM Traversal with Events
&lt;/h2&gt;

&lt;p&gt;Combine event listeners with traversal methods to create interactive elements.&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&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="nx"&gt;e&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;nextElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextElementSibling&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;nextElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Advanced Traversal Techniques
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1. Recursive Traversal
&lt;/h3&gt;

&lt;p&gt;Traverse the entire DOM tree recursively. This method is useful when the depth is unknown:&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;function&lt;/span&gt; &lt;span class="nx"&gt;traverseDOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&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;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;traverseDOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&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="nx"&gt;traverseDOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.2. Climbing Up the DOM
&lt;/h3&gt;

&lt;p&gt;In some cases, you may need to find a parent element with a specific selector:&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;function&lt;/span&gt; &lt;span class="nx"&gt;findAncestor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;el&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;listItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;containingDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;findAncestor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mastering DOM traversal is paramount for any full-stack or frontend developer. JavaScript provides a plethora of methods and properties to navigate the intricate relationships of the DOM. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>dom</category>
    </item>
    <item>
      <title>Streaming Large Files with PHP to Save Memory</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Sat, 12 Aug 2023 13:24:52 +0000</pubDate>
      <link>https://dev.to/accreditly/streaming-large-files-with-php-to-save-memory-4nmk</link>
      <guid>https://dev.to/accreditly/streaming-large-files-with-php-to-save-memory-4nmk</guid>
      <description>&lt;p&gt;Handling large files is a common task for web developers. However, if not done properly, it can lead to high memory usage and slow performance. In this tutorial, we will look at how to stream large files to the browser in a memory-efficient way using PHP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of PHP&lt;/li&gt;
&lt;li&gt;An active PHP development environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: File Streaming Basics
&lt;/h2&gt;

&lt;p&gt;Before we dive into the code, let's first understand what file streaming is. When you open a file in PHP with &lt;code&gt;fopen()&lt;/code&gt;, you can read it line by line or character by character with &lt;code&gt;fgets()&lt;/code&gt; or &lt;code&gt;fgetc()&lt;/code&gt;, instead of loading the entire file into memory. This is known as file streaming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Setting Up the PHP Script
&lt;/h2&gt;

&lt;p&gt;Let's create a new PHP script, &lt;code&gt;download.php&lt;/code&gt;. In this script, we will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the file we want to stream.&lt;/li&gt;
&lt;li&gt;Read a portion of the file and output it to the browser.&lt;/li&gt;
&lt;li&gt;Repeat step 2 until the entire file has been read and sent.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'path/to/your/largefile.pdf'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Make sure the file exists&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;file_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;die&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'File not found.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Set headers to tell the browser to download the file&lt;/span&gt;
&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/octet-stream'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Disposition: attachment; filename="'&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Length: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;filesize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Open the file in binary mode&lt;/span&gt;
&lt;span class="nv"&gt;$fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rb'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Output the file&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;feof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fp&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Read and output a chunk of the file&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;fread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Flush the output buffer to free up memory&lt;/span&gt;
    &lt;span class="nb"&gt;ob_flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Close the file&lt;/span&gt;
&lt;span class="nb"&gt;fclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we use &lt;a href="https://php.net/fopen"&gt;&lt;code&gt;fopen()&lt;/code&gt;&lt;/a&gt; to open the file and &lt;a href="https://php.net/fread"&gt;&lt;code&gt;fread()&lt;/code&gt;&lt;/a&gt; to read a chunk of 8192 bytes at a time (which is approximately 8KB). We then output this chunk using &lt;code&gt;echo&lt;/code&gt; and &lt;code&gt;flush&lt;/code&gt; the output buffer to free up the memory used. This process repeats until the end of the file (&lt;code&gt;feof($fp)&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In this tutorial, you've learned how to stream large files to the browser in a memory-efficient way using PHP. This method is very useful when dealing with large files that could otherwise consume significant server memory and lead to performance issues. Always remember to close any open file handles and flush the output buffer to free up memory.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>files</category>
    </item>
    <item>
      <title>Building a frontend auth in WordPress</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Tue, 01 Aug 2023 10:06:02 +0000</pubDate>
      <link>https://dev.to/accreditly/building-a-frontend-auth-in-wordpress-4lpn</link>
      <guid>https://dev.to/accreditly/building-a-frontend-auth-in-wordpress-4lpn</guid>
      <description>&lt;p&gt;WordPress, love it or hate it, is here to stay. It powers ~65% of the Internet, and is used by corporations large and small, bloggers, agencies and everything in between.&lt;/p&gt;

&lt;p&gt;As WordPress website's grow in functionality it often becomes necessary for users to log into the site. One example of this may be when you offer (pay)walled content, whereby a user must be logged in to read it.&lt;/p&gt;

&lt;p&gt;There are plugins that can do this, but that's a heavy dependency on a third-party that can introduce security risks, not to mention a risk of them disappearing (this happens more often than you may think, even for popular plugins).&lt;/p&gt;

&lt;p&gt;So, roll your own.&lt;/p&gt;

&lt;p&gt;We've created a series of tutorials on &lt;a href="https://accreditly.io/articles/create-a-frontend-auth-experience-in-wordpress"&gt;how to build your own frontend auth experience in WordPress&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This series of articles takes you through the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://accreditly.io/articles/building-a-frontend-registration-form-in-wordpress"&gt;Building a frontend registration form in WordPress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://accreditly.io/articles/creating-a-frontend-login-form-in-wordpress"&gt;Building a frontend login form in WordPress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://accreditly.io/articles/building-a-frontend-forgotten-password-form-in-wordpress"&gt;Building a frontend forgotten password form in WordPress&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Check it out, and if you have any questions let us know in the comments.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>wordpress</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding blobs in JavaScript</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Fri, 21 Jul 2023 08:57:19 +0000</pubDate>
      <link>https://dev.to/accreditly/understanding-blobs-in-javascript-5gcd</link>
      <guid>https://dev.to/accreditly/understanding-blobs-in-javascript-5gcd</guid>
      <description>&lt;p&gt;JavaScript, a powerful and flexible language, offers many features that make it a staple for client-side web development. One of these features is the Blob object, a fundamental data type that plays a crucial role when dealing with binary data.&lt;/p&gt;

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

&lt;p&gt;A Blob (Binary Large OBject) is an immutable object in JavaScript that represents raw, unprocessed data. This data can be of any type and is not limited to binary. Blobs are typically used to store data such as images, audio, or other multimedia files, though they can hold almost any data type.&lt;/p&gt;

&lt;p&gt;The data contained in a Blob is not necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to provide features like &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;lastModified&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Blob
&lt;/h2&gt;

&lt;p&gt;You can create a Blob object in JavaScript using the Blob constructor. Here's a simple example:&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;let&lt;/span&gt; &lt;span class="nx"&gt;helloBlob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Blob&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, Blob!&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="na"&gt;type&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, the Blob constructor takes two arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An array of data parts: This could be a simple array of strings, &lt;code&gt;ArrayBuffer&lt;/code&gt;, &lt;code&gt;ArrayBufferView&lt;/code&gt; (a typed array), Blob objects, or a mix of any of the above.&lt;/li&gt;
&lt;li&gt;An options object: This is optional and can be used to specify the MIME type of the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reading a Blob
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FileReader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Blob&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, Blob!&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="na"&gt;type&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readAsText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;readAsText&lt;/code&gt; method is used to read the content of the blob as a string.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blob URLs
&lt;/h2&gt;

&lt;p&gt;Blobs can also be used to create URLs that can be used to link or display binary data such as an image. This is done using the &lt;code&gt;URL.createObjectURL()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Here's an example:&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;let&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Blob&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, Blob!&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="na"&gt;type&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;blobUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Now you can use blobUrl to display the data&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blobUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Outputs something like: blob:http://your-url.com/550e8400-e29b-41d4-a716-446655440000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The URL.createObjectURL() method creates a DOMString containing an URL representing the object given in the parameter.&lt;/p&gt;

&lt;p&gt;In summary, the Blob object is a powerful tool in JavaScript for handling raw data. It is particularly useful for working with binary objects where you need to manipulate files, such as images or multimedia content. Understanding how to use Blobs effectively can greatly expand your JavaScript capabilities when handling complex data types.&lt;/p&gt;

&lt;p&gt;You can read more about Blobs, and their Web API on the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob"&gt;MDN docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://accreditly.io/articles/understanding-blobs-in-javascript"&gt;Read this article on Accreditly&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to migrate a live website without losing data</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Thu, 20 Jul 2023 09:52:48 +0000</pubDate>
      <link>https://dev.to/accreditly/how-to-migrate-a-live-website-without-losing-data-53g4</link>
      <guid>https://dev.to/accreditly/how-to-migrate-a-live-website-without-losing-data-53g4</guid>
      <description>&lt;p&gt;In this guide we're going to discuss how to migrate a live website to a new infrastructure with &lt;strong&gt;no downtime&lt;/strong&gt; and &lt;strong&gt;without losing data&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Website being migrated
&lt;/h2&gt;

&lt;p&gt;We'll assume in this example that we're dealing with a busy ecommerce website. The ecommerce website processes around 500 orders a day, so downtime is costly, and data is constantly moving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem areas of a migration
&lt;/h2&gt;

&lt;p&gt;It's important to understand the potential issues with any migration. These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data in your database&lt;/strong&gt; (the most challenging aspect)&lt;/li&gt;
&lt;li&gt;Your code and changes&lt;/li&gt;
&lt;li&gt;Environment files and variables not in version control&lt;/li&gt;
&lt;li&gt;Files uploaded in your application&lt;/li&gt;
&lt;li&gt;DNS changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Current architecture
&lt;/h2&gt;

&lt;p&gt;Let's start by outlying our current infrastructure. We'll try and keep it simple. If you have more complex infrastructure then it's likely this guide will still work, or you'll understand the nuances enough to translate it to your own use case.&lt;/p&gt;

&lt;p&gt;Our current infrastructure consists of a single app server, which contains our web server (Apache or nginx) and a database server (MySQL). This guide will work perfectly fine if you're on immutable architecture (eg. multiple web servers, load balancer and single database).&lt;/p&gt;

&lt;h3&gt;
  
  
  User uploaded files
&lt;/h3&gt;

&lt;p&gt;Files uploaded by users are currently handled by S3, so there isn't much for us to worry about there as that will continue to happen. On any solution I always recommend using an external service for housing user uploaded files as it is cheaper, more reliable, easier to implement, easier to migrate, and you won't be plagued with disk space issues.&lt;/p&gt;

&lt;p&gt;However, we'll discuss how you can migrate files as part of this guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  The migration
&lt;/h2&gt;

&lt;p&gt;OK, let's begin.&lt;/p&gt;

&lt;h3&gt;
  
  
  User uploaded files
&lt;/h3&gt;

&lt;p&gt;In our app we use S3 for files, so really this doesn't need much attention at all, but if you're not using a third party to handled user uploaded files then you'll need to move them there.&lt;/p&gt;

&lt;p&gt;Unfortunately, although this process is reasonably straightforward, it will require changes to your application code. There are ways to do it without changing code (such as rsyncing to the service), but they aren't recommended.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Make changes to your codebase to use the service's endpoint for files.
&lt;/h4&gt;

&lt;p&gt;With this we'll assume we're using AWS S3. You'll need to make changes to your app's code to point at S3 rather than your local files. Obviously the steps to do this vary depending on your own application. I'd also recommend putting Cloudfront in front of your S3 bucket for both speed and cost savings.&lt;/p&gt;

&lt;p&gt;You should put this change behind a feature flag. A feature flag is a concept used in software development to enable and disable features of an app very quickly. In simple terms it's a config file full of booleans. In our case it allows us to quickly switch from using local files to S3 files by changing a single variable.&lt;/p&gt;

&lt;p&gt;Once it's all implemented and tested, leave the feature turned off so we're still serving local files.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Move existing files to S3.
&lt;/h4&gt;

&lt;p&gt;Next we need to move all of our existing files to S3. The easiest way to do this is using AWS' CLI client.&lt;/p&gt;

&lt;p&gt;First off &lt;a href="https://help.mypurecloud.com/articles/create-iam-resources-for-aws-s3-bucket/"&gt;set up an IAM user who has read-write access to a bucket on S3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"&gt;install AWS CLI&lt;/a&gt; on your server.&lt;/p&gt;

&lt;p&gt;Then you can sync all of your files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws s3 sync source_folder  s3://your_bucket_name/destination_folder/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Please note: You don't have to use AWS S3. There are now lots of other services available, which are often cheaper than S3, that use the same suite of APIs as S3 so they're drop-in replacements.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. (Optional) set up Cloudfront
&lt;/h4&gt;

&lt;p&gt;Cloudfront is a CDN. It has many uses, but for us it sits in front of S3 and serves files for us.&lt;/p&gt;

&lt;p&gt;You can configure Cloudfront to run as 'origin pull', where it will pull files with the same path requested directly from S3, and then cache them indefinitely.&lt;/p&gt;

&lt;p&gt;For example, let's say you have a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example-s3-bucket.com/images/myfile.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once configured you can instead request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://my-example-app.cloudfront.net/images/myfile.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the first request Cloudfront will download the file to the CDN, cache it, then serve it to the user. Subsequent requests will serve the cached file.&lt;/p&gt;

&lt;p&gt;AWS have &lt;a href="https://repost.aws/knowledge-center/cloudfront-https-requests-s3"&gt;a guide on setting this up&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Ensure future files are uploaded to S3
&lt;/h4&gt;

&lt;p&gt;You'll need to change your application's code to ensure future files are uploaded to S3.&lt;/p&gt;

&lt;p&gt;You have multiple options here, you can opt to &lt;a href="https://accreditly.io/articles/uploading-files-directly-to-aws-s3-from-an-html-form-securely"&gt;upload files directly to AWS S3 from a HTML form&lt;/a&gt;, or you can upload them to your server and sync from there.&lt;/p&gt;

&lt;p&gt;There is no right or wrong approach, it depends on your circumstances.&lt;/p&gt;

&lt;p&gt;Ensure this feature also has its own feature flag, or ties into the original feature flag from step 1.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Go live with S3 files
&lt;/h4&gt;

&lt;p&gt;Once tested and you're happy you can resync all of your files (step 2: &lt;code&gt;aws s3 sync source_folder  s3://your_bucket_name/destination_folder/&lt;/code&gt;), and then go live.&lt;/p&gt;

&lt;p&gt;Going live is as simple as changing the feature flag to true.&lt;/p&gt;

&lt;p&gt;You can always re-sync after going live, just in case any files were uploaded during the last sync prior to going live.&lt;/p&gt;

&lt;p&gt;You can get this done prior to the rest of the migration.&lt;/p&gt;

&lt;h3&gt;
  
  
  DNS preparation
&lt;/h3&gt;

&lt;p&gt;OK, so that's user files taken care of, now we need to prep DNS.&lt;/p&gt;

&lt;p&gt;DNS is a subject that is simple for the basics, but extremely complex when you dig into it. Fortunately we're sticking to the basics.&lt;/p&gt;

&lt;p&gt;DNS is just a list of signposts for services. When someone's browser requests example.com their computer will ask the nameserver (DNS server) for that domain what IP address example.com points to. It's as simple as that.&lt;/p&gt;

&lt;p&gt;A DNS record consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Record type (A, AAAA, CNAME, TXT, MX, etc)&lt;/li&gt;
&lt;li&gt;Record target (&lt;code&gt;example.com&lt;/code&gt;, &lt;code&gt;www.example.com&lt;/code&gt;, &lt;code&gt;whatever.example.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Record value (IP address for a lot of records, a string for others)&lt;/li&gt;
&lt;li&gt;TTL (time to live. Effectively the amount of time to cache the record)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During the migration we're going to change the record value for both our root domain (example.com) and &lt;code&gt;www.&lt;/code&gt; record.&lt;/p&gt;

&lt;p&gt;In preparation for this we need to do 2 things:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Ensure &lt;code&gt;www.&lt;/code&gt; is a CNAME for the root domain
&lt;/h3&gt;

&lt;p&gt;Assuming this works for your infrastructure, you should ensure the &lt;code&gt;www.&lt;/code&gt; record of your domain DNS is a CNAME that points back to the root domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CNAME www.example.com example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is generally considered best practice, simply because you only need to change one record to move the domain which reduces chances of human error, or extremely rare issues like your DNS provider having an outage half way through editing 2 fields.&lt;/p&gt;

&lt;p&gt;Doing this ahead of time gives your DNS time to propagate to providers.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Reduce your TTL
&lt;/h4&gt;

&lt;p&gt;The TTL of your records is effectively the time DNS providers cache the record.&lt;/p&gt;

&lt;p&gt;During normal activities you are safe to set this as a reasonably high value such as an hour, or a day (in seconds). However, during a migration we want DNS providers to update as fast as possible, so it's a good idea to update this to a much lower value.&lt;/p&gt;

&lt;p&gt;Most DNS providers have a lower cap on what they'll allow, but you should be able to set it to something like &lt;code&gt;30&lt;/code&gt;, which is 30 seconds.&lt;/p&gt;

&lt;p&gt;Doing this ahead of time allows DNS providers to update their systems accordingly. &lt;/p&gt;

&lt;p&gt;Remember though, TTL is a guidance you provide and it's up to DNS providers to actually take note of it. Many ISPs, especially residential ISPs who provide DNS services to their customers, will heavily cache records regardless of your TTL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up your new infrastructure and code freeze
&lt;/h3&gt;

&lt;p&gt;At this point you'll want to set up your new infrastructure and ensure everything works as expected.&lt;/p&gt;

&lt;p&gt;You can test it using a hosts file entry. Getting this all set up is outside the scope of this guide.&lt;/p&gt;

&lt;p&gt;Once set up you should have the following in place:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Old infrastructure still in place.&lt;/li&gt;
&lt;li&gt;Files on old infrastructure being uploaded to a third-party such as S3.&lt;/li&gt;
&lt;li&gt;DNS prepared for fast changes.&lt;/li&gt;
&lt;li&gt;New infrastructure in place, but not used yet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point you need to implement a code freeze. No more code changes can be made, and no deployments should be made.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrate and sync data
&lt;/h3&gt;

&lt;p&gt;The most challenging part of moving a live website that transacts is the database. The data is changing with every transaction, and your application is probably writing to the database frequently.&lt;/p&gt;

&lt;p&gt;There are a number of solutions to moving your data without causing any data loss. We'll be focusing on two solutions here (there are others).&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Migrate and remote connect
&lt;/h4&gt;

&lt;p&gt;The first and simplest option is to use a remote connection. Read on for how this works, but be aware that you could be unlucky and have a small amount of "data loss" (it is recoverable) with this approach, so it's important you understand the risk involved. &lt;/p&gt;

&lt;p&gt;OK, so this approach involves setting up your new infrastructure to allow remote connections. You then manually migrate your data from old infrastructure (create an export, transfer it to new server, import it). Once migrated you change the connection details on the old infrastructure to point to the database on the new infrastructure.&lt;/p&gt;

&lt;p&gt;At this point your visitors will be using the web server on the old infrastructure, but the database server on the new infrastructure. This allows you to then make DNS changes and it doesn't really matter how long it takes to propagate.&lt;/p&gt;

&lt;p&gt;There are risks. Running an export, transferring it, and importing again takes time. How much time depends on the amount of data and the resources available on all machines involved. If you don't have a particularly busy website then this is probably OK.&lt;/p&gt;

&lt;p&gt;If the worst should happen and your website makes a sale during the migration then the data isn't lost, it will be sat on the old database. Depending on the complexity of your data schema it might be straightforward to manually move the missing rows to your new database.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Create a master/slave setup
&lt;/h4&gt;

&lt;p&gt;MySQL has a concept called master/slave, something that was popular with older hard drives that were prone to failure.&lt;/p&gt;

&lt;p&gt;Effectively the master database acts as you would expect it to, all writes go into it, and any data being read by the application is read from there.&lt;/p&gt;

&lt;p&gt;The slave is never read from, but any writes that happen also happen to the slave. You effectively get a real-time copy of the database that is constantly being updated as changes happen.&lt;/p&gt;

&lt;p&gt;The concept here is to set up the database on the old infrastructure as the master, and set up the database on the new infrastructure as the slave. Once you're happy data is being written to both you can simply switch roles so the new infrastructure becomes the master.&lt;/p&gt;

&lt;p&gt;This approach seems much simpler, and won't incur any data loss. However, setting up remote master/slave instances isn't as straightforward as it may seem and it adds a level of complication that may not be favourable.&lt;/p&gt;

&lt;p&gt;Although this solution is housed entirely in MySQL it is possible to do it within the application itself. Many application frameworks support master/slave setups, where you're able to set up a single 'read' source with multiple write destinations (or multiple reads to load balance your databases). You may find it easier to implement the master/slave setup in your application rather than in MySQL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-replication-in-mysql"&gt;DigitalOcean have a great guide on MySQL replication&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment files &amp;amp; tertiary setup
&lt;/h3&gt;

&lt;p&gt;By this point you should have tested your application on the new infrastructure many times, so it should be obvious whether anything isn't working. However, a few gotchas that can come up when moving between infrastructure to check at this point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure you have all environment variables set up on new infrastructure (&lt;code&gt;.env&lt;/code&gt; file or equivalent).&lt;/li&gt;
&lt;li&gt;Ensure you have a migration process in place for deployments. This differs massively depending on your setup, but make sure when you make the change you aren't deploying code changes to old infrastructure.&lt;/li&gt;
&lt;li&gt;Ensure your scheduler or equivalent is setup and running on your new infrastructure.&lt;/li&gt;
&lt;li&gt;Ensure any queue runners and daemons are setup and running on your new infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Go live
&lt;/h3&gt;

&lt;p&gt;So at this point you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identical code on old and new infrastructure&lt;/li&gt;
&lt;li&gt;User uploaded files on a third party like S3&lt;/li&gt;
&lt;li&gt;Database is now on new infrastructure&lt;/li&gt;
&lt;li&gt;Code is still being run on old infrastructure&lt;/li&gt;
&lt;li&gt;DNS is prepared with low TTL and CNAME on &lt;code&gt;www.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Tested new infrastructure thoroughly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All that is left to do is to change your DNS record on the root domain to point to the new infrastructure. You should start to see traffic within a minute or two, and within 24 hours (remember, not all DNS providers follow your TTL) all traffic should be hitting the new infrastructure.&lt;/p&gt;

&lt;p&gt;The benefits of this piecemeal approach to the migration is that if you encounter an issue at any point, you can easily roll it back. So after moving DNS, if the new infrastructure catches fire, you can just switch the DNS back and you shouldn't encounter any data loss.&lt;/p&gt;

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

&lt;p&gt;OK so let's go through what we did there from a high level.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensured we're using immutable user-uploaded files. If not, migrate to S3 or similar.&lt;/li&gt;
&lt;li&gt;Prepped DNS.&lt;/li&gt;
&lt;li&gt;Migrated data.&lt;/li&gt;
&lt;li&gt;Began using database on new infrastructure, with a failover back to old infrastructure.&lt;/li&gt;
&lt;li&gt;Switched DNS to new infrastructure.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At any point in this whole process we have a live backup of the previous setup to revert to. For example, if you switch the database to new infrastructure and it fails, you can switch to old without any data loss (especially if you use master/slave), or if you switch DNS and something fails you can easily switch back with no data loss or downtime.&lt;/p&gt;

&lt;p&gt;An exact migration plan will differ depending on your application's specifics though. More complex applications may also have additional requirements that need handling, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Key-value storage for sessions or caching. If you have this then you'll need to understand how you're going to invalidate sessions upon moving infrastructure. You don't want to destroy people's cart sessions as they're about to transact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queue and job processing. Many applications offload tasks to a queue to be processed. There are many solutions for handling this, but if you're handling it all within your own infrastructure then you'll need to ensure this is also moved without any interruption. There are many options here, but most applications support multiple queues, so it should be trivial to pause the queue processing, migrate to new infrastructure, and then process it there.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Webhooks. Webhooks &lt;em&gt;shouldn't&lt;/em&gt; be affected by the migration, because both infrastructure should be able to handle inbound web requests within the same database environment at all times. But if the worst happens and you encounter any issues that result in downtime you will need to have a recovery process in place to handle missed webhooks. Most services will retry failed webhooks after a period of time, and will offer a way to manually fire them at a later point should you need to, just remember to check them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other services. There's no one-size-fits-all migration plan. You know your application, if there's something not considered here then you'll need to ensure it's handled properly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hopefully this is of use to you. If you have any questions or suggestions, feel free to leave a comment.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>migration</category>
      <category>devops</category>
      <category>dns</category>
    </item>
    <item>
      <title>The double not operator (!!)</title>
      <dc:creator>Accreditly</dc:creator>
      <pubDate>Wed, 21 Jun 2023 16:51:05 +0000</pubDate>
      <link>https://dev.to/accreditly/the-double-not-operator--5a4l</link>
      <guid>https://dev.to/accreditly/the-double-not-operator--5a4l</guid>
      <description>&lt;p&gt;In the realm of programming, operators are tools that allow us to perform operations on variables and values. One such operator that often catches developers off-guard is the double not operator (&lt;code&gt;!!&lt;/code&gt;). This article delves into what the double not operator is, when and why to use it, and when to avoid it. We'll also explore examples in both PHP and JavaScript, two languages where this operator can be handy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Double Not Operator?
&lt;/h2&gt;

&lt;p&gt;In both PHP and JavaScript (and many other languages), the &lt;code&gt;!&lt;/code&gt; symbol is a logical &lt;code&gt;NOT&lt;/code&gt; operator. It negates the truthiness of the operand that follows it. If the value is truthy (i.e., evaluates to true in a boolean context), &lt;code&gt;!&lt;/code&gt; turns it to false and vice versa.&lt;/p&gt;

&lt;p&gt;We've covered what it is in PHP extensively in our article &lt;a href="https://accreditly.io/articles/the-double-not-operator-explained-in-php"&gt;The double not (!!) operator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The double not operator (&lt;code&gt;!!&lt;/code&gt;) is simply the &lt;code&gt;!&lt;/code&gt; operator used twice. The first &lt;code&gt;!&lt;/code&gt; converts the operand to its boolean opposite, and the second &lt;code&gt;!&lt;/code&gt; flips it back. The result is a value that is explicitly either true or false.&lt;/p&gt;

&lt;p&gt;Let's look at an example in JavaScript:&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;let&lt;/span&gt; &lt;span class="nx"&gt;truthyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, world!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;truthyValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Outputs: true&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;falsyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;falsyValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Outputs: false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the same in PHP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$truthyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hello, world!'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nv"&gt;$truthyValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Outputs: bool(true)&lt;/span&gt;

&lt;span class="nv"&gt;$falsyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nv"&gt;$falsyValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Outputs: bool(false)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why and When to Use the Double Not Operator
&lt;/h2&gt;

&lt;p&gt;The double not operator is a quick and concise way to convert any value to its boolean equivalent. It's particularly useful in conditions where you need to ensure a variable's truthy or falsy nature and not its actual value.&lt;/p&gt;

&lt;p&gt;In JavaScript, it can be beneficial due to the language's loose typing and because various values can be considered "falsy" (e.g., &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;, empty string, etc.). Using &lt;code&gt;!!&lt;/code&gt; can help normalize these values to a proper boolean.&lt;/p&gt;

&lt;p&gt;Here's an example where &lt;code&gt;!!&lt;/code&gt; can be used effectively in JavaScript:&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;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// isAdmin property is missing&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User is an admin&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User is not an admin&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;p&gt;In this case, because &lt;code&gt;isAdmin&lt;/code&gt; is missing, &lt;code&gt;!!user.isAdmin&lt;/code&gt; will return &lt;code&gt;false&lt;/code&gt;, and 'User is not an admin' will be printed.&lt;/p&gt;

&lt;p&gt;In PHP, the &lt;code&gt;!!&lt;/code&gt; operator can also be useful in conditional checks, especially when dealing with values that could be considered "falsy" like &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;, empty string, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$isAdmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nv"&gt;$isAdmin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'User is an admin'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'User is not an admin'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When to Avoid the Double Not Operator
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;!!&lt;/code&gt; can be handy, it can also make code more difficult to read, especially for those unfamiliar with this operator. It's not as explicit as using methods like &lt;code&gt;Boolean()&lt;/code&gt; in JavaScript or &lt;code&gt;(bool)&lt;/code&gt; casting in PHP, which achieve the same result.&lt;/p&gt;

&lt;p&gt;Here are equivalent examples without &lt;code&gt;!!&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;JavaScript:&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;let&lt;/span&gt; &lt;span class="nx"&gt;truthyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, world!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;truthyValue&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Outputs: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$truthyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hello, world!'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$truthyValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Outputs: bool(true)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If readability and clarity are a priority, or if you're working with developers who may not be familiar with &lt;code&gt;!!&lt;/code&gt;, it may be best to use these more explicit methods to convert values to their &lt;code&gt;boolean&lt;/code&gt; equivalent.&lt;/p&gt;

&lt;p&gt;The double not operator (&lt;code&gt;!!&lt;/code&gt;) is a quick, if somewhat cryptic, way to convert any value to a boolean in languages like JavaScript and PHP. While it's a clever trick and can come in handy, remember that it may come at the cost of readability. Use your judgment and consider your team's familiarity with such nuances when deciding whether to use it in your code.&lt;/p&gt;

&lt;p&gt;If you're an experienced developer and have come across the double not operator before then you may be interested in both our &lt;a href="https://accreditly.io/certifications/php-fundamentals"&gt;PHP Fundamentals Certification&lt;/a&gt; and &lt;a href="https://accreditly.io/certifications/javascript-fundamentals"&gt;JavaScript Fundamentals Certification&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
