<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Saheed Oladele - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Saheed Oladele - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 22 May 2026 17:39:19 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/suretrust/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Migrate from create-react-app to Vite using Jest and Browserslist ]]>
                </title>
                <description>
                    <![CDATA[ The React team no longer recommends using create-react-app (CRA) as a bundler to create a new React application. The team and community realized that even though CRA was a jump-starter, it lacked the flexibility needed to configure or manage large an... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-migrate-from-create-react-app-to-vite/</link>
                <guid isPermaLink="false">66bb8f98caaeb78feb348947</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vite ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Saheed Oladele ]]>
                </dc:creator>
                <pubDate>Fri, 06 Oct 2023 18:01:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/pexels-tima-miroshnichenko-5380664.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The React team no longer recommends using <a target="_blank" href="https://github.com/facebook/create-react-app">create-react-app (CRA)</a> as a bundler to create a new React application. The team and community realized that even though CRA was a jump-starter, it lacked the flexibility needed to configure or manage large and complex applications.</p>
<p>Nowadays, the team recommends using <a target="_blank" href="https://react.dev/learn/start-a-new-react-project#production-grade-react-frameworks">production-grade React frameworks</a> like <a target="_blank" href="https://nextjs.org/">NextJS</a>, <a target="_blank" href="https://www.freecodecamp.org/news/p/b2e8aa42-17f7-486f-9fab-b47f9704248b/Remix">Remix</a>, <a target="_blank" href="https://www.gatsbyjs.com/">Gatsby</a>, or <a target="_blank" href="https://expo.dev/">Expo</a> for native apps. While frameworks are the preferred choice, the React team also recommend using <a target="_blank" href="https://vitejs.dev/">Vite</a> or <a target="_blank" href="https://parceljs.org/">Parcel</a> for custom build processes.</p>
<p>This is partly because the <a target="_blank" href="https://www.npmjs.com/package/create-react-app">CRA package has not been updated</a> for about a year. This may cause some problems where packages already updated to more recent versions cannot be used within an existing application. As a result, you may need to update existing applications by replacing the CRA package with the recommended alternatives — Vite or Parcel.</p>
<p>This article walks you through the steps for migrating a production-based application from CRA to Vite. You will learn the "why" of each step, how to retain <code>Jest</code> for tests, and how to update your <code>browserslist</code> since it doesn't work with <code>vite</code> out of the box.</p>
<p>In the conclusion section, you can find a sample pull request that includes all the changes. At the end of each step, you will find a sample commit text which shows the code change required per step.</p>
<h2 id="heading-step-1-install-vite-and-plugins">Step 1: Install <code>Vite</code> and Plugins</h2>
<p>Here are the commands to install the packages we need:</p>
<pre><code class="lang-bash">yarn add vite @vitejs/plugin-react vite-tsconfig-paths

OR

npm install vite @vitejs/plugin-react vite-tsconfig-paths
</code></pre>
<p>Apart from Vite, we are adding two plugins — <code>@vitejs/plugin-react</code> and  <code>vite-tsconfig-paths</code>.</p>
<p>The <code>vitejs/plugin-react</code> <a target="_blank" href="https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md#vitejsplugin-react-">plugin</a> enables fast refresh in development, uses automatic JSX runtime, and custom Babel plugins or presets. It enriches your React development experience.</p>
<p>The <code>vite-tsconfig-paths</code> <a target="_blank" href="https://github.com/aleclarson/vite-tsconfig-paths">plugin</a> resolves imports for TypeScript's path mapping. For example, you can use <code>components/ComponentName</code> instead of <code>./../components/ComponentName</code>.</p>
<h3 id="heading-other-vite-plugins">Other Vite plugins</h3>
<p>Another plugin you could consider is <code>vite-plugin-svgr</code>, which <a target="_blank" href="https://github.com/pd4d10/vite-plugin-svgr">transforms</a> SVG into React components and uses <a target="_blank" href="https://github.com/gregberge/svgr">svgr</a> under the hood. I left it out since we do not have such a use case in the application I’m migrating.</p>
<p>You can also checkout other official Vite plugins <a target="_blank" href="https://vitejs.dev/plugins/">here</a>.</p>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/2b37990690f7898117b1a0cb89e1118451bd24d9">Step 1 sample commit</a>.</p>
<h2 id="heading-step-2-create-a-vite-config-file">Step 2: Create a <code>Vite</code> config file</h2>
<p>On running <code>vite</code> in the command terminal, Vite tries to find a <code>vite.config.ts</code> file inside the project's root directory. You can read more on <a target="_blank" href="https://vitejs.dev/config/">Vite's page</a> for how to further configure this file for i<a target="_blank" href="https://vitejs.dev/config/#config-intellisense">ntellisense</a>, <a target="_blank" href="https://vitejs.dev/config/#conditional-config">environment based configurations</a>, <a target="_blank" href="https://vitejs.dev/config/#async-config">async configuration</a>, and <a target="_blank" href="https://vitejs.dev/config/#using-environment-variables-in-config">env variables usage</a>.</p>
<p>At your application’s root, create a file named <code>vite.config.ts</code> with the following content:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>
<span class="hljs-keyword">import</span> react <span class="hljs-keyword">from</span> <span class="hljs-string">'@vitejs/plugin-react'</span>
<span class="hljs-keyword">import</span> viteTsconfigPaths <span class="hljs-keyword">from</span> <span class="hljs-string">'vite-tsconfig-paths'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
    <span class="hljs-comment">// depending on your application, base can also be "/"</span>
    <span class="hljs-attr">base</span>: <span class="hljs-string">''</span>,
    <span class="hljs-attr">plugins</span>: [react(), viteTsconfigPaths()],
    <span class="hljs-attr">server</span>: {    
        <span class="hljs-comment">// this ensures that the browser opens upon server start</span>
        <span class="hljs-attr">open</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-comment">// this sets a default port to 3000  </span>
        <span class="hljs-attr">port</span>: <span class="hljs-number">3000</span>, 
    },
})
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/557e8fbda9f8a19bf58ae0eeb1aa81e14111729a">Step 2 sample commit</a>.</p>
<h2 id="heading-step-3-create-a-vite-types-file-reference">Step 3: Create a <code>Vite</code> Types File Reference</h2>
<p>This step is needed to reference a type declarations file which aids type checks and Intellisense. By default, Vite types are for a NodeJS environment. For client side code, <a target="_blank" href="https://vitejs.dev/guide/env-and-mode.html#intellisense-for-typescript">Vite provides the type definitions</a> in <a target="_blank" href="https://github.com/vitejs/vite/blob/main/packages/vite/client.d.ts"><code>vite/client.d.ts</code></a>.</p>
<p>At your application’s root, create a file named <code>vite-env.d.ts</code> with the following content:</p>
<pre><code class="lang-js"><span class="hljs-comment">/// &lt;reference types="vite/client" /&gt;</span>
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/3002d2dbe1a421c0f31f57658ddde3030e898d1a">Step 3 sample commit</a>.</p>
<h2 id="heading-step-4-move-the-indexhtml-file">Step 4: Move the <code>index.html</code> File</h2>
<p>Vite has a <a target="_blank" href="https://vitejs.dev/guide/#index-html-and-project-root">root directory</a> which your files are served from. Since <code>index.html</code> is the entry point for Vite's server, the file needs to be in the root directory.</p>
<p>From the public directory, move the <code>index.html</code> file to the root of your project.</p>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/940f1f743fe6a380b157b86256aef7e29b2457a1">Step 4 sample commit</a>.</p>
<h2 id="heading-step-5-update-the-indexhtml-file">Step 5: Update the <code>index.html</code> File</h2>
<p>Two updates are necessary here:</p>
<h3 id="heading-remove-publicurl">Remove <code>%PUBLIC_URL%</code></h3>
<p>Vite <a target="_blank" href="https://vitejs.dev/guide/#index-html-and-project-root">automatically resolves</a> URLs inside <code>index.html</code>, so there's no need for <code>%PUBLIC_URL%</code> placeholders. You can do a search and replace inside your <code>index.html</code> file for this. Be sure to remove all occurrences.</p>
<p>Before:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"%PUBLIC_URL%/favicon.svg"</span> /&gt;</span>
</code></pre>
<p>After:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
</code></pre>
<h3 id="heading-add-module-script-to-the-bottom-of-the-body-tag">Add module script to the bottom of the body tag</h3>
<p>Vite treats <code>index.html</code> <a target="_blank" href="https://vitejs.dev/guide/#index-html-and-project-root">as source code and part of the module graph</a>. It resolves <code>&lt;script type="module" src="..."&gt;</code> that references your JavaScript source code.</p>
<p>At the bottom of the body tag in <code>index.html</code> file, add the script as shown below:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    {/* others here */}
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/src/index.tsx"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/406b9765c5c166a0bafff6332f8a908156b794c4">Step 5 sample commit</a>.</p>
<h2 id="heading-step-6-replace-cra-with-vite">Step 6: Replace CRA with <code>Vite</code></h2>
<p>You can now remove CRA, add <code>Vite</code> scripts to the <code>package.json</code> file, and update <code>tsconfig.json</code>.</p>
<h3 id="heading-remove-cra">Remove CRA</h3>
<p>To remove CRA, run the following command. This will remove <code>react-scripts</code> from our installed packages.</p>
<pre><code class="lang-bash">yarn remove react-scripts

OR

npm uninstall react-scripts
</code></pre>
<p>After running the command above, delete the <code>react-app-env.d.ts</code> file.</p>
<h3 id="heading-add-vite-scripts-to-the-packagejson-file">Add Vite scripts to the <code>package.json</code> file</h3>
<p>With Vite installed, you can use the <code>vite</code> binary in your scripts. This could mean replacing <code>react-scripts</code> in a few places. Your focus should be on the <code>start</code> and <code>build</code> keys. The <code>preview</code> key is an addition which helps to preview production build locally.</p>
<p>Note that <code>start</code> is <code>vite</code> and not <code>vite start</code>.</p>
<pre><code class="lang-javascript">{  
  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"start"</span>: <span class="hljs-string">"vite"</span>, <span class="hljs-comment">// start dev server</span>
    <span class="hljs-string">"build"</span>: <span class="hljs-string">"tsc &amp;&amp; vite build"</span>, <span class="hljs-comment">// build for production</span>
    <span class="hljs-string">"preview"</span>: <span class="hljs-string">"vite preview"</span> <span class="hljs-comment">// locally preview production build</span>
  }
},
</code></pre>
<h3 id="heading-update-tsconfigjson">Update <code>tsconfig.json</code></h3>
<p>Here, your focus should be on the <code>isolatedModules</code>, <code>lib</code>, <code>target</code>, and <code>types</code>. For more options, here is a <a target="_blank" href="https://github.com/vitejs/create-vite-app/blob/master/template-react-ts/tsconfig.json">sample tsconfig file from Vite</a>.</p>
<pre><code class="lang-javascript">{  
    <span class="hljs-string">"compilerOptions"</span>: {    
        <span class="hljs-string">"lib"</span>: [<span class="hljs-string">"dom"</span>, <span class="hljs-string">"dom.iterable"</span>, <span class="hljs-string">"esnext"</span>],    
        <span class="hljs-string">"target"</span>: <span class="hljs-string">"ESNext"</span>,    
        <span class="hljs-string">"types"</span>: [<span class="hljs-string">"vite/client"</span>],
        <span class="hljs-string">"isolatedModules"</span>: <span class="hljs-literal">true</span>,
    },
 }
</code></pre>
<h3 id="heading-update-processenvreactappvariable-optional">Update <code>process.env.REACT_APP_VARIABLE</code> (optional)</h3>
<p>This is necessary if your application uses environment variable. Vite uses <code>import.meta.env.REACT_APP_VARIABLE</code> instead of <code>process.env.REACT_APP_VARIABLE</code>. You can find more details on <a target="_blank" href="https://vitejs.dev/guide/env-and-mode.html">Vite's env variables and modes here</a>.</p>
<p>Before:</p>
<pre><code class="lang-javascript">process.env.REACT_APP_VARIABLE
</code></pre>
<p>After:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span>.meta.env.REACT_APP_VARIABLE
</code></pre>
<h3 id="heading-replace-react-with-vite-optional">Replace <code>REACT_</code> with <code>VITE_</code> (optional)</h3>
<p>You only need this if you updated <code>process.env</code> above. Replace your <code>REACT_</code> environment variables to start with <code>VITE_</code>. This is needed because Vite filters out any env variable not starting with <code>VITE_</code>.</p>
<p>Before:</p>
<pre><code class="lang-javascript">REACT_APP_API_BASE
</code></pre>
<p>After:</p>
<pre><code class="lang-javascript">VITE_APP_API_BASE
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/775b3e841f107c2116e46d2a94b3ca9e697561e9">Step 6 sample commit</a>.</p>
<h2 id="heading-step-7-run-your-application">Step 7: Run your Application</h2>
<pre><code class="lang-bash">yarn start

OR

npm start
</code></pre>
<p>Congratulations! You have successfully completed the first step in migrating your application from CRA to Vite. You should see a screen that looks like the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Screenshot-2023-10-05-at-17.21.43-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>No sample commit. ;)</p>
<h2 id="heading-possible-blockers-and-their-solutions">Possible blockers and their solutions</h2>
<h3 id="heading-global-is-not-defined-error"><code>global</code> is not defined error</h3>
<p>If you have this error, define global inside your <code>vite.config.ts</code> file as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>;
<span class="hljs-keyword">import</span> react <span class="hljs-keyword">from</span> <span class="hljs-string">'@vitejs/plugin-react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-comment">// ...</span>
  <span class="hljs-attr">define</span>: {
    <span class="hljs-comment">// here is the main update</span>
    <span class="hljs-attr">global</span>: <span class="hljs-string">'globalThis'</span>,
  },
});
</code></pre>
<h3 id="heading-if-you-use-emotionreact-or-emotioncss">If you use <code>@emotion/react</code> or <code>@emotion/css</code></h3>
<p>You need to inform Vite about this. To do this, install <code>@emotion/babel-plugin</code>.</p>
<pre><code class="lang-shell">yarn add @emotion/babel-plugin

OR

npm install @emotion/babel-plugin
</code></pre>
<p>Then update your Vite's <code>react</code> plugin in the <code>vite.config.ts</code> as shown below:</p>
<pre><code class="lang-javscript">import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsconfigPaths from 'vite-tsconfig-paths';
import svgr from 'vite-plugin-svgr';

export default defineConfig({
  // ...
  plugins: [
    // here is the main update
    react({
      jsxImportSource: '@emotion/react',
      babel: {
        plugins: ['@emotion/babel-plugin'],
      },
    }),
  ],
  // ...
});
</code></pre>
<h3 id="heading-oh-no-my-unit-tests-are-not-working">Oh no, my unit tests are not working!</h3>
<p>At this point, try running your unit tests — <code>yarn test</code> or <code>npm run test</code>. It’s possible that they don’t work. The following steps highlight how you can fix your unit tests.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Screenshot-2023-10-06-at-16.20.33.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Your unit tests are not working because CRA uses <code>react-scripts test</code> to run tests, so we want to switch to using <code>jest</code>.</p>
<h2 id="heading-step-8-install-jest-and-typescript-related-dependencies">Step 8: Install Jest and TypeScript-related Dependencies</h2>
<p>To start with, you need to install <code>jest</code>, <code>ts-jest</code>, and <code>jest-environment-jsdom</code>. <code>jest</code> will be our new binary for running the tests, <code>[ts-jest](https://www.npmjs.com/package/ts-jest)</code> is a transformer with source map support which allows you to run tests in TypeScript projects, and <code>jest-environment-jsdom</code> imitates the browser's behavior during test runs.</p>
<pre><code class="lang-shell">yarn add -D jest @types/jest ts-jest jest-environment-jsdom

OR

npm install --save-dev jest @types/jest ts-jest jest-environment-jsdom
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/66283764d616c4572ecd53d51ac1711f30fbe8e0">Step 8 sample commit</a>.</p>
<h2 id="heading-step-9-update-jest-config">Step 9: Update Jest Config</h2>
<p>This depends on your current Jest configuration. If it is configured inside <code>package.json</code>, you can update as follows. Here, you focus on <code>preset</code>, <code>testEnvironment</code>, <code>moduleNameMapper</code>, and <code>modulePaths</code>.</p>
<p><code>preset</code> is set to <code>ts-jest/presets/js-with-ts</code> to allow TypeScript with JavaScript. You can also just set it to <code>ts-jest</code> depending on your application.</p>
<p><code>moduleNameMapper</code> configures Jest to gracefully handle assets such as stylesheets and images.</p>
<pre><code class="lang-json">  <span class="hljs-string">"jest"</span>: {
    <span class="hljs-attr">"preset"</span>: <span class="hljs-string">"ts-jest/presets/js-with-ts"</span>,
    <span class="hljs-attr">"testEnvironment"</span>: <span class="hljs-string">"jest-environment-jsdom"</span>,
    <span class="hljs-attr">"moduleNameMapper"</span>: {
      <span class="hljs-attr">"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$"</span>: <span class="hljs-string">"&lt;rootDir&gt;/__mocks__/fileMock.js"</span>,
      <span class="hljs-attr">"\\.(css|less)$"</span>: <span class="hljs-string">"&lt;rootDir&gt;/__mocks__/styleMock.js"</span>
    },
    <span class="hljs-attr">"modulePaths"</span>: [
      <span class="hljs-comment">// you can update this to match your application setup</span>
      <span class="hljs-string">"&lt;rootDir&gt;/src"</span>
    ],
  },
</code></pre>
<p>Since we referenced a file in <code>moduleNameMapper</code> above, we need to create the file and it's corresponding files. Step 10 takes care of this. This setup is explained further in <a target="_blank" href="https://jestjs.io/docs/webpack#handling-static-assets">Jest's documentation here</a>.</p>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/4383f05fce07ac1de3c80d04f581e40218f8c83b">Step 9 sample commit</a>.</p>
<h2 id="heading-step-10-add-the-mocks-directory-to-the-root-of-your-project">Step 10: Add the <code>__mocks__</code> Directory to the Root of Your Project</h2>
<p>At the root of your project, create a folder named <code>__mocks__</code>.</p>
<p>Inside the created <code>__mocks__</code> folder, add a file named <code>styleMock.js</code> and add the following content:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {}
</code></pre>
<p>Inside the created <code>__mocks__</code> folder, add a file named <code>fileMock.js</code> and add the following content.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = <span class="hljs-string">'test-file-stub'</span>
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/d6da2a8984176041fcbfe08ca2bf0e9339fb25b4">Step 10 sample commit</a>.</p>
<h2 id="heading-step-11-update-the-packagejson-scripts">Step 11: Update the <code>package.json</code> Scripts</h2>
<p>Now that we have <code>jest</code> properly installed, we can replace <code>react-scripts tests</code> with <code>jest</code>. Changes should be as shown below. If you do not have the <code>test:coverage</code> or <code>test:debug</code> keys in your code before, feel free to ignore.</p>
<p>Before:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"react-scripts test"</span>,
    <span class="hljs-attr">"test:coverage"</span>: <span class="hljs-string">"react-scripts test --coverage ."</span>,
    <span class="hljs-attr">"test:debug"</span>: <span class="hljs-string">"react-scripts test --inspect-brk --runInBand --no-cache"</span>
}
</code></pre>
<p>After:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"jest"</span>,
    <span class="hljs-comment">// you can add this to keep watch mode on</span>
    <span class="hljs-attr">"test:watch"</span>: <span class="hljs-string">"jest --watch"</span>,
    <span class="hljs-attr">"test:coverage"</span>: <span class="hljs-string">"jest --coverage ."</span>,
    <span class="hljs-attr">"test:debug"</span>: <span class="hljs-string">"jest --inspect-brk --runInBand --no-cache"</span>
}
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/e27a66593954ffcb36d77c3e86076444a0cf82e5">Step 11 sample commit</a>.</p>
<h2 id="heading-step-12-run-your-tests">Step 12: Run your Tests</h2>
<pre><code class="lang-shell">yarn test

OR

npm test
</code></pre>
<p>If you face a problem related to <code>import.meta</code>, you can resolve this by moving all your environment keys to a single file and mocking this file in your test. You can take a <a target="_blank" href="https://github.com/suretrust/stock-ticker/commit/07d15d1f000ec2cef7ec6dd01fccb43af3e67d30">look at this commit</a> to have a better understanding of what I mean.</p>
<p>No sample commit. :)</p>
<p>Ah, it works! But how about the browserslist config?</p>
<h2 id="heading-what-is-browserslist-config">What is browserslist config?</h2>
<p>This is a configuration used to share your target or supported browsers among multiple frontend repositories. </p>
<p>There are various standards depending on the industry. For example, in EdTech, it's possible that all users learning online use similar browsers in terms of brand, version, and screen size. This list of the commonly used browsers can easily become a standard for the EdTech industry.</p>
<p>A sample application of the browserslist config is when you need to be compatible with older browsers. Passing this range to the browserslist config helps your bundler to compile your code using polyfills that are compatible with your target browsers. This way, your page has optimized performance with good user experience.</p>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Polyfill">Mozilla defines a Polyfill</a> as a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it.</p>
<p>Browserslist config is often set in the <code>package.json</code> or <code>.browserslistrc</code> file as shown below.</p>
<h3 id="heading-packagejson"><code>package.json</code></h3>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"browserslist"</span>: [
    <span class="hljs-string">"iOS &gt;= 9"</span>,
    <span class="hljs-string">"Android &gt;= 4.4"</span>,
    <span class="hljs-string">"last 2 versions"</span>,
    <span class="hljs-string">"&gt; 0.2%"</span>,
    <span class="hljs-string">"not dead"</span>
  ]
}
</code></pre>
<h3 id="heading-browserslistrc"><code>.browserslistrc</code></h3>
<pre><code class="lang-javascript">iOS &gt;= <span class="hljs-number">9</span>
Android &gt;= <span class="hljs-number">4.4</span>
last <span class="hljs-number">2</span> versions
&gt; <span class="hljs-number">0.2</span>%
not dead
</code></pre>
<p>You can also <a target="_blank" href="https://modernjs.dev/builder/en/guide/advanced/browserslist">read more about Browserslist here</a>.</p>
<h2 id="heading-why-is-browserslist-a-problem-with-vite">Why is <code>browserslist</code> a Problem with Vite?</h2>
<p>Vite uses ESBuild under the hood which expects a different format to the usual <code>browserslist</code> format.</p>
<p>ESBuild expected format: <code>['es2015', 'safari11', 'ios11']</code></p>
<p>Browserslist format: <code>['defaults', 'Safari &gt;= 11', 'ios_saf &gt;= 11']</code></p>
<p>As a result of this discrepancy, Vite ignores your <code>browserslist</code> configuration which is currently in the <code>package.json</code> or <code>.brwserslistrc</code> file. </p>
<p>To fix this, you can use a package called <a target="_blank" href="https://github.com/marcofugaro/browserslist-to-esbuild"><code>browserslist-to-esbuild</code></a> which does this conversion under the hood and pass the config to <code>build.target</code> inside the <code>vite.config.ts</code> file. Steps 13 and 14 take care of this.</p>
<h2 id="heading-step-13-install-browserslist-to-esbuild">Step 13: Install <code>browserslist-to-esbuild</code></h2>
<pre><code class="lang-shell">yarn add browserslist-to-esbuild

OR 

npm install browserslist-to-esbuild
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/fc7239af0a0da0b4bd844f8d17b3860b794f0ea5">Step 13 sample commit</a>.</p>
<h2 id="heading-step-14-confiure-the-browserslist-in-vite-config">Step 14: Confiure the <code>browserslist</code> in Vite Config</h2>
<p>In the <code>vite.config.ts</code> file, update as shown below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>
<span class="hljs-keyword">import</span> browserslistToEsbuild <span class="hljs-keyword">from</span> <span class="hljs-string">'browserslist-to-esbuild'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  ..
  build: {
    <span class="hljs-comment">// --&gt; ["chrome79", "edge92", "firefox91", "safari13.1"]</span>
    <span class="hljs-attr">target</span>: browserslistToEsbuild(), 
  },
  ..
})
</code></pre>
<p>And then, you can pass your configs as shown below,</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  ..
  build: {
    <span class="hljs-comment">// you can also pass your usual browserslist config here</span>
    <span class="hljs-attr">target</span>: browserslistToEsbuild([
        <span class="hljs-string">'&gt;0.2%'</span>,
        <span class="hljs-string">'not dead'</span>,
        <span class="hljs-string">'not op_mini all'</span>
    ]),
  },
  ..
})
</code></pre>
<p><a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1/commits/b8758cd4ac9e0e1d79e361b1b0097714bc6a85ae">Step 14 sample commit</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Voilà! You're done and your application is fully migrated.</p>
<p>Missing any step? Here is a <a target="_blank" href="https://github.com/suretrust/stock-ticker/pull/1">sample pull request that highlights all the changes</a> involved.</p>
<p>You have learned the "why" and "how" of replacing <code>create-react-app</code> with <code>Vite</code>. I hope you are as proud of yourself as I was of myself for what I have learned in the process of the migration.</p>
<p>Alrighty, that it! Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Rails: How to set unique interchangeable index constraint ]]>
                </title>
                <description>
                    <![CDATA[ Setting uniqueness validation in rails is something you’ll end up doing quite often. Perhaps, you even already added them to most of your apps. However, this validation only gives a good user interface and experience. It informs the user of the error... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-set-unique-interchangeable-index-constraint-in-rails/</link>
                <guid isPermaLink="false">66bb8f9ad2bda3e4315491c6</guid>
                
                    <category>
                        <![CDATA[ database ]]>
                    </category>
                
                    <category>
                        <![CDATA[ postgres ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ruby on Rails ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Saheed Oladele ]]>
                </dc:creator>
                <pubDate>Mon, 15 Jul 2019 10:50:49 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca178740569d1a4ca4ec3.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Setting uniqueness validation in rails is something you’ll end up doing quite often. Perhaps, you even already added them to most of your apps. However, this validation only gives a good user interface and experience. It informs the user of the errors preventing the data from being persisted in the database.</p>
<h3 id="heading-why-uniqueness-validation-is-not-enough">Why uniqueness validation is not enough</h3>
<p>Even with the uniqueness validation, unwanted data sometimes gets saved in the database. For clarity, let’s take a look at a user model shown below:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>
    validates <span class="hljs-symbol">:username</span>, <span class="hljs-symbol">presence:</span> <span class="hljs-literal">true</span>, <span class="hljs-symbol">uniqueness:</span> <span class="hljs-literal">true</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>To validate the username column, rails queries the database using SELECT to see if the username already exists. If it does, it prints “Username already exists”. If it doesn’t, it runs an INSERT query to persist the new username in the database.  </p>
<p><img src="https://lh5.googleusercontent.com/BXp1jq7tCUcP9meYKOz4G8fL_2hcEKK5roipT6sH7wugLhIizTFov8q37QTDTF0mNJtgI0QQm8vbrXaKq9JIQVq1hzcnBYYDr_Fy2KO6mEAR4fBfJy9uWoJ3VUu_JNxUYa0_ELfm" alt="Image" width="1258" height="686" loading="lazy"></p>
<p>When two users are running the same process at the same time, the database can sometimes save the data regardless of the validation constraint and that is where the database constraints (unique index) comes in.</p>
<p>If user A and user B are both trying to persist the same username into the database at the same time, rails runs the SELECT query, if the username already exists, it informs both users. However, if the username doesn’t exist in the database, it runs the INSERT query for both users simultaneously as shown in the image below.</p>
<p><img src="https://lh3.googleusercontent.com/8-B6arsNFfdkLSkZbYt3F2KPPaFEbjAolPeDU9j3jMw3twF7r44uCum8dGNPGCduaLcX1E4n5QUTF4YUzPrPMI_QHyajoma8ULLyWo1aSYM5CJgu-1NEc3PDIuSpUFQvISE4Pu4y" alt="Image" width="1258" height="686" loading="lazy"></p>
<p>Now that you know why the database unique index (database constraint) is important, let’s get into how to set it. It’s quite easy to set database unique index(es) for any column or set of columns in rails. However, some database constraint in rails can be tricky.</p>
<h3 id="heading-a-quick-look-at-setting-a-unique-index-for-one-or-more-column">A quick look at setting a unique index for one or more column</h3>
<p>This is quite as simple as running a migration. Let’s assume we have a users table with column username and we want to ensure that each user has a unique username. You simply create a migration and input the following code:</p>
<pre><code class="lang-ruby">add_index <span class="hljs-symbol">:users</span>, <span class="hljs-symbol">:username</span>, <span class="hljs-symbol">unique:</span> <span class="hljs-literal">true</span>
</code></pre>
<p>Then you run the migration and that’s it. The database now ensures that no similar usernames are saved in the table.</p>
<p>For multiple associated columns, let’s assume we have a requests table with columns sender_id and receiver_id. Similarly, you simply create a migration and input the following code:</p>
<pre><code class="lang-ruby">add_index <span class="hljs-symbol">:requests</span>, [<span class="hljs-symbol">:sender_id</span>, <span class="hljs-symbol">:receiver_id</span>], <span class="hljs-symbol">unique:</span> <span class="hljs-literal">true</span>
</code></pre>
<p>And that’s it? <em>Uh oh, not so fast.</em></p>
<h3 id="heading-the-problem-with-the-multiple-column-migration-above">The problem with the multiple column migration above</h3>
<p>The problem is that the ids, in this case, are interchangeable. This means that if you have a sender_id of 1 and receiver_id of 2, the request table can still save a sender_id of 2 and receiver_id of 1, even though they already have a pending request.</p>
<p>This problem often happens in a self-referential association. This means both the sender and receiver are users and sender_id or receiver_id is referenced from the user_id. A user with user_id(sender_id) of 1 sends a request to a user with user_id(receiver_id) of 2.</p>
<p>If the receiver sends another request again, and we allow it to save in the database, then we have two similar requests from the same two users(sender and receiver || receiver and sender) in the request table.</p>
<p>This is illustrated in the image below:</p>
<p><img src="https://lh3.googleusercontent.com/9VNqmd8nuvhxKqJ3nVoZKS5ke1y5K-m6wQ7N5r8NPLSFYUnv3yeoMH2afGj89sGtsEhk3zsJbI30pB2WsgOOF1Xiijtqmv3mqbi1PxDzkIoQM0sfXGLZjcSTRrrIUTamG9RqGzEM" alt="Image" width="1258" height="686" loading="lazy"></p>
<h3 id="heading-the-common-fix">The common fix</h3>
<p>This problem is often fixed with the pseudo-code below:</p>
<pre><code class="lang-ruby"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">force_record_conflict</span></span>
    <span class="hljs-comment"># 1. Return if there is an already existing request from the sender to receiver </span>
    <span class="hljs-comment"># 2. If not then swap the sender and receiver</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>The problem with this solution is that the receiver_id and sender_id get swapped each time before saving to the database. Hence, the receiver_id column will have to save the sender_id and vice versa.</p>
<p>For example, if a user with sender_id of 1 sends a request to a user with receiver_id of 2, the request table will be as shown below:</p>
<p><img src="https://lh3.googleusercontent.com/FhGRXh1uZOdxMsL1CvfKsM82kazpp_smHl7LkxNHpoxCxX6sChTbve5lQAotyW0WsqEITf7Ddc3C2XYG2-wwppSW4glymJqgPu4JmbiU1uxXR52c7EvWft73UHGf5-1gfmNW4ziC" alt="Image" width="1258" height="686" loading="lazy"></p>
<p>This may not sound like an issue but it’s better if your columns are saving the exact data you want them to save. This has numerous advantages. For example, if you need to send a notification to the receiver through the receiver_id, then you’ll query the database for the exact id from the receiver_id column. This already became more confusing the moment you start switching the data saved in your request table.</p>
<h3 id="heading-the-proper-fix">The proper fix</h3>
<p>This problem can be entirely resolved by talking to the database directly. In this case, I’ll explain using PostgreSQL. When running the migration, you must ensure that the unique constraint checks for both (1,2) and (2,1) in the request table before saving.</p>
<p>You can do that by running a migration with the code below:</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AddInterchangableUniqueIndexToRequests</span> &lt; ActiveRecord::Migration[5.2]</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">change</span></span>
        reversible <span class="hljs-keyword">do</span> <span class="hljs-params">|dir|</span>
            dir.up <span class="hljs-keyword">do</span>
                connection.execute(<span class="hljs-string">%q(
                    create unique index index_requests_on_interchangable_sender_id_and_receiver_id on requests(greatest(sender_id,receiver_id)</span>, least(sender_id,receiver_id));
                    create unique index index_requests_on_interchangable_receiver_id_and_sender_id on requests(least(sender_id,receiver_id), greatest(sender_id,receiver_id));
                ))
            <span class="hljs-keyword">end</span>

            dir.down <span class="hljs-keyword">do</span>
                connection.execute(<span class="hljs-string">%q(
                    drop index index_requests_on_interchangable_sender_id_and_receiver_id;
                    drop index index_requests_on_interchangable_receiver_id_and_sender_id;
                )</span>)
            <span class="hljs-keyword">end</span>    
        <span class="hljs-keyword">end</span>
    <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<h3 id="heading-code-explanation">Code explanation</h3>
<p>After creating the migration file, the reversible is to ensure that we can revert our database whenever we must. The <code>dir.up</code> is the code to run when we migrate our database and <code>dir.down</code> will run when we migrate down or revert our database.</p>
<p><code>connection.execute(%q(...))</code> is to tell rails that our code is PostgreSQL. This helps rails to run our code as PostgreSQL.</p>
<p>Since our “ids” are integers, before saving into the database, we check if the greatest and least (2 and 1) are already in the database using the code below:</p>
<pre><code class="lang-ruby">requests(greatest(sender_id,receiver_id), least(sender_id,receiver_id))
</code></pre>
<p>Then we also check if the least and greatest (1 and 2) are in the database using:</p>
<pre><code class="lang-ruby">requests(least(sender_id,receiver_id), greatest(sender_id,receiver_id))
</code></pre>
<p>The request table will then be exactly how we intend as shown in the image below:</p>
<p><img src="https://lh5.googleusercontent.com/LHiuQRNBeyui8vuXx1hMWZfzVOBBkccmnFUml2A4kehPHg1xcpC35LsRan_8oggdmYH0zvBardwpIXHWDA-hiFTH4Grd7D6tejAATSJZLpS0l1aLig00KD8NUx7yrtTmICD1C0tI" alt="Image" width="1258" height="686" loading="lazy"></p>
<p>And that’s it. Happy coding!</p>
<h3 id="heading-references">References:</h3>
<p><a target="_blank" href="https://edgeguides.rubyonrails.org/active_record_validations.html#uniqueness">Edgeguides</a> | <a target="_blank" href="https://thoughtbot.com/blog/the-perils-of-uniqueness-validations">Thoughtbot</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A simple Git guide and cheat sheet for open source contributors ]]>
                </title>
                <description>
                    <![CDATA[ A go-to git cheat sheet for your open source contributions. If you’re reading this article, you already know that the benefit of open source contribution abounds. You can skip the article and navigate to the end if you’re here for the cheat sheet. Th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-simple-git-guide-and-cheat-sheet-for-open-source-contributors/</link>
                <guid isPermaLink="false">66bb8f95d2bda3e4315491c4</guid>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitLab ]]>
                    </category>
                
                    <category>
                        <![CDATA[ open source ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Saheed Oladele ]]>
                </dc:creator>
                <pubDate>Fri, 12 Jul 2019 17:18:51 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca17a740569d1a4ca4ed1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A go-to git cheat sheet for your open source contributions.</p>
<p>If you’re reading this article, you already know that the benefit of open source contribution abounds. You can skip the article and navigate to the end if you’re here for the cheat sheet.</p>
<p>The common problem faced by aspiring open source contributors is how to take the first step <em>from fork to pull request</em>. After reading this article, you should be well equipped with all you need to make your first open source pull request.</p>
<p>Apart from making the process easier for you, the git workflow defined in this piece also makes your contributions look professional. This is especially useful in case you want to add your open source contributions to your portfolio.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/image-240.png" alt="Image" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@randyfath?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Randy Fath / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<p>This article assumes you already know the steps to take to contribute to open source. If you don’t know, you may want to read <a target="_blank" href="https://rubygarage.org/blog/how-contribute-to-open-source-projects">this article written by Maryna</a>. This piece also assumes that you’ve already setup Git on your PC. If you haven’t, you may want to check the <a target="_blank" href="https://help.github.com/en/articles/set-up-git">setting up Git section of this article</a> and do that first.</p>
<h3 id="heading-step-1-fork-the-project">Step 1: Fork the project</h3>
<p>This is as simple as clicking a button on GitHub. Navigate to the repository of the project you want to contribute to, then click the fork button at the top right corner as illustrated in the picture below.</p>
<p><img src="https://lh4.googleusercontent.com/4u1uvX1dRTkG0RLXeWqt6N7-Ed2BeNiOfG8KgXsiOAE-quBpq2rDKS2d6dkxyEWbMThVJu4bgeqU9aKO-vhxyj5XULbRxpV0WedoctN0wm_RhgSyzg5ICn4aZUkk99BwBj2ugCBv" alt="Image" width="1040" height="631" loading="lazy"></p>
<p>After using the fork button, you’d now have the repository on your GitHub account.</p>
<h3 id="heading-step-2-clone-the-project-to-your-local-machine">Step 2: Clone the project to your local machine</h3>
<p>This is the simplest part of Git. Navigate to your forked repository (the repository is now one of your GitHub repositories). Follow steps 1 and 2 as shown in the image below to copy the clone address. This address should look like this: <code>https:[github.com/suretrust.com/freeCodeCamp.git](http://github.com/suretrust.com/freeCodeCamp.git)</code></p>
<p><img src="https://lh5.googleusercontent.com/lyeLwQ6uz-VcEFoQcEGNf5KQiSzaDz1iwefGwi4CAoxuqiOdUPBm_jxVz1GJMgjHYHYkzGIHKb1l7iPdTQ5OIu3WUzK_ouFHHGAruNe-WJVKBsWpPgyLD5EClWnj7kaxsszwFqHB" alt="Image" width="1040" height="631" loading="lazy"></p>
<p>Then, clone the project by typing <code>git clone &lt;the copied address&gt;</code> into your command terminal as shown below:</p>
<p><code>git clone [https://github.com/suretrust/freeCodeCamp.git](https://github.com/suretrust/freeCodeCamp.git)</code></p>
<h3 id="heading-step-3-create-upstream">Step 3: Create upstream</h3>
<p>The upstream is necessary to keep track of the difference between the forked repository that is on your Git account and the original repository. This is most useful if you want to contribute to a popular repository.</p>
<p>Some repositories merge pull requests hourly or less, so be safe and assume that the forked repository you have will be behind the original repository. </p>
<p><strong>Note that the upstream is in the freeCodeCamp repository and not your forked repository.</strong> Follow steps 1 and 2 as shown below to copy the upstream address:</p>
<p><img src="https://lh6.googleusercontent.com/-fIOwK3jSHRJQrtVdCbGYc_0xFxPt-I22JmCqIom7f5F53iKceawsfju-NBw_wQ5LtRmsk9gJB3qJfA28ujR01lhF8VQKvvercoigfnVUbKNHrgOalp4OXz5CH6tXX46ev7d6Acv" alt="Image" width="1040" height="631" loading="lazy"></p>
<p>To create a link to the original repository, copy and paste the following command into your terminal:</p>
<p><code>git remote add upstream &lt;upstream address&gt;</code></p>
<p>You can use <code>git pull upstream master</code> to confirm if there has been any change at the moment (from when you forked the repository to now).</p>
<h3 id="heading-step-4-create-the-branch-you-want-to-work-on">Step 4: Create the branch you want to work on</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/image-241.png" alt="Image" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@<em>zachreiner</em>?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Zach Reiner / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<p>It is nice to create a new branch whenever you want to contribute. This illustrates that the branch is only for that contribution you are about to make. It could be as small as fixing a typo or as large as implementing a new feature. Either way, it’s good practice to create a branch.</p>
<p>Another important part of the branch creation is naming. It is pleasing to use a name that a stranger who knows nothing about the repository can easily understand. If you want to add a login feature, for example, you could create a branch called <code>add-login-feature</code> or <code>login-feature</code>.</p>
<p>To create a branch type the following command into your terminal:</p>
<p><code>git checkout -b &lt;your branch name&gt;</code></p>
<p>This command will create the branch and navigate into it. If your branch name is login-feature, then you can use the following command:</p>
<p><code>git checkout -b login-feature</code></p>
<p><em><strong>Then add your contributions. After adding your contribution, move on to Step 5.</strong></em></p>
<h3 id="heading-step-5-git-add-and-commit-your-contributions">Step 5: Git add and commit your contributions</h3>
<p>This is quite simple as well. Stage and commit your changes by typing the following into your terminal.</p>
<p><code>git add .</code></p>
<p><code>git commit -m 'Commit message'</code></p>
<p>Now, you have the changes staged and committed. What next?</p>
<h3 id="heading-step-6-pull-from-upstream-to-the-branch">Step 6: Pull from upstream to the branch</h3>
<p>As I explained in step 4, this step is to merge any difference in the upstream into the branch so as to prevent conflicts.</p>
<p><code>git pull upstream &lt;branch name&gt;</code></p>
<p>This merges the upstream changes into your current branch.</p>
<h3 id="heading-step-7-push-to-the-branch-youre-working-on">Step 7: Push to the branch you’re working on</h3>
<p>Now, you are almost there. Push your changes to the branch you are working on as shown below:</p>
<p><code>git push origin &lt;branch-name&gt;</code></p>
<h3 id="heading-step-8-open-a-pull-request">Step 8: Open a pull request</h3>
<p>This is the final step for any open source contribution, you are simply saying ‘I have made some changes, would you mind adding it to the project?’.</p>
<p>You open a pull request and if the repository owner or members like what they see, they’ll merge it. Otherwise, they could make changes then merge or request for changes.</p>
<p>To open a pull request, navigate to the forked repository as shown below. You’ll see your last push branch <code>‘login-feature’</code>, then click on <code>‘compare and pull request’</code>.</p>
<p><img src="https://lh5.googleusercontent.com/GHcFpgR70pKrxpyhfNDnPRvVluSPF-gz2ICUKv1Q3uxZKEaBcwv32E8Rh7d-5yNS9uvGXWzCcoc22KBbddEOybzP7BkONlKdqXXmFtdcqIm6AU5ebZjAZeFV0iL7PMulwrnT8MnA" alt="Image" width="887" height="559" loading="lazy"></p>
<p>Explain clearly, the changes you made, then open a pull request as shown below:</p>
<p><img src="https://lh4.googleusercontent.com/4yGQB3_1-2IyGDiOAfNec1yyoMXyvEzUAEcShTx4xf8_DU5vgfhFN0Uihn0A-BZzKGJkeCnjDbQkXT_AKtTCsgAnXK6vDcIWuvWY5ETmUH4MORXT7kgz_4qKVnD2zj1bLcQRTWf1" alt="Image" width="994" height="567" loading="lazy"></p>
<p>And that’s it. :) You can now go ahead and contribute like a PRO!</p>
<h2 id="heading-git-cheat-sheet-for-open-source-contributors">Git cheat sheet for open source contributors</h2>
<p><img src="https://lh5.googleusercontent.com/ZoVAty5u4vZaFdwBXh2fpsPQMsgW_3qxnt_dCo8Qn5ayk-fdvIZh6D6jSY_GdUhW8yUZvIIaBc_6WoLTyWseX3M8m7yPIzA8f4fL6X_oikH5wRcykopNH1KPI7eEuiz_8-M-jnZm" alt="Image" width="1040" height="631" loading="lazy"></p>
<p>Peace out and happy contributing!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Why you should stop writing CSS in “CSS” ]]>
                </title>
                <description>
                    <![CDATA[ CSS is fun to write, but it can quickly get complicated. A typical example is having to scroll upwards to check the hexadecimal values of the colors you are using. Typing a class or id selector several times within a single CSS file, or having to cop... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/why-you-should-stop-writing-css-in-css-6fb724f6e3fc/</link>
                <guid isPermaLink="false">66bb8f9ed2bda3e4315491c8</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Saheed Oladele ]]>
                </dc:creator>
                <pubDate>Mon, 08 Apr 2019 16:23:33 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca37a740569d1a4ca5bd6.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>CSS is fun to write, but it can quickly get complicated. A typical example is having to scroll upwards to check the hexadecimal values of the colors you are using.</p>
<p>Typing a class or id selector several times within a single CSS file, or having to copy and paste every browser’s support prefix to your code each time for cross-browser compatibility can make your CSS file harder to maintain.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/863sGFar-HXTATzeqGsA3n-jlIMgrFFlNeBS" alt="Image" width="800" height="444" loading="lazy">
<em>A CSS code sample</em></p>
<pre><code class="lang-css">// <span class="hljs-selector-tag">cross-browser</span> <span class="hljs-selector-tag">compatibility</span>

<span class="hljs-selector-tag">-webkit-transform</span>: $<span class="hljs-selector-tag">property</span>
<span class="hljs-selector-tag">-ms-transform</span>: $<span class="hljs-selector-tag">property</span>
<span class="hljs-selector-tag">transform</span>: $<span class="hljs-selector-tag">property</span>

<span class="hljs-selector-tag">display</span>: <span class="hljs-selector-tag">-ms-flexbox</span>;
<span class="hljs-selector-tag">display</span>: <span class="hljs-selector-tag">flex</span>;

<span class="hljs-selector-tag">-ms-flex-wrap</span>: <span class="hljs-selector-tag">wrap</span>;
<span class="hljs-selector-tag">flex-wrap</span>: <span class="hljs-selector-tag">wrap</span>;
</code></pre>
<p>The next time you want to write CSS, try not “writing” in CSS at all.</p>
<p>Instead, try using CSS Preprocessors.</p>
<h3 id="heading-what-are-preprocessors">What are Preprocessors?</h3>
<p>According to <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/CSS_preprocessor">MDN</a>, a <strong>CSS preprocessor</strong> is a program that lets you generate CSS from the preprocessor’s own unique syntax. You write your CSS code in them and then generate a corresponding CSS file to style your HTML.</p>
<p>Some of the popular preprocessors to use include <a target="_blank" href="http://sass-lang.com/">SASS/SCSS</a>, <a target="_blank" href="http://lesscss.org/">LESS</a>, <a target="_blank" href="http://stylus-lang.com/">Stylus</a>, and <a target="_blank" href="http://postcss.org/">PostCSS</a>. I use SASS, so my illustrations in this article are in SASS.</p>
<p>Though preprocessors have their own syntax, they are quite easy to catch up with, just a few differences from writing vanilla CSS.</p>
<h3 id="heading-6-reasons-why-you-should-stop-writing-css-in-css">6 Reasons Why You Should STOP Writing CSS in “CSS”</h3>
<p>Preprocessors’ syntax gives room for some additional functionalities that deliver the following:</p>
<h4 id="heading-1-variables">1. Variables</h4>
<p>Preprocessors use variables to store reusable values. You can store any type of styling in a variable. It could be <code>color</code>, <code>font-family</code>, or even values for your <code>padding</code>, <code>margin</code>, <code>width</code>, or <code>height</code>.</p>
<p>When you define the variable, there is no need to remember the value. Recall the variable whenever you need the stored value.</p>
<pre><code class="lang-css">// <span class="hljs-selector-tag">variables</span>

$<span class="hljs-selector-tag">my_font</span>: <span class="hljs-selector-tag">Helvetica</span>, <span class="hljs-selector-tag">sans-serif</span>
$<span class="hljs-selector-tag">my-color</span>: <span class="hljs-selector-id">#333</span>

<span class="hljs-selector-tag">body</span>  
    <span class="hljs-selector-tag">font</span>: 100% $<span class="hljs-selector-tag">my-font</span>
    <span class="hljs-selector-tag">color</span>: $<span class="hljs-selector-tag">my-color</span>
</code></pre>
<h4 id="heading-2-nesting"><strong>2. Nesting</strong></h4>
<p>We write HTML by nesting child/children in parent elements like the <code>ul</code>, <code>li</code>, and <code>a</code> element in a <code>nav</code>. When using preprocessors, you don’t have to write out the parent CSS selector (<code>nav</code> tag in this case) each time.</p>
<p>Move to the next line and type the child element as shown below:</p>
<pre><code class="lang-css">// <span class="hljs-selector-tag">navigation</span> <span class="hljs-selector-tag">bar</span>

<span class="hljs-selector-tag">nav</span>
      <span class="hljs-selector-tag">ul</span>
        <span class="hljs-selector-tag">margin</span>: 0    
        <span class="hljs-selector-tag">padding</span>: 0    
        <span class="hljs-selector-tag">list-style</span>: <span class="hljs-selector-tag">none</span>  

    <span class="hljs-selector-tag">li</span>    
        <span class="hljs-selector-tag">display</span>: <span class="hljs-selector-tag">inline-block</span>

     <span class="hljs-selector-tag">a</span>    
        <span class="hljs-selector-tag">display</span>: <span class="hljs-selector-tag">block</span>
        <span class="hljs-selector-tag">padding</span>: 6<span class="hljs-selector-tag">px</span> 12<span class="hljs-selector-tag">px</span>
        <span class="hljs-selector-tag">text-decoration</span>: <span class="hljs-selector-tag">none</span>
</code></pre>
<p>The <code>ul</code>, <code>li</code>, and <code>a</code> selectors are nested inside the <code>nav</code> selector.</p>
<p>Some developers believe this is coming to CSS. But hey, it’s not here yet, it doesn’t hurt to get used to it before its arrival in CSS. :)</p>
<h4 id="heading-3-import"><strong>3. Import</strong></h4>
<p>Preprocessors make CSS’s existing <code>import</code> better.</p>
<p><code>import</code> lets you split your CSS into smaller files for readability and maintainability. It takes the file you are importing and adds it to the file you are importing into.</p>
<pre><code class="lang-css">// _<span class="hljs-selector-tag">reset</span><span class="hljs-selector-class">.sass</span>

<span class="hljs-selector-tag">html</span>, <span class="hljs-selector-tag">body</span>, <span class="hljs-selector-tag">div</span>, <span class="hljs-selector-tag">span</span>, <span class="hljs-selector-tag">applet</span>, <span class="hljs-selector-tag">object</span>, <span class="hljs-selector-tag">iframe</span>, <span class="hljs-selector-tag">h1</span>, <span class="hljs-selector-tag">h2</span>, <span class="hljs-selector-tag">h3</span>, <span class="hljs-selector-tag">h4</span>, <span class="hljs-selector-tag">h5</span>, <span class="hljs-selector-tag">h6</span>, <span class="hljs-selector-tag">p</span>, <span class="hljs-selector-tag">blockquote</span>    
    <span class="hljs-selector-tag">margin</span>: 0;
    <span class="hljs-selector-tag">padding</span>: 0;
    <span class="hljs-selector-tag">border</span>: 0;
    <span class="hljs-selector-tag">font-size</span>: 100%;
    <span class="hljs-selector-tag">font</span>: <span class="hljs-selector-tag">inherit</span>;
    <span class="hljs-selector-tag">vertical-align</span>: <span class="hljs-selector-tag">baseline</span>;
</code></pre>
<p>You can import the <code>reset.sass</code> file as shown below:</p>
<pre><code class="lang-css">// <span class="hljs-selector-tag">main</span><span class="hljs-selector-class">.sass</span>

<span class="hljs-keyword">@import</span> reset

body
    <span class="hljs-attribute">font:</span> <span class="hljs-number">100%</span> Helvetica, sans-serif
    <span class="hljs-attribute">background-color:</span> #efefef
</code></pre>
<p>This means you can have the <code>main.sass</code> file, then others like <code>reset.sass</code>, <code>header.sass</code>, <code>footer.sass</code>, or <code>variables.sass</code>. You <code>import</code> other files into the <code>main.sass</code> using the preprocessor’s <code>import</code> syntax.</p>
<p>The imported file is then added to the end of the <code>main.sass</code> file (the file you imported into).</p>
<h4 id="heading-4-extend"><strong>4. Extend</strong></h4>
<p><code>extend</code> stores a styling or series of styling into a class. It works like a variable. It uses a placeholder class <code>(%)</code> to tell the compiler not to print the class unless extended.</p>
<p>When the class is extended into an element, then the element inherits all the styling properties saved in the placeholder class. You can still add unique styling if needed.</p>
<pre><code class="lang-css">// <span class="hljs-selector-tag">This</span> <span class="hljs-selector-tag">CSS</span> <span class="hljs-selector-tag">will</span> <span class="hljs-selector-tag">print</span> <span class="hljs-selector-tag">because</span> %<span class="hljs-selector-tag">message-shared</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">extended</span>.
// "%" <span class="hljs-selector-tag">illustrates</span> <span class="hljs-selector-tag">the</span> <span class="hljs-selector-tag">placeholder</span> <span class="hljs-selector-tag">class</span>

%<span class="hljs-selector-tag">message-shared</span>
    <span class="hljs-selector-tag">border</span>: 1<span class="hljs-selector-tag">px</span> <span class="hljs-selector-tag">solid</span> <span class="hljs-selector-id">#ccc</span>
    <span class="hljs-selector-tag">padding</span>: 10<span class="hljs-selector-tag">px</span>
    <span class="hljs-selector-tag">color</span>: <span class="hljs-selector-id">#333</span>

// <span class="hljs-selector-tag">This</span> <span class="hljs-selector-tag">CSS</span> <span class="hljs-selector-tag">won</span>'<span class="hljs-selector-tag">t</span> <span class="hljs-selector-tag">print</span> <span class="hljs-selector-tag">because</span> %<span class="hljs-selector-tag">equal-heights</span> <span class="hljs-selector-tag">is</span> <span class="hljs-selector-tag">never</span> <span class="hljs-selector-tag">extended</span>.

%<span class="hljs-selector-tag">equal-heights</span>  
    <span class="hljs-selector-tag">display</span>: <span class="hljs-selector-tag">flex</span>
    <span class="hljs-selector-tag">flex-wrap</span>: <span class="hljs-selector-tag">wrap</span>

// <span class="hljs-selector-tag">This</span> <span class="hljs-selector-tag">extends</span> <span class="hljs-selector-tag">without</span> <span class="hljs-selector-tag">adding</span> <span class="hljs-selector-tag">any</span> <span class="hljs-selector-tag">other</span> <span class="hljs-selector-tag">styling</span>

<span class="hljs-selector-class">.message</span>
    <span class="hljs-keyword">@extend</span> %message-shared

// These extend with additional styling (green, red, yellow)

.success
    @extend %message-shared
    <span class="hljs-attribute">border-color:</span> green

.error  
    @extend %message-shared  
    <span class="hljs-attribute">border-color:</span> red

.warning  
    @extend %message-shared
    <span class="hljs-attribute">border-color:</span> yellow
</code></pre>
<p>This saves time and keeps your CSS clean.</p>
<h4 id="heading-5-arithmetic-operations"><strong>5. Arithmetic Operations</strong></h4>
<p>Preprocessors allow you to run arithmetic operations in your CSS. It supports standard mathematical operators like <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, and <code>%</code>.</p>
<pre><code class="lang-css">// <span class="hljs-selector-tag">Arithmetic</span> <span class="hljs-selector-tag">operations</span>
<span class="hljs-selector-class">.container</span>  
    <span class="hljs-selector-tag">width</span>: 100%

<span class="hljs-selector-tag">article</span><span class="hljs-selector-attr">[role=<span class="hljs-string">"main"</span>]</span>  
    <span class="hljs-selector-tag">float</span>: <span class="hljs-selector-tag">left</span>
    <span class="hljs-selector-tag">width</span>: 600<span class="hljs-selector-tag">px</span> / 960<span class="hljs-selector-tag">px</span> * 100%
</code></pre>
<h4 id="heading-6-minification"><strong>6. Minification</strong></h4>
<p>Minification reduces your file size to speed up load time. It removes white spaces and unnecessary characters from your code (CSS in this case).</p>
<p>Preprocessors allow you to generate a compressed version of your CSS. I know there are several other ways to generate this, but hey, this is cool as well. :)</p>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>Having to use the terminal when compiling is the main downside of using preprocessors. However, there are other ways to compile, such as using <a target="_blank" href="https://codekitapp.com/">CodeKit</a>, <a target="_blank" href="http://compass-style.org/">Compass.app</a>, and <a target="_blank" href="https://www.vanamco.com/ghostlab/">GhostLab</a>. There are now some in-editor plugins (like Live Sass Compiler on Visual Studio Code) to help with this as well.</p>
<p>Try out any preprocessor of your choice. I bet you won’t ever write CSS in “CSS” anymore. If you have been using preprocessors, share your experience in comments.</p>
<p>Peace out and happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
