<?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" version="2.0"><channel><title><![CDATA[Impact Lounge]]></title><description><![CDATA[Software Engineer with 5 years of experience building websites and apps using different technologies within the Javascript Ecosystem. Experienced with React, Ne]]></description><link>https://blog.abdulyusuf.me</link><generator>RSS for Node</generator><lastBuildDate>Wed, 13 May 2026 07:42:56 GMT</lastBuildDate><atom:link href="https://blog.abdulyusuf.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Increase Page Speed and Performance: Proven Strategies for Reducing JavaScript Bundle Size]]></title><description><![CDATA[Page speed and performance are some of the key factors that determine if a user will stay on a website or not. Any website that takes over ~2 seconds for its initial page load isn’t performant. Today's users do not have the patience or attention span...]]></description><link>https://blog.abdulyusuf.me/increase-page-speed-and-performance-proven-strategies-for-reducing-javascript-bundle-size</link><guid isPermaLink="true">https://blog.abdulyusuf.me/increase-page-speed-and-performance-proven-strategies-for-reducing-javascript-bundle-size</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[performance]]></category><category><![CDATA[Performance Optimization]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Abdulrahman Yusuf]]></dc:creator><pubDate>Mon, 10 Apr 2023 21:21:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/M-H70CDJnDI/upload/1666a8de19b60245aa80513be05bd967.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Page speed and performance are some of the key factors that determine if a user will stay on a website or not. Any website that takes over ~2 seconds for its initial page load isn’t performant. Today's users do not have the patience or attention span to wait long before getting a response on a site. Hence, it has become paramount for any website built today to be fast and responsive, especially during the initial load time.</p>
<p>Have you ever wondered why it’s taking time for your page to load whenever you visit a website? Did you check your network and confirm everything is okay? This is most likely due to the large Javascript bundle being fetched and parsed in the browser. If the JS bundle isn’t optimized, it will result in lower performance and higher user load time.</p>
<p>This article will review strategies and methods to reduce our overall Javascript bundle when deploying to production.</p>
<h3 id="heading-prerequisites"><strong>Prerequisites</strong></h3>
<p>This article assumes that you have:</p>
<ol>
<li><p><a target="_blank" href="https://nodejs.org/">Node</a> installed on your local machine</p>
</li>
<li><p><a target="_blank" href="https://yarnpkg.com/">yarn</a> or <a target="_blank" href="https://www.npmjs.com/">npm</a> installed on your local machine (npm comes pre-installed with node)</p>
</li>
<li><p>A text editor installed, e.g., VsCode.</p>
</li>
<li><p>Basic knowledge of HTML, CSS, Javascript, and the terminal. (see the <a target="_blank" href="https://youtu.be/kMT54MPz9oE">link</a> for a refresher on them)</p>
</li>
<li><p>Familiarity with at least one UI Framework, i.e., React, VueJS, or Angular.</p>
</li>
</ol>
<p>Before we proceed, we must understand why we must ensure our Javascript bundle is optimized and reduced to the smallest bundle size before deploying to production.</p>
<h3 id="heading-why-do-we-need-to-ship-smaller-js-bundles-to-production"><strong>Why Do We Need To Ship Smaller JS Bundles to Production?</strong></h3>
<p>Shipping small Javascript bundles to production is paramount as it's one of the major factors contributing to a website's overall performance. It determines how long a user waits for a page, whenever it’s visited, and what kind of experience the user gets on the webpage, especially for first-time users. It’s in the best interest of the business owners to ensure they don’t keep users waiting while their page is loading.</p>
<p>In the background, whenever a page is visited, the browser makes an HTTP request to the server to download the assets and files needed for that page. The Javascript files are then parsed and executed before rendering occurs. After completing these processes, user interaction becomes active on the page. All these depend on how large the Javascript bundle is, so optimizing and reducing the overall bundle size is a necessity every serious business owner must perform.</p>
<p>There are various factors resulting in large javascript bundles in our project. Some of them include:</p>
<ul>
<li><p><strong>Ignoring bundle sizes</strong>: Not paying attention to the bundle size of libraries and packages being installed.</p>
</li>
<li><p><strong>Lack of clean and readable code:</strong> The kind of code we write also determines how fast our Javascript files get parsed, compiled, and executed. If there are any sections in our code where we’ve ignored best practices and well-tested patterns, it’ll eventually affect the execution time of our javascript file in the browser.</p>
</li>
<li><p><strong>Absence of bundlers and compilers:</strong> Bundlers and compilers play a huge role in ensuring our overall javascript bundle is the bare minimum as we enjoy benefits like Minification, Code-Spliting, Tree-Shaking, and so much more. So, ignoring these tools would result in shipping a plain javascript file without the abovementioned features. The file would still run fine in the browser. However, important metrics like parse/compile time, execution time, memory usage, etc., all get affected.</p>
</li>
</ul>
<p>Having gone over why we need to ship smaller Javascript bundles and identifying the factors that lead to large bundles in our project, we will now discuss the strategies and methods we can employ to reduce our JS bundles. I’ve listed all the strategies we’ll discuss below:</p>
<ul>
<li><p>Using a bundler, e.g., webpack, parcel, vite, etc.</p>
</li>
<li><p>Bundle Size Inspection</p>
<ul>
<li><p>VsCode Import Cost Plugin</p>
</li>
<li><p>Webpack-Bundle-Analyzer</p>
</li>
<li><p>Others include <a target="_blank" href="https://github.com/danvk/source-map-explorer">Source-Map-Explorer</a>, <a target="_blank" href="https://www.bundle-buddy.com/create-react-app">Bundle-Buddy</a>, <a target="_blank" href="https://bundlephobia.com/">Bundlephobia</a> e.t.c</p>
</li>
</ul>
</li>
<li><p>Code-Splitting</p>
</li>
<li><p>Lazy-loading</p>
</li>
</ul>
<h3 id="heading-using-a-bundler"><strong>Using a Bundler</strong></h3>
<p>The first step in achieving a smaller, optimized bundle size is using a code bundling tool. Bundling means merging all our Javascript files and modules into one single file, which will then be executed in the browser. With bundling, we enjoy benefits like Minification, Tree-Shaking, Code-Splitting, etc., out of the box without going through them ourselves.</p>
<p>Fortunately, almost all frameworks or UI libraries we use today have a bundler setup by default whenever they are being installed for development. Popular bundlers include <a target="_blank" href="https://webpack.js.org">webpack</a>, <a target="_blank" href="https://parceljs.org">parcel</a>, <a target="_blank" href="https://vitejs.dev">vite</a>, <a target="_blank" href="https://browserify.org">browserify</a>, <a target="_blank" href="https://rollupjs.org">rollup</a>, etc.</p>
<h3 id="heading-bundle-size-inspection"><strong>Bundle Size Inspection</strong></h3>
<p>In today’s development world, hundreds of packages and dependencies are usually installed in our project. The best way to reduce our Javascript bundle size is to be conscious and observe how large a dependency or package is after installation. This would enable us to take a step back and weigh our options if it’s best to use the package or develop a hand-written utility to solve whichever problem we might need it for. Various tools have been created to make bundle-size inspection easy and straightforward. However, we will review a few of them, which I feel are the most important: Import Cost Plugin, Webpack-Bundle-Analyzer, and Source-Map-Explorer.</p>
<p><strong>Import Cost Plugin</strong></p>
<p>A popular tool that makes this easy to achieve is the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost">vscode-import-cost</a> plugin. This extension calculates every third-party import we make in our application and displays inline the size of the imported package. It is also available as a standalone package for other IDEs integration.</p>
<p><img src="https://lh3.googleusercontent.com/eqi853e5NxgFbNMytP9udDyvsUKg9KGY2ZMzdP529G_-_LS6A4WCpMRYU69bJHa0kOudKUyP_2xUxcbCllilMF-tShZcDBc4NdFrHpY89AIaRAAkaeOmF9vax_4EKdznHf_RHW3YMH_ZJgjDx-bB2nk" alt="Example Image" /></p>
<p><strong>Webpack-Bundle-Analyzer</strong></p>
<p>This popular webpack plugin helps users visualize their bundle sizes in a treemap and help identify which package or dependencies need to be removed. It visualizes each file in our bundle as interactive blocks that can be clicked and zoomed on for us to inspect all dependencies. Setting up webpack is pretty straightforward. However, one downside is that it can only be used in projects with webpack installed as its code bundler.</p>
<p>Webpack-bundle-analyzer can be installed using the following commands:</p>
<pre><code class="lang-bash">npm install --save-dev webpack-bundle-analyzer
</code></pre>
<p>Paste the following snippet in your <code>webpack.config.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> BundleAnalyzerPlugin = <span class="hljs-built_in">require</span>(<span class="hljs-string">'webpack-bundle-analyzer'</span>).BundleAnalyzerPlugin;

<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">plugins</span>: [
    <span class="hljs-keyword">new</span> BundleAnalyzerPlugin()
  ]
}
</code></pre>
<p>Then run your build command:</p>
<pre><code class="lang-bash">npm run build
// OR
npx webpack -—config webpack.config.js
</code></pre>
<p>This will create and open an interactive treemap visualization of the contents of all your bundles in the browser.</p>
<p><img src="https://lh6.googleusercontent.com/hcNwflFvHwaIjqmEwZJF4ftpP4gsFlLZiTBjTwwLq0ihtzd_e-jfURrJw82Mp_IMRddkzT44zUBTvPxLZ9rQnCjyndS05yelXktkUtfenocYJ22i5lyVcIj8u7BmzrBcGyOxIuGA1V8GrJ1YOcjg1E4" alt="webpack bundle analyzer zoomable treemap" /></p>
<p><strong>Source-Map-Explorer</strong></p>
<p>Source-Map-Explorer is an excellent alternative to webpack-bundle-analyzer. It analyzes our Javascript bundles using source maps and helps identify where our code bloat comes from. It’s also handy for people who have bootstrapped their React applications with the CRA (<a target="_blank" href="https://create-react-app.dev">create-react-app</a>) setup and have no intention of ejecting their application.</p>
<p>To install the source-map-explorer, run the command below:</p>
<pre><code class="lang-bash">npm install -g source-map-explorer
</code></pre>
<p>Then add the code snippet below to the “scripts” section in your <code>package.json</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"scripts"</span>: {
   <span class="hljs-string">"analyze"</span>: <span class="hljs-string">"source-map-explorer 'build/static/js/*.js'"</span>,
   <span class="hljs-string">"start"</span>: <span class="hljs-string">"react-scripts start"</span>,
   <span class="hljs-string">"build"</span>: <span class="hljs-string">"react-scripts build"</span>,
   <span class="hljs-string">"test"</span>: <span class="hljs-string">"react-scripts test"</span>
}
</code></pre>
<p>Finally,  run the <code>npm run build</code> and <code>npm run analyze</code> commands in your terminal.</p>
<p>This will create a visualization in your browser and show how the space is used in your minified bundle.</p>
<p><img src="https://lh6.googleusercontent.com/kn5hDf04ogsgTSTZT_b0v3hSkYGrxlL8pEkjH-MDb2-HAL6IZ13fpMohGzwlsKa6OxSksExIP8UXY2iWenMt2BvLXaidxGyqQpWxVSQb972zv6jXFDEpB1njzsJe1SrNoErVj1ITTiW7dAchJlTPa_I" alt /></p>
<h3 id="heading-code-splitting"><strong>Code Splitting</strong></h3>
<p>This is the process of splitting our code into various bundles or chunks, which can be loaded later in the future when needed. It can dramatically improve our app's performance as only the bundles required for a page are loaded in the browser. Code Splitting can be done by most bundlers out there, and it’s all a matter of identifying the files that are required for the initial page load.</p>
<p>For most bundlers, the best way to introduce code-splitting is through the <code>import()</code> syntax.</p>
<p>“<em>The import() syntax, commonly called dynamic import, is a function-like expression that allows loading an ECMAScript module asynchronously and dynamically into a potentially non-module environment.</em>” - <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import">MDN</a></p>
<p>The difference between this <code>import()</code> function and the static <code>import</code> keyword is that the former can be used anywhere within a module or non-module file, while the latter can only be used in top-level modules.</p>
<p>Most frameworks have also improved how code-splitting can be implemented in their applications. For instance:</p>
<ul>
<li><p>In React, code-splitting can be implemented using <a target="_blank" href="https://reactjs.org/docs/code-splitting.html">React.lazy() and Suspense</a>.</p>
</li>
<li><p>In NextJS, we have <a target="_blank" href="https://nextjs.org/docs/advanced-features/dynamic-import">NextJS Dynamic Import</a>.</p>
</li>
<li><p>In VueJS, we can import <a target="_blank" href="https://vuejs.org/guide/best-practices/performance.html#code-splitting">defineAsyncComponent()</a>.</p>
</li>
</ul>
<p>A perfect use case for dynamic import would be with a Language Switcher. Imagine a webpage supporting about 3 - 5 locales, which users can toggle using a dropdown. Loading and bundling all the translations for all five locales would be inefficient and affect the webpage load time performance. One way to optimize this is by loading the translations dynamically.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> i18n <span class="hljs-keyword">from</span> “i18next”;

<span class="hljs-comment">// Initialize i18n instance</span>
i18n
 .use()
 .init({ … })


<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handleLoadLanguage = <span class="hljs-keyword">async</span> (locale = <span class="hljs-string">"en"</span>) =&gt; {
    <span class="hljs-keyword">const</span> messages = <span class="hljs-keyword">await</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">`../translations/<span class="hljs-subst">${locale}</span>.json`</span>);
    i18n.setLocaleMessage(locale, messages.root);
    <span class="hljs-keyword">await</span> i18n.changeLanguage(locale)
};
</code></pre>
<p>Other use cases where dynamic import would be helpful include:</p>
<ul>
<li><p>Displaying a modal: a modal is shown conditionally in most cases</p>
</li>
<li><p>Displaying a Date-Picker component</p>
</li>
<li><p>Loading user comment sections on a blog or website</p>
</li>
<li><p>UI for a page not rendered immediately</p>
</li>
</ul>
<p>One thing to keep in mind is to ensure that dynamically fetching a file or component in the background doesn’t affect user experience and make the UI feel unresponsive or delayed while the user is on a page.</p>
<h3 id="heading-lazy-loading"><strong>Lazy Loading</strong></h3>
<p>Lazy loading is an optimization technique mostly used in web browsers. However, it is a form of <strong>code-splitting</strong> as well because the files are only loaded until a certain condition has been met. In most cases, lazy loading is implemented for images and media-related assets. They get loaded when the user reaches a visible part of the viewport or when interaction occurs with an image. One popular way components can dynamically be loaded on interaction is using the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">Intersection Observer API</a>.</p>
<p>An excellent example is a Product-Listings page. Loading all the products simultaneously would require considerable bandwidth, increasing load time as the products are loaded. Hence, with Lazy-loading, only the products a user can see in the viewport would be downloaded, then on scrolling down the webpage, the rest of the products would be downloaded on demand. Implementing a strategy like this would result in substantial performance gains for the website.</p>
<p>Here are Airbnb product listings being lazy loaded:</p>
<p><img src="https://lh6.googleusercontent.com/rrcAJMerxfs6gyJXsjxhqy0dkp_140VqzNwYpJjE_RSVkF-mBcFgjQ0AkYog4asX4wIQnAHCM9hRIRcOkpFAkKBM7Hy2z1QI61XNG5nh-FfF0WeLiCu8QUKPx1GsWanMM0lihil9wHKe_T6nqT5Ozxk" alt /></p>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>The size of our Javascript bundle remains an essential factor to consider when optimizing our webpage for performance. However, achieving a performant website not only has to do with our javascript bundle. Other strategies like Image and Font Optimization, serving via CDN, Caching static pages, etc., are all non-javascript-related methods that need to be in place to achieve the best performance for our site.</p>
<p>Hence, the journey to obtaining that state of performance we all yearn for on our websites is not achieved in a single run. Instead, it requires frequent optimizations and strategies being put in place to ensure users of our website get the information they need on time.</p>
<p>I hope you found this article helpful and have learned a few methods to achieve the required performance we all want for our websites. Feel free to contact me via <a target="_blank" href="https://www.linkedin.com/in/abdulrahman-yusuf-a44463176/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/zaydabdulrahman">Twitter</a> if you have any questions.</p>
<h3 id="heading-resources"><strong>Resources</strong></h3>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=MxBCPc7bQvM">How to analyze your Javascript Bundles</a>, Google Chrome Developers Channel, Youtube</p>
</li>
<li><p><a target="_blank" href="https://calibreapp.com/blog/bundle-size-optimization">Small Bundles, Fast Pages: What to do with too much Javascript,</a> Calibre</p>
</li>
<li><p><a target="_blank" href="https://www.smashingmagazine.com/2022/02/javascript-bundle-performance-code-splitting/">Improving Javascript Bundle Performance with Code-Splitting,</a> Smashing Magazine</p>
</li>
<li><p><a target="_blank" href="https://www.debugbear.com/blog/reducing-javascript-bundle-size">Optimizing Javascript Bundle Size</a>, DebugBear</p>
</li>
<li><p><a target="_blank" href="https://www.keycdn.com/blog/website-performance-optimization">18 Tips for Website Performance Optimization</a>, KeyCDN</p>
</li>
<li><p><a target="_blank" href="https://blog.bitsrc.io/5-methods-to-reduce-javascript-bundle-size-67f2e1220457">5 Methods to Reduce Javascript Bundle Size</a>, Bits and Pieces</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Introduction to JavaScript Modules]]></title><description><![CDATA[Originally, Javascript was used as a tool to create beautiful animations and interactions on the web, they were there to make websites look attractive and eye catchy, and that was all. But then, Google Maps was introduced, and that period represented...]]></description><link>https://blog.abdulyusuf.me/introduction-to-javascript-modules</link><guid isPermaLink="true">https://blog.abdulyusuf.me/introduction-to-javascript-modules</guid><category><![CDATA[html/css]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Abdulrahman Yusuf]]></dc:creator><pubDate>Mon, 27 Feb 2023 14:39:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/IEiAmhXehwE/upload/bb086e74da5eb97dffdd9e5b199aaab4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Originally, Javascript was used as a tool to create beautiful animations and interactions on the web, they were there to make websites look attractive and eye catchy, and that was all. But then, Google Maps was introduced, and that period represented when innovations and technologies were built using Javascript.</p>
<p>It was a whole new era with its quirks and downsides. Initially, javascript code didn’t exceed two to four lines, but as the complexity of websites and apps increased, the amount of javascript code shipped to the browser skyrocketed. As a result, we now have millions of javascript code running in the browser, thanks to the frameworks and libraries we use for development.</p>
<p>Managing and maintaining that much code requires a much more efficient and productive method, hence the creation of <strong>Javascript Modules</strong>.</p>
<p>In this article, I’ll explain how we can utilize the power of javascript modules in our project and why it’s a good pattern when developing javascript applications.</p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<ol>
<li><p><a target="_blank" href="https://nodejs.org/">Node</a> installed on your local machine</p>
</li>
<li><p><a target="_blank" href="https://yarnpkg.com/">yarn</a> or <a target="_blank" href="https://www.npmjs.com/">npm</a> installed on your local machine (npm comes pre-installed with node)</p>
</li>
<li><p>A text editor installed, e.g., VsCode.</p>
</li>
<li><p>Basic knowledge of HTML, CSS, Javascript, and the terminal (Check out this <a target="_blank" href="https://youtu.be/kMT54MPz9oE">article</a> for a refresher on them)</p>
</li>
</ol>
<h2 id="heading-what-is-a-module"><strong>What is a Module?</strong></h2>
<p>A module is a self-contained javascript file containing variables, functions, or classes that can be available to other files across your project. Making a function or class available to other modules is called <strong>export</strong>. In contrast, using a function or class from another module is called <strong>import.</strong> Javascript Modules allow us to utilize this system of modules within our project, thereby enabling us to enjoy benefits like:</p>
<ul>
<li><p>Code maintainability</p>
</li>
<li><p>Ease of code reusability</p>
</li>
<li><p>Code scalability</p>
</li>
</ul>
<p>Javascript Modules allow us to break down and split our code into multiple and self-contained chunks that can be easily well-maintained and scalable should there be any need for any addition in the future. This feature has been available in NodeJS and in popular frameworks and libraries within the Javascript ecosystem for a while now. However, it’s only recently that this feature became available natively within the browser.</p>
<p>Looking at the Browser Compatibility Specs on <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#a_background_on_modules">MDN</a>, it’s now supported in most popular browsers used by everyone.</p>
<p><img src="https://lh5.googleusercontent.com/vwl2Jr3fws_LS4J4naQl0XnBOmegZbq6q6TI7aokhzu39X1GHtIVe3c8Uy5zpUZCEjzWKUJOHcjgnn7OPeeNUHM6KHMKy7olvpSmDoPB5pl2gn4KqcCYIrfmtVyrogQXs921ue0CyJZFdhZvA5gjgyA" alt /></p>
<p><img src="https://lh4.googleusercontent.com/Ic0NM29Y-HNnqAo2X2GEh0VPERruzyLSqVixU14t4BJxdzdYKw64Rg9QqWev_r_UigChd6fLdU83ai4G7cCPpJkZV2k5aoP1lReZ2C4PnlGMIxNo1OPN8XLVlX666EcaHMwq_8lOqMk9_oeXGMP9_sM" alt /></p>
<h2 id="heading-using-modules-in-a-project"><strong>Using Modules in a Project</strong></h2>
<p>To get started with modules in a project, your script tag in the HTML file needs to have the <code>type</code> attribute included, like the snippet below:</p>
<p><img src="https://lh5.googleusercontent.com/DILLJRnPBaw_382EUddJBJ4I4iJa6LR6eLF8Dim-mQiQPp9MISkmxwiZ4lwW-0KU01f-3YJrTTi4YRXTCPLK8XccNgfOMJr_OfNtt5LfS2qOshcwXCvKg67Bv2LUGjzm-UqEtBAzdrGTq40iT8jb9vI" alt /></p>
<p>Open your terminal and paste in the command below to create a new folder, navigate into it and create an HTML file named <code>index.html</code>:</p>
<pre><code>mkdir js-modules
cd js-modules
touch index.html
</code></pre><p>Open the folder in VsCode using the command below:</p>
<pre><code>code .
</code></pre><p>Our project should look like this now:</p>
<p><img src="https://lh3.googleusercontent.com/PSHIAfNeHnttbDll4z-EUlQcVdvmGvCnoP08LynbPG8Qc1pbqzwnayIfc26ptRsEJD13FRCxJ8G1LOiHCZFTSJcVUWLrZrxEFgNg0lRLJo4PF35tI1Q5qZnmytwzd2jeq3j6BTPfPMxngs9T0AZbIAA" alt /></p>
<p>Paste the starter code below in our <code>index.html</code> file and create a javascript file called <code>app.js</code>:</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
  &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1&gt;Hello World&lt;/h1&gt;
  &lt;script type="module" src="app.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>If you observe, the script tag in our HTML file has the <code>type</code> attribute with a value of <code>module</code>. This is because the <code>app.js</code> file we just created would be a module.</p>
<p>Also, when using javascript files that are modules, we need to serve our HTML file using a server cause opening the file directly would throw a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors">CORS error</a> in the browser console due to our browser not identifying where the file is being served from. Not doing this would result in the error below:</p>
<p><img src="https://lh4.googleusercontent.com/oDcrlZfM1jyotqjHGpgd2bNeI4JSgh8UjMBBsUNrnGNr2CLcM4ujgxIxOrt8XfQtx6YBMvZ79w-krVrx4KRsUVJoWZl2zq1G7iHIRkfQUd-LZKsraMWZ4C42Zxn4poEeF6I-Pn24-yGAR5rNxL2jprw" alt /></p>
<p>We'll use Live Server in this tutorial. See <a target="_blank" href="https://www.youtube.com/watch?v=2fhe0LLj3Rw">this video</a> on how to install it in VsCode.</p>
<p>Now, create another javascript file named utils.js and paste in the following snippets below:</p>
<pre><code><span class="hljs-keyword">const</span> users = [
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"John"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Doe"</span>,
  },
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Evan"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Blacwk"</span>,
  },
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Julian"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Drey"</span>,
  },
];

<span class="hljs-comment">/**
 * function to get all even numbers in an array of numbers
 *
 * @param {number[]} nums
 * @return {number[]} Array of even numbers
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getEvenNumbers</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>);
}

<span class="hljs-comment">/**
 * function to get all odd numbers in an array of numbers
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number[]}</span> </span>Array of odd numbers
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getOddNumbers</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num % <span class="hljs-number">2</span> !== <span class="hljs-number">0</span>);
}

<span class="hljs-comment">/**
 * function to get all numbers greater than 5 in an array of numbers
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number[]}</span></span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getNumbersLargerThanFive</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num &gt; <span class="hljs-number">5</span>);
}

<span class="hljs-comment">/**
 * function to combine firstName and  lastName into a fullname
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">firstName</span></span>
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">lastName</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{string}</span> <span class="hljs-variable">FullName</span></span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">combineNames</span>(<span class="hljs-params">firstName, lastName</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${firstName}</span> <span class="hljs-subst">${lastName}</span>`</span>;
}
</code></pre><h2 id="heading-using-the-export-and-import-keyword"><strong>Using the export and import keyword</strong></h2>
<p>There are two main ways the <strong>export/import</strong> keyword can be used in a script, they are:</p>
<ul>
<li><p>Using as a Named Export/Import</p>
</li>
<li><p>Using as a Default Export/Import</p>
</li>
</ul>
<p><strong>Named Exports</strong></p>
<p>Let’s update the code snippet we pasted in our utils.js file by appending the export keyword before each function. Our code should look like this now:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> users = [
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"John"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Doe"</span>,
  },
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Evan"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Blacwk"</span>,
  },
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Julian"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Drey"</span>,
  },
];

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getEvenNumbers</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>);
}
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getOddNumbers</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num % <span class="hljs-number">2</span> !== <span class="hljs-number">0</span>);
}
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getNumbersLargerThanFive</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num &gt; <span class="hljs-number">5</span>);
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">combineNames</span>(<span class="hljs-params">firstName, lastName</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${firstName}</span> <span class="hljs-subst">${lastName}</span>`</span>;
}
</code></pre><p>The <strong>export</strong> keyword makes whichever variable, function, or class it’s appended to available to all other scripts in our project. If we have so many functions we want to export, adding the export keyword on each of them might be a task on its own, so there’s a much cleaner approach which is having a single export object at the end of the file as we have below:</p>
<pre><code><span class="hljs-keyword">const</span> users = [
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"John"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Doe"</span>,
  },
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Evan"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Blacwk"</span>,
  },
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Julian"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Drey"</span>,
  },
];

<span class="hljs-comment">/**
 * function to get all even numbers in an array of numbers
 *
 * @param {number[]} nums
 * @return {number[]} Array of even numbers
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getEvenNumbers</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>);
}

<span class="hljs-comment">/**
 * function to get all odd numbers in an array of numbers
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number[]}</span> </span>Array of odd numbers
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getOddNumbers</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num % <span class="hljs-number">2</span> !== <span class="hljs-number">0</span>);
}

<span class="hljs-comment">/**
 * function to get all numbers greater than 5 in an array of numbers
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number[]}</span></span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getNumbersLargerThanFive</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num &gt; <span class="hljs-number">5</span>);
}

<span class="hljs-comment">/**
 * function to combine firstName and  lastName into a fullname
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">firstName</span></span>
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">lastName</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{string}</span> <span class="hljs-variable">FullName</span></span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">combineNames</span>(<span class="hljs-params">firstName, lastName</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${firstName}</span> <span class="hljs-subst">${lastName}</span>`</span>;
}

<span class="hljs-keyword">export</span> {
  users,
  getEvenNumbers,
  getOddNumbers,
  getNumbersLargerThanFive,
  combineNames,
};
</code></pre><p>Having done this, we can now import any of these functions in <code>app.js</code> and make use of it below:</p>
<pre><code><span class="hljs-keyword">import</span> {
  getEvenNumbers,
  getOddNumbers,
  getNumbersLargerThanFive,
  users,
  combineNames,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils.js"</span>;

<span class="hljs-built_in">console</span>.log(getEvenNumbers([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>])); <span class="hljs-comment">// Prints [2, 4, 6, 8, 10]</span>
<span class="hljs-built_in">console</span>.log(getOddNumbers([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>])); <span class="hljs-comment">// Prints [1, 3, 5, 7, 9]</span>
<span class="hljs-built_in">console</span>.log(getNumbersLargerThanFive([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>])); <span class="hljs-comment">// Prints [6, 7, 8, 9, 10]</span>
<span class="hljs-built_in">console</span>.log(users.map(<span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> combineNames(user.firstName, user.lastName))); <span class="hljs-comment">// Prints ['John Doe', 'Evan Blacwk', 'Julian Drey']</span>
</code></pre><p>We should get the output below in our console when we open our <code>index.html</code> file in the browser:</p>
<p><img src="https://lh4.googleusercontent.com/v6lVX_5EbdxXzYbu-nifOUvMrcbPaiMaRJsztbf4J0ATSOl7EJljZHKb641VpkEgcY7VjoFAv1Y7pkyLZYNjs_9WWCnuy96ubbLt-v1Ngh2oRaFlHiVhfQeGLFdSDrYR6d4rrAFSxJt1oaE5Iscrhfg" alt /></p>
<p><strong>NB:</strong> Since the curly braces for the <code>export/import</code> looks like an object, we have the option of being able to rename a variable or function in an <code>export/import</code> statement using the <code>as</code> keyword like this:</p>
<pre><code><span class="hljs-comment">// For export</span>
<span class="hljs-keyword">export</span> {
  users <span class="hljs-keyword">as</span> userList,
  getEvenNumbers <span class="hljs-keyword">as</span> extractNumbersDivisibleByTwo,
  getOddNumbers <span class="hljs-keyword">as</span> extractOddNumbers,
  getNumbersLargerThanFive,
  combineNames,
};
<span class="hljs-comment">// For import</span>
<span class="hljs-keyword">import</span> {
  extractNumbersDivisibleByTwo <span class="hljs-keyword">as</span> evenNumbersFunc,
  getOddNumbers <span class="hljs-keyword">as</span> oddNumbersFunc,
  getNumbersLargerThanFive,
  usersList,
  combineNames,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils.js"</span>;
</code></pre><p>One other advantage of named import is the fact that we can import everything exported from the <code>utils.js</code> file into a module object which we can then be accessed using the dot notation like this:</p>
<pre><code><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> utils <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils.js'</span>;

<span class="hljs-built_in">console</span>.log(utils.getEvenNumbers([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>])); <span class="hljs-comment">// Prints [2, 4, 6, 8, 10]</span>
<span class="hljs-built_in">console</span>.log(utils.getOddNumbers([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>])); <span class="hljs-comment">// Prints [1, 3, 5, 7, 9]</span>
<span class="hljs-built_in">console</span>.log(utils.getNumbersLargerThanFive([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>])); <span class="hljs-comment">// Prints [6, 7, 8, 9, 10]</span>
</code></pre><p>This is very useful for situations where our <code>utils.js</code> file might be used in multiple files. That way, the variables or functions can be named according to the file where it’s being used.</p>
<p><strong>Default Exports</strong></p>
<p>In a situation where we would like to have a default variable or function exported, we can include <code>default</code> alongside the <code>export</code> keyword prefixing the variable or function to be exported. Also, there can only be one default statement in a module. For example, let’s export our <code>users</code> array as a default export below:</p>
<pre><code><span class="hljs-keyword">const</span> users = [
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"John"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Doe"</span>,
  },
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Evan"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Blacwk"</span>,
  },
  {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Julian"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Drey"</span>,
  },
];

<span class="hljs-comment">/**
 * function to get all even numbers in an array of numbers
 *
 * @param {number[]} nums
 * @return {number[]} Array of even numbers
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getEvenNumbers</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>);
}

<span class="hljs-comment">/**
 * function to get all odd numbers in an array of numbers
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number[]}</span> </span>Array of odd numbers
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getOddNumbers</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num % <span class="hljs-number">2</span> !== <span class="hljs-number">0</span>);
}

<span class="hljs-comment">/**
 * function to get all numbers greater than 5 in an array of numbers
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number[]}</span></span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getNumbersLargerThanFive</span>(<span class="hljs-params">nums</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
  <span class="hljs-keyword">return</span> nums.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num &gt; <span class="hljs-number">5</span>);
}

<span class="hljs-comment">/**
 * function to combine firstName and  lastName into a fullname
 *
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">firstName</span></span>
 * <span class="hljs-doctag">@param <span class="hljs-type">{string}</span> <span class="hljs-variable">lastName</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{string}</span> <span class="hljs-variable">FullName</span></span>
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">combineNames</span>(<span class="hljs-params">firstName, lastName</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${firstName}</span> <span class="hljs-subst">${lastName}</span>`</span>;
}

<span class="hljs-keyword">export</span> {
  getEvenNumbers,
  getOddNumbers,
  getNumbersLargerThanFive,
  combineNames,
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> users;
</code></pre><p>In our <code>app.js</code> file, we can import the <code>users</code> variable individually without having the curly braces as we had from the earlier examples. This is because our <code>users</code> array is the default variable exported from <code>utils.js</code>.</p>
<pre><code><span class="hljs-keyword">import</span> {
  getEvenNumbers,
  getOddNumbers,
  getNumbersLargerThanFive,
  combineNames,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils.js"</span>;
<span class="hljs-keyword">import</span> users <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils.js'</span>;

<span class="hljs-comment">// The rest of the code</span>
...
</code></pre><p>Or we could have it like this:</p>
<pre><code><span class="hljs-keyword">import</span> users, {
  getEvenNumbers,
  getOddNumbers,
  getNumbersLargerThanFive,
  combineNames,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils.js"</span>;
</code></pre><h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This article introduced you to Javascript Modules and how to utilize them in your project. I hope you’ve found it helpful. </p>
<p>If you have any questions or suggestions for me, feel free to drop a comment below. And if you are looking for additional resources, I’d recommend these ones:</p>
<ul>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules">Javascript Modules</a>, MDN Docs</p>
</li>
<li><p><a target="_blank" href="https://javascript.info/modules-intro">Modules Introduction</a>, Javascript Info</p>
</li>
<li><p><a target="_blank" href="https://hacks.mozilla.org/2015/08/es6-in-depth-modules/">ES6 In Depth: Modules</a>, Mozilla Hacks</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Building an Embeddable Widget With HTML, CSS, and Javascript]]></title><description><![CDATA[The use cases for widgets have risen over the past ten years within the web ecosystem as their importance has grown in different sectors ranging from e-commerce to fintech to health websites.
Widgets have made it easy and seamless for users to perfor...]]></description><link>https://blog.abdulyusuf.me/building-an-embeddable-widget-with-html-css-and-javascript</link><guid isPermaLink="true">https://blog.abdulyusuf.me/building-an-embeddable-widget-with-html-css-and-javascript</guid><category><![CDATA[HTML]]></category><category><![CDATA[CSS]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[ecommerce]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Abdulrahman Yusuf]]></dc:creator><pubDate>Wed, 25 Jan 2023 12:47:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674648474876/e172e4f3-5229-4c33-a2ba-ebdab2efdf90.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The use cases for widgets have risen over the past ten years within the web ecosystem as their importance has grown in different sectors ranging from e-commerce to fintech to health websites.</p>
<p>Widgets have made it easy and seamless for users to perform various actions on a website.</p>
<p>In this article, we will be going over a tutorial on how to build a simple messaging widget that can be embedded in any website.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ol>
<li><p><a target="_blank" href="https://nodejs.org/">Node</a> installed on their local machine</p>
</li>
<li><p><a target="_blank" href="https://yarnpkg.com/">yarn</a> or <a target="_blank" href="https://www.npmjs.com">npm</a> installed on your local machine (npm comes pre-installed with node)</p>
</li>
<li><p>A text editor installed e.g VsCode.</p>
</li>
<li><p>Basic knowledge of HTML, CSS, Javascript, and the terminal. (see <a target="_blank" href="https://youtu.be/kMT54MPz9oE">link</a> for a refresher on them)</p>
</li>
</ol>
<h2 id="heading-what-is-a-widget">What is a Widget?</h2>
<p>A widget is a stand-alone app or component that can be added to a website. They usually work independently of the website in which they’re installed, hence, they have everything they need to run efficiently wherever they’re used. Widgets can be set up very easily - it’s as simple as copy-pasting a script or code block into your website for it to start working.</p>
<p>There are so many reasons or use cases for needing a widget in a website, they are useful with a lot of things like:</p>
<ul>
<li><p>Helping business owners and customers communicate more easily via instant messaging.</p>
</li>
<li><p>Aiding the customer support team to efficiently interact with a user’s issues or bugs in a website.  They can even serve as a means through which users can see FAQs on a website.</p>
</li>
<li><p>Enabling users to gain easy access to products and items in carts for eCommerce businesses.</p>
</li>
</ul>
<p>Generally, widgets improve the overall customer retention/experiences of businesses and help drive sales and solve recurring issues amongst users. There are many kinds of widgets, ranging from customer support to messaging widgets, help widgets, search widgets, cart widgets, etc. Anything can be a widget as long as it has a specific functionality it’s meant to perform on a website.</p>
<h2 id="heading-getting-started">Getting Started</h2>
<p>For this tutorial, we will build a simple messaging widget that can be installed on any website. If you’re interested in getting the code for the final app, you can find it <a target="_blank" href="https://github.com/Young-Einstein10/messaging-widget">here</a>.</p>
<p>We’ll be building our widget using <a target="_blank" href="https://vitejs.dev">Vite</a> as our package bundler. It’s very easy and straightforward to set up.</p>
<h2 id="heading-setting-up-the-project">Setting up the project</h2>
<p>Open your terminal and paste in the command below to create a new folder and navigate into that folder:</p>
<pre><code class="lang-plaintext">mkdir messaging-widget
cd messaging-widget
</code></pre>
<p>Once you’re in the folder, paste in the command below to setup Vite:</p>
<pre><code class="lang-plaintext">yarn create vite
</code></pre>
<p>You’ll get some prompts that you’ll need to answer for the setup, use my responses below:</p>
<ul>
<li><p>Project Name is: <code>./</code></p>
</li>
<li><p>Select a framework: Vanilla</p>
</li>
<li><p>Select a variant: Javascript</p>
</li>
</ul>
<p>On doing this, you should get results similar to the one below:</p>
<p><img src="https://lh4.googleusercontent.com/9TxaWWnLMMIN11LMxy6BHNQit3SPfMjxoqSUDlQrfy_GvYyialPgL7-MG_R8AVEZACf8HmvrLnCqjPnjbwz7seAsjTKtgrRPNqFS2DsbGatSxAlhYTfG9Shol_HgVPmX18oPSI5CdiNH8IXqlfBw2iSceAyx_bBVVO7IlSiablF2GUxC_HRQyoh4S4H2ug" alt /></p>
<p>Now that Vite has been set up successfully, we’ll need to install it as it’s a dev dependency in our project. To do this, run the code snippet below:</p>
<pre><code class="lang-plaintext">yarn install
</code></pre>
<p>Once the installation has been completed, you can now open the folder in VsCode by using the command below or locate the folder in your file manager and open it directly from there.</p>
<pre><code class="lang-plaintext">code .
</code></pre>
<p>Our project should now look like this now:</p>
<p><img src="https://lh5.googleusercontent.com/jouRdSMQkxGTLkNCPzBLt03gXJ-0Nolqg02hYu7kpQIOrakEkctzUm7UHHofXz_aP_5LZ5xxuT_6wmR-0Ih1duMxO4pA2artHAG3tVHbg_0LoZG2Stnu5HCHux5oBs3EhlGfdYQ_5gbbeQH1SeIpDMU5iL1-Sf3jyReaYkR_xJfXekZ98_F06Z5j1A0czg" alt /></p>
<h2 id="heading-adding-the-widget-functionality">Adding the widget functionality</h2>
<p>Now, go inside the <code>main.js</code> file and delete any code we have in there, the same applies to the <code>counter.js</code> file, delete all code in there and rename the file to <code>asset.js</code>, we’ll be using it later in the tutorial.</p>
<p>Paste in the following code block inside our main.js file:</p>
<pre><code class="lang-plaintext">class MessageWidget {
  constructor(position = "bottom-right") {
    this.position = this.getPosition(position);
    this.open = false;
    this.initialize();
    this.injectStyles();
  }

  position = "";
  open = false;
  widgetContent = null;  
}
</code></pre>
<p>We’ll be using a Javascript Class to encapsulate most of our logic for the widget. The <code>constructor()</code> method is automatically invoked whenever a new instance of our <code>MessageWidget</code> is instantiated. Our class accepts a position parameter that would be used to determine the widget's position in the DOM. We’ve assigned a default parameter for our position argument, hence, it’s not a requirement when the class is being instantiated.</p>
<p>We’re also setting some properties and invoking some methods inside the constructor, we’ll be creating them later on as we move. However, here are their responsibilities:</p>
<ul>
<li><p><strong>position</strong>  - Used to save the position of the widget in the DOM.</p>
</li>
<li><p><strong>open</strong> - Used to toggle the state of our widget i.e Open or Closed.</p>
</li>
<li><p><strong>widgetContainer</strong> - HTML element for our widget.</p>
</li>
<li><p><strong>initialize()</strong>  - Invoked to display and create the UI for our widget in the DOM.</p>
</li>
<li><p><strong>injectStyles()</strong> - Invoked to add the styling for our widget.</p>
</li>
</ul>
<p>Continuing, let’s create the methods we’ve used above. To do this, copy the code snippet below and paste it below the constructor:</p>
<pre><code class="lang-plaintext">import { CLOSE_ICON, MESSAGE_ICON, styles } from "./assets.js";

class MessageWidget {
  constructor(position = "bottom-right") { ... }

  position = "";
  open = false;
  widgetContainer = null;

  getPosition(position) {
    const [vertical, horizontal] = position.split("-");
    return {
      [vertical]: "30px",
      [horizontal]: "30px",
    };
  }

  async initialize() {
    /**
     * Create and append a div element to the document body
     */
    const container = document.createElement("div");
    container.style.position = "fixed";
    Object.keys(this.position).forEach(
      (key) =&gt; (container.style[key] = this.position[key])
    );
    document.body.appendChild(container);

    /**
     * Create a button element and give it a class of button__container
     */
    const buttonContainer = document.createElement("button");
    buttonContainer.classList.add("button__container");

    /**
     * Create a span element for the widget icon, give it a class of `widget__icon`, and update its innerHTML property to an icon that would serve as the widget icon.
     */
    const widgetIconElement = document.createElement("span");
    widgetIconElement.innerHTML = MESSAGE_ICON;
    widgetIconElement.classList.add("widget__icon");
    this.widgetIcon = widgetIconElement;

    /**
     * Create a span element for the close icon, give it a class of `widget__icon` and `widget__hidden` which would be removed whenever the widget is closed, and update its innerHTML property to an icon that would serve as the widget icon during that state.
     */
    const closeIconElement = document.createElement("span");
    closeIconElement.innerHTML = CLOSE_ICON;
    closeIconElement.classList.add("widget__icon", "widget__hidden");
    this.closeIcon = closeIconElement;

    /**
     * Append both icons created to the button element and add a `click` event listener on the button to toggle the widget open and close.
     */
    buttonContainer.appendChild(this.widgetIcon);
    buttonContainer.appendChild(this.closeIcon);
    buttonContainer.addEventListener("click", this.toggleOpen.bind(this));

    /**
     * Create a container for the widget and add the following classes:- `widget__hidden`, `widget__container`
     */
    this.widgetContainer = document.createElement("div");
    this.widgetContainer.classList.add("widget__hidden", "widget__container");

    /**
     * Invoke the `createWidget()` method
     */
    this.createWidgetContent();

    /**
     * Append the widget's content and the button to the container
     */
    container.appendChild(this.widgetContainer);
    container.appendChild(buttonContainer);
  }

  createWidgetContent() {
    this.widgetContainer.innerHTML = `
        &lt;header class="widget__header"&gt;
            &lt;h3&gt;Start a conversation&lt;/h3&gt;
            &lt;p&gt;We usually respond within a few hours&lt;/p&gt;
        &lt;/header&gt;
        &lt;form&gt;
            &lt;div class="form__field"&gt;
                &lt;label for="name"&gt;Name&lt;/label&gt;
                &lt;input
                  type="text"
                  id="name"
                  name="name"
                  placeholder="Enter your name"
                /&gt;
            &lt;/div&gt;
            &lt;div class="form__field"&gt;
                &lt;label for="email"&gt;Email&lt;/label&gt;
                &lt;input
                  type="email"
                  id="email"
                  name="email"
                  placeholder="Enter your email"
                /&gt;
            &lt;/div&gt;
            &lt;div class="form__field"&gt;
                &lt;label for="subject"&gt;Subject&lt;/label&gt;
                &lt;input
                  type="text"
                  id="subject"
                  name="subject"
                  placeholder="Enter Message Subject"
                /&gt;
            &lt;/div&gt;
            &lt;div class="form__field"&gt;
                &lt;label for="message"&gt;Message&lt;/label&gt;
                &lt;textarea
                  id="message"
                  name="message"
                  placeholder="Enter your message"
                  rows="6"
                &gt;&lt;/textarea&gt;
            &lt;/div&gt;
            &lt;button&gt;Send Message&lt;/button&gt;
        &lt;/form&gt;
    `;
  }

  injectStyles() {
    const styleTag = document.createElement("style");
    styleTag.innerHTML = styles.replace(/^\s+|\n/gm, "");
    document.head.appendChild(styleTag);
  }

  toggleOpen() {
    this.open = !this.open;
    if (this.open) {
      this.widgetIcon.classList.add("widget__hidden");
      this.closeIcon.classList.remove("widget__hidden");
      this.widgetContainer.classList.remove("widget__hidden");
    } else {
      this.createWidgetContent();
      this.widgetIcon.classList.remove("widget__hidden");
      this.closeIcon.classList.add("widget__hidden");
      this.widgetContainer.classList.add("widget__hidden");
    }
  }
}
</code></pre>
<p>The code snippet adds the three methods in our class, namely:</p>
<ul>
<li><p><strong>getPosition()</strong> - used to generate the numerical positions of the widget in the DOM</p>
</li>
<li><p><strong>createWidgetContent()</strong> - used to generate the HTML content for our widget</p>
</li>
<li><p><strong>initialize()</strong> - responsible for displaying and creating the UI for our widget in the DOM. I’ve added short comments in the body of the method to explain what’s being done in each step.</p>
</li>
<li><p><strong>injectStyles()</strong> - responsible for injecting the HTML stylings for the widget inside the page’s document.</p>
</li>
</ul>
<h2 id="heading-adding-our-styling">Adding our styling</h2>
<p>The next thing we are going to do is add our styling and assets to the <code>asset.js</code> file we created earlier. Paste in the following code inside <code>asset.js</code>:</p>
<pre><code class="lang-plaintext">export const styles = `
    .widget__container * {
        box-sizing: border-box;
    }        
    h3, p, input {
        margin: 0;
        padding: 0;
    }
    .widget__container {
        box-shadow: 0 0 18px 8px rgba(0, 0, 0, 0.1), 0 0 32px 32px rgba(0, 0, 0, 0.08);
        width: 400px;
        overflow: auto;
        right: -25px;
        bottom: 75px;
        position: absolute;
        transition: max-height .2s ease;
        font-family: Helvetica, Arial ,sans-serif;
        background-color: #e6e6e6a6;
        border-radius: 10px;
        box-sizing: border-box;
    }
    .widget__icon {
        cursor: pointer;
        width: 60%;
        position: absolute;
        top: 18px;
        left: 16px;
        transition: transform .3s ease;
    }
    .widget__hidden {
        transform: scale(0);
    }
    .button__container {
        border: none;
        background-color: #0f172a;
        width: 60px;
        height: 60px;
        border-radius: 50%;
        cursor: pointer;
    }
    .widget__container.hidden {
        max-height: 0px;
    }
    .widget__header {
        padding: 1rem 2rem 1.5rem;
        background-color: #000;
        color: #fff;
        border-top-left-radius: 10px;
        border-top-right-radius: 10px;
        text-align: center;
    }
    .widget__header h3 {
        font-size: 24px;
        font-weight: 400;
        margin-bottom: 8px;
    }
    form {
        padding: 2rem 1rem 1.5rem;
    }
    form .form__field {
        margin-bottom: 1.5rem;
        display: flex;
        flex-direction: column;
    }
    .form__field label {
        margin-bottom: 8px;
        font-size: 14px;
    }
    .form__field input,
    .form__field textarea {
        border: 1px solid #000000ad;
        border-radius: 3px;
        padding: 8px 10px;
        background-color: #fff;
    }
    .form__field input {
        height: 48px;
    }
    .form__field textarea::placeholder {
        font-family: Helvetica, Arial ,sans-serif;
    }
    form button {
        height: 48px;
        border-radius: 6px;
        font-size: 18px;
        background-color: #000;
        color: #fff;
        border: 0;
        width: 100%;
        cursor: pointer;
    }
    form button:hover {
        background-color: rgba(0, 0, 0, 95%);
    }
`;

export const MESSAGE_ICON = `
    &lt;svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-mail"&gt;
        &lt;path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"&gt;&lt;/path&gt;
        &lt;polyline points="22,6 12,13 2,6"&gt;&lt;/polyline&gt;
    &lt;/svg&gt;
`;

export const CLOSE_ICON = `
    &lt;svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x"&gt;
        &lt;line x1="18" y1="6" x2="6" y2="18"&gt;&lt;/line&gt;
        &lt;line x1="6" y1="6" x2="18" y2="18"&gt;&lt;/line&gt;
    &lt;/svg&gt;
`;
</code></pre>
<p>This contains the styling for our messaging widget and the icons used in the widget. We’ll need to import them inside our main.js file, and paste the code below at the beginning of our file:</p>
<pre><code class="lang-plaintext">import { styles, CLOSE_ICON, MESSAGE_ICON } from "./assets.js";
</code></pre>
<p>The last thing for us is to create a function to initialize our MessagingWidget. The function created returns a new instance of the MessagingWidget every time it’s invoked.</p>
<p>To do this, copy the code snippet below and paste it below the constructor.</p>
<pre><code class="lang-plaintext">class MessagingWidget { ... }

function initializeWidget() {
  return new MessageWidget();
}

initializeWidget();
</code></pre>
<h2 id="heading-testing-our-widget">Testing our widget</h2>
<p>Now, save all changes and paste the code below in your terminal to start a development server:</p>
<pre><code class="lang-plaintext">yarn dev
</code></pre>
<p>Then, open the generated port in your browser and you should have the following result:</p>
<p><img src="https://lh6.googleusercontent.com/yKa0pV68XrXFIcW2Cr2HkmO4KuhgXqervfGNbPCiDVSt3bGrtP-Lyom-ylqTNMs-Ed2ourPsv_LwekuPjdpG_D8X1RQfur4ouXrcVxEZcu9EFDJSynQldPD_0Tp3RugGJ0Ghrzg6_dn6_aWttNDYCjuQabHCGHikAhIwaPnerCOHzkcNCpyvq3lHuwWw4A" alt /></p>
<p>Congratulations🎉, you now have a working widget. Hmm🤔…Wait a minute, remember I mentioned at the beginning, a widget can work on any website that it’s installed, how do we now make our widget installable and available to everyone?</p>
<h2 id="heading-connecting-our-widget-to-a-cdn">Connecting our widget to a CDN</h2>
<p>We’ll need to deploy our code to <a target="_blank" href="https://github.com">GitHub</a> or <a target="_blank" href="https://www.npmjs.com">npm</a> and then connect it to a <a target="_blank" href="https://www.cloudflare.com/en-gb/learning/cdn/what-is-a-cdn">CDN</a> (Content Delivery Network) so that we can have a link that can be shareable anywhere in the world. That’s not all! For the widget to be installed on a website, we’ll also need to have documentation or instruction which people can follow for them to perform the installation.</p>
<p>In our case, we'll be deploying our code to GitHub and connecting it to <a target="_blank" href="https://www.jsdelivr.com/github">JsDelivr</a> so that we can get our code on a CDN. There are many popular CDNs out there like <a target="_blank" href="https://www.cloudflare.com/">Cloudflare</a>, <a target="_blank" href="https://www.jsdelivr.com">JsDelivr</a>, <a target="_blank" href="https://raw.githack.com">RawCDN</a>, etc. so feel free to choose anyone you find interesting.</p>
<p>To deploy your code online, create a repository on GitHub and push your code there. Once your code is already on GitHub, copy the link to the Javascript file, we’ll be needing it in a bit when we’re on JsDelivr.</p>
<p><img src="https://lh5.googleusercontent.com/vj6Yrd2nX9qXbdZtv0_AX6bGSGzR83jpHAtpIJlRqy-NICaYAF1NjhgpjuKH6u0-Q43P4_Tlf4cQDApJHd9NTy5Xnk6HQVqf8QYi7t6PMlk-OaYjpTcZIF2kcE31-yd8O-SqFN07f69608yOp1SsK8vdOzxoMswaobBgzFWuoBi-Xu_WhszZETvIqO2VNQ" alt /></p>
<p>Now, head on to <a target="_blank" href="https://www.jsdelivr.com/github">JsDelivr</a> and paste the link in the input element labeled GitHub. A new CDN link would be generated for you which can be used to access the code for the widget anywhere in the world.</p>
<p><img src="https://lh5.googleusercontent.com/4uy_FubIrtX8rBpkG94-3r9tjdsWfrrgc2L3ARs04z-sneDVNs9Op7a9Jb-h6XpxO-x62Ge5lb1b3T5S7fhzCPJJL_X6JLWuyVagn6IgUM2LCgYWwwPPAp4a6rQmFtnxjK2tcLf3ec9fVVsuIqCymba5IXaXaSvBTzqkuBzgnM1Qw1a2fpMrtgqGBnJQkQ" alt /></p>
<h2 id="heading-creating-an-instruction-for-installation">Creating an instruction for installation</h2>
<p>Having a straightforward method for installing your widgets is one of the things that need to be covered when building one. There are many methods or processes for installing widgets on websites. It all depends on who the widget is being created for. For example, if the users of the widget are developers, then they might need to install an SDK or a library for them to get started with it. However, the majority of widgets are created for non-technical users, hence, one of the most popular methods is creating a <strong>copy-paste</strong> code block that they can copy and paste into their sites instantly.</p>
<p>One other advantage of using a CDN is <a target="_blank" href="https://www.cloudflare.com/en-gb/learning/performance/why-minify-javascript-code">Minification</a><strong>.</strong> This helps us minify our code and remove all unnecessary space and characters in it thereby reducing the overall size and improving its load time. JsDelivr helps with this if the <code>.min</code>  suffix is added to the URL.</p>
<p>In our case, we can create a script tag that can be copied by anyone interested in making use of our Messaging Widget. It would look like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Copy the code below and paste it into the body of your website.</span>
&lt;script type=<span class="hljs-string">"module"</span> src=<span class="hljs-string">"https://cdn.jsdelivr.net/gh/Young-Einstein10/messaging-widget@main/main.min.js"</span>&gt;&lt;/script&gt;
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we’ve learned how to build a simple messaging widget with HTML, CSS, and Javascript. We also talked about CDNs and how they can be used to make our code available to everyone across the world.</p>
<p>I hope you’ve found  this tutorial helpful. Feel free to reach out to me via <a target="_blank" href="https://www.linkedin.com/in/abdulrahman-yusuf-a44463176/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/zaydabdulrahman">Twitter</a> if there are any questions.</p>
<p>You can find the complete code for the tutorial on <a target="_blank" href="https://github.com/Young-Einstein10/messaging-widget">GitHub</a>.</p>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><p><a target="_blank" href="https://www.groovehq.com/blog/what-is-web-widget#:~:text=A%20web%20widget%20is%20a,framework%20of%20your%20website%20host.">How We Reduced Support Volume by 33% Using a Web Widget</a>, Groove Blog</p>
</li>
<li><p><a target="_blank" href="https://www.strikingly.com/content/blog/website-widgets-what-are-they-and-why-do-i-need-them">Website Widgets: What Are They and Why Do I Need Them?</a> The Strikingly Blog</p>
</li>
<li><p><a target="_blank" href="https://www.cloudflare.com/en-gb/learning/cdn/what-is-a-cdn/">What is a CDN?</a> Cloudflare</p>
</li>
<li><p><a target="_blank" href="https://javascript.info/class">Javascript Classes</a>, <a target="_blank" href="http://Javascript.Info">Javascript.Info</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Setting up Internationalization in React using react-18next 🇺🇸🇫🇷]]></title><description><![CDATA[Nowadays, websites and applications can be accessed from different parts and regions of the world. So, it is very essential to make your website easily accessible to anyone regardless of their location.
In this article, I’ll share the importance of i...]]></description><link>https://blog.abdulyusuf.me/setting-up-internationalization-in-react-using-react-18next</link><guid isPermaLink="true">https://blog.abdulyusuf.me/setting-up-internationalization-in-react-using-react-18next</guid><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[internationalization]]></category><category><![CDATA[language]]></category><dc:creator><![CDATA[Abdulrahman Yusuf]]></dc:creator><pubDate>Wed, 23 Nov 2022 10:44:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1669198706646/9g0VUPQXn.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Nowadays, websites and applications can be accessed from different parts and regions of the world. So, it is very essential to make your website easily accessible to anyone regardless of their location.</p>
<p>In this article, I’ll share the importance of internationalization and how to set up internationalization in a ReactJS application.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>This tutorial assumes the reader has the following:</p>
<ol>
<li><a target="_blank" href="https://nodejs.org/">Node</a> installed on their local machine</li>
<li><a target="_blank" href="https://yarnpkg.com/">yarn</a> or <a target="_blank" href="https://www.npmjs.com">npm</a> installed on their local machine (npm comes pre-installed with node)</li>
<li>Basic knowledge of HTML, CSS, Javascript and React.</li>
</ol>
<hr />
<h2 id="heading-what-is-internationalization">What is Internationalization?</h2>
<p>Before we proceed, let’s first understand the meaning of Internationalization!</p>
<p>According to <a target="_blank" href="https://en.wikipedia.org/wiki/Internationalization_and_localization">Wikipedia</a>, Internationalization is the process of designing a software application so that it can be adapted to various languages and regions without engineering changes.</p>
<p>Basically, Internationalization is the process of making your website or applications usable by all people irrespective of the country or region they find themselves. There are so many benefits of internationalization, but here are some of my favourites:</p>
<ul>
<li>It helps in customer and user retention, which leads to an increase in overall customer satisfaction.</li>
<li>It saves time and cost as you don’t have to develop a separate website for people in separate regions.</li>
<li>It makes maintenance of the website easier.</li>
</ul>
<h2 id="heading-getting-started">Getting Started</h2>
<p>For this tutorial, I’ve created a simple login page which we’ll be using to set up internationalization in our app. You can find and clone the project to your machine using this <a target="_blank" href="https://github.com/Young-Einstein10/internationalization-in-react">Github Link</a>.</p>
<p>There are so many tools out there that can be used to set up internationalization, but we’ll be using react-18next due to its ease of setup and the vast amount of plugins that can be integrated into it.</p>
<h2 id="heading-installing-dependencies">Installing Dependencies</h2>
<p>Let’s start by installing react-18next and a plugin in our project using the command below:</p>
<pre><code>yarn add react-i18next i18next i18next-browser-languagedetector
</code></pre><p>I’ll be explaining what the plugin is for in the coming section.</p>
<h2 id="heading-setting-up-react-i18next">Setting up react-i18next</h2>
<p>After the installation is completed, we need to set up some configurations for <code>react-18next</code> before we can begin using it. For that, create a file named <code>i18n.js</code> in your src directory and paste the code snippet below:</p>
<pre><code><span class="hljs-comment">// i18n.js</span>

<span class="hljs-keyword">import</span> i18n <span class="hljs-keyword">from</span> <span class="hljs-string">"i18next"</span>;
<span class="hljs-keyword">import</span> { initReactI18next } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-i18next"</span>;

i18n
  .use(initReactI18next) <span class="hljs-comment">// passes i18n down to react-i18next</span>
  .init({
    <span class="hljs-attr">resources</span>: {},
    <span class="hljs-attr">lng</span>: <span class="hljs-string">"en"</span>,
    <span class="hljs-attr">keySeparator</span>: <span class="hljs-string">"."</span>,
  });

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> i18n;
</code></pre><p>Here, we imported the <code>i18n</code> instance and <code>initReactI18next</code> from i18next and react-i18next respectively. We then went on to initialize the instance by adding other parameters needed for configuration.</p>
<p>Next, we need to create a new directory called <code>locales</code>, this directory would contain all our translations for different regions or languages that our application uses. For this tutorial, we’ll be sticking with two languages, mainly English and French. The <code>locales</code> directory would contain the translation files for our respective locale like so:-</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_6CEBE7963D9F76707C361DE28554CD96EDC2B57BA0C4F761180E25A1B8798855_1668407798184_Screenshot+2022-11-14+at+07.36.07.png" alt /></p>
<h2 id="heading-adding-our-locales">Adding our locales</h2>
<p>Paste the code snippet below into the English locale</p>
<pre><code>{
    <span class="hljs-string">"login"</span>: {
        <span class="hljs-string">"heading"</span>: <span class="hljs-string">"Login to your account"</span>,
        <span class="hljs-string">"submit"</span>: <span class="hljs-string">"Login"</span>,
        <span class="hljs-string">"input"</span>: {
            <span class="hljs-string">"email"</span>: <span class="hljs-string">"Email"</span>,
            <span class="hljs-string">"emailPlaceholder"</span>: <span class="hljs-string">"Email Placeholder"</span>,
            <span class="hljs-string">"password"</span>: <span class="hljs-string">"Password"</span>,
            <span class="hljs-string">"passwordPlaceholder"</span>: <span class="hljs-string">"Password Placeholder"</span>,
            <span class="hljs-string">"toggle_password"</span>: <span class="hljs-string">"Toggle Password"</span>
        },
        <span class="hljs-string">"errors"</span>: {
            <span class="hljs-string">"email"</span>: <span class="hljs-string">"Email is required"</span>,
            <span class="hljs-string">"password"</span>: <span class="hljs-string">"Password is required"</span>,
            <span class="hljs-string">"passwordLength"</span>: <span class="hljs-string">"Password length should be at least 6 characters"</span>
        },
        <span class="hljs-string">"forgot_password"</span>: <span class="hljs-string">"Forgot Password"</span>
    }
}
</code></pre><p>Paste the code snippet below into the French locale</p>
<pre><code>{
    <span class="hljs-string">"login"</span>: {
        <span class="hljs-string">"heading"</span>: <span class="hljs-string">"Connectez-vous à votre compte"</span>,
        <span class="hljs-string">"submit"</span>: <span class="hljs-string">"connexion"</span>,
        <span class="hljs-string">"input"</span>: {
            <span class="hljs-string">"email"</span>: <span class="hljs-string">"E-mail"</span>,
            <span class="hljs-string">"emailPlaceholder"</span>: <span class="hljs-string">"Espace réservé d'e-mail"</span>,
            <span class="hljs-string">"password"</span>: <span class="hljs-string">"Mot de passe"</span>,
            <span class="hljs-string">"passwordPlaceholder"</span>: <span class="hljs-string">"Espace réservé pour le mot de passe"</span>,
            <span class="hljs-string">"toggle_password"</span>: <span class="hljs-string">"basculer le mot de passe"</span>
        },
        <span class="hljs-string">"errors"</span>: {
            <span class="hljs-string">"email"</span>: <span class="hljs-string">"L'e-mail est requis"</span>,
            <span class="hljs-string">"password"</span>: <span class="hljs-string">"Mot de passe requis"</span>,
            <span class="hljs-string">"passwordLength"</span>: <span class="hljs-string">"La longueur du mot de passe doit être d'au moins 6 caractères"</span>
        },
        <span class="hljs-string">"forgot_password"</span>: <span class="hljs-string">"Mot de passe oublié"</span>
    }
}
</code></pre><p>The translations are represented in a key-value pair which allows us to manage the text for different parts of our app in an efficient manner. The keys would later be referenced when we want to set up dynamic translations in our components.</p>
<p>Now that we have the translations for our locales, we need to import them inside our <code>i18n.js file</code> and include it in the resources property like this:</p>
<pre><code><span class="hljs-keyword">import</span> i18n <span class="hljs-keyword">from</span> <span class="hljs-string">"i18next"</span>;
<span class="hljs-keyword">import</span> { initReactI18next } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-i18next"</span>;
<span class="hljs-keyword">import</span> EN_TRANSLATION <span class="hljs-keyword">from</span> <span class="hljs-string">"./locales/en/translation.json"</span>;
<span class="hljs-keyword">import</span> FR_TRANSLATION <span class="hljs-keyword">from</span> <span class="hljs-string">"./locales/fr/translation.json"</span>;

i18n
  .use(initReactI18next)
  .init({
    <span class="hljs-attr">resources</span>: {
      <span class="hljs-attr">en</span>: {
        <span class="hljs-attr">translation</span>: EN_TRANSLATION,
      },
      <span class="hljs-attr">fr</span>: {
        <span class="hljs-attr">translation</span>: FR_TRANSLATION,
      },
    },
    <span class="hljs-attr">lng</span>: <span class="hljs-string">"en"</span>,
    <span class="hljs-attr">keySeparator</span>: <span class="hljs-string">"."</span>,
  });

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> i18n;
</code></pre><p>Now that we have our i18n.js file set up, we need to import the <code>i18n</code> instance we just configured in app.js so that it can get bundled during compilation. Import i18n.js below in your <code>app.js</code> file like this:</p>
<pre><code><span class="hljs-keyword">import</span> {
  Center,
  ChakraProvider,
  Flex,
  Heading,
  Select,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;
<span class="hljs-keyword">import</span> Login <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/login"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./i18n"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ChakraProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Flex</span>
        <span class="hljs-attr">as</span>=<span class="hljs-string">"nav"</span>
        <span class="hljs-attr">mx</span>=<span class="hljs-string">"5rem"</span>
        <span class="hljs-attr">height</span>=<span class="hljs-string">"80px"</span>
        <span class="hljs-attr">justifyContent</span>=<span class="hljs-string">"space-between"</span>
        <span class="hljs-attr">alignItems</span>=<span class="hljs-string">"center"</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h4"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"md"</span>&gt;</span>
          Logo
        <span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Select</span>
          <span class="hljs-attr">width</span>=<span class="hljs-string">"150px"</span>
          <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{i18n.language}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleSelectChange}</span>
        &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"en"</span>&gt;</span>English<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"fr"</span>&gt;</span>French<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Select</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Flex</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Center</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"calc(100vh - 80px)"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Login</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Center</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraProvider</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre><p>Save the changes and view them in the browser.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_6CEBE7963D9F76707C361DE28554CD96EDC2B57BA0C4F761180E25A1B8798855_1668409787616_Screenshot+2022-11-14+at+08.08.36.png" alt /></p>
<h2 id="heading-using-the-translations-in-our-components">Using the translations in our components</h2>
<p>Now that our app works and we’ve set up react-i18next, we need to make use of the translations in our components in order for them to dynamically change to their respective locales depending on the region the user is in.</p>
<p><code>react-i18next</code> offers us three different methods for accessing translations, namely:</p>
<ol>
<li>Using the <code>useTranslation</code> hook</li>
<li>Using the <code>withTranslation</code> HOC</li>
<li>Using the <code>Translation</code> render prop</li>
</ol>
<p><strong>Using the</strong> <code>useTranslation</code> <strong>hook</strong></p>
<p>The <code>t</code> function is the main function in <code>i18next</code> to translate content. We’ll be importing the <code>useTranslation</code> hook from react-i18next which allows us to destructure the <code>t</code> function from the hook. Add the lines of code below in our <code>login.js</code> file.</p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> {
  Box,
  Flex,
  Button,
  Heading,
  FormControl,
  Input,
  FormLabel,
  FormErrorMessage,
  Link <span class="hljs-keyword">as</span> ChakraLink,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
<span class="hljs-keyword">import</span> PasswordInput <span class="hljs-keyword">from</span> <span class="hljs-string">"./passwordInput"</span>;
<span class="hljs-keyword">import</span> { useTranslation } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-i18next"</span>;


<span class="hljs-keyword">const</span> Login = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { t } = useTranslation();
  <span class="hljs-keyword">const</span> {
    handleSubmit,
    register,
    <span class="hljs-attr">formState</span>: { errors, isSubmitting },
  } = useForm();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">values</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
      <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        alert(<span class="hljs-built_in">JSON</span>.stringify(values, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>));
        resolve();
      }, <span class="hljs-number">3000</span>);
    });
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Box</span> <span class="hljs-attr">maxW</span>=<span class="hljs-string">"400px"</span> <span class="hljs-attr">w</span>=<span class="hljs-string">"full"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span>
        <span class="hljs-attr">fontWeight</span>=<span class="hljs-string">{700}</span>
        <span class="hljs-attr">fontSize</span>=<span class="hljs-string">"24px"</span>
        <span class="hljs-attr">fontFamily</span>=<span class="hljs-string">"Source Sans Pro"</span>
        <span class="hljs-attr">mb</span>=<span class="hljs-string">{10}</span>
        <span class="hljs-attr">textAlign</span>=<span class="hljs-string">"center"</span>
      &gt;</span>
        {t("login.heading")}
      <span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(onSubmit)}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Box</span> <span class="hljs-attr">p</span>=<span class="hljs-string">{4}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">FormControl</span> <span class="hljs-attr">mb</span>=<span class="hljs-string">{6}</span> <span class="hljs-attr">isInvalid</span>=<span class="hljs-string">{errors.email}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FormLabel</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"#100B05"</span> <span class="hljs-attr">fontSize</span>=<span class="hljs-string">"14px"</span>&gt;</span>
              {t("login.input.email")}
            <span class="hljs-tag">&lt;/<span class="hljs-name">FormLabel</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{t(</span>"<span class="hljs-attr">login.input.emailPlaceholder</span>")}
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">email</span>", {
                <span class="hljs-attr">required:</span> <span class="hljs-attr">t</span>("<span class="hljs-attr">login.errors.email</span>"),
              })}
              <span class="hljs-attr">isRequired</span>
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FormErrorMessage</span>&gt;</span>
              {errors.email &amp;&amp; errors.email.message}
            <span class="hljs-tag">&lt;/<span class="hljs-name">FormErrorMessage</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">FormControl</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">FormControl</span> <span class="hljs-attr">mb</span>=<span class="hljs-string">{2}</span> <span class="hljs-attr">isInvalid</span>=<span class="hljs-string">{errors.password}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FormLabel</span> <span class="hljs-attr">htmlFor</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"#100B05"</span> <span class="hljs-attr">fontSize</span>=<span class="hljs-string">"14px"</span>&gt;</span>
              {t("login.input.password")}
            <span class="hljs-tag">&lt;/<span class="hljs-name">FormLabel</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">PasswordInput</span> <span class="hljs-attr">register</span>=<span class="hljs-string">{register}</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">FormErrorMessage</span>&gt;</span>
              {errors.password &amp;&amp; errors.password.message}
            <span class="hljs-tag">&lt;/<span class="hljs-name">FormErrorMessage</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">FormControl</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Flex</span> <span class="hljs-attr">justify</span>=<span class="hljs-string">"flex-end"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ChakraLink</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"brand"</span> <span class="hljs-attr">fontSize</span>=<span class="hljs-string">"sm"</span>&gt;</span>
              {t("login.forgot_password")}
            <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraLink</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Flex</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
            <span class="hljs-attr">mt</span>=<span class="hljs-string">{10}</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>
            <span class="hljs-attr">colorScheme</span>=<span class="hljs-string">"teal"</span>
            <span class="hljs-attr">w</span>=<span class="hljs-string">"full"</span>
            <span class="hljs-attr">isLoading</span>=<span class="hljs-string">{isSubmitting}</span>
          &gt;</span>
            {t("login.submit")}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Login;
</code></pre><p><strong>Using the</strong> <code>withTranslation</code> <strong>HOC</strong></p>
<p><code>react-i18next</code> also offers a HOC that can be used for situations where the hook isn’t the preferred style. Add the code below in our <code>passwordInput.js</code> file.</p>
<pre><code><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> {
  Input,
  InputGroup,
  IconButton,
  InputRightElement,
  useDisclosure,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;
<span class="hljs-keyword">import</span> { ViewIcon, ViewOffIcon } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/icons"</span>;
<span class="hljs-keyword">import</span> { withTranslation } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-i18next"</span>;

<span class="hljs-keyword">const</span> PasswordInput = <span class="hljs-function">(<span class="hljs-params">{ register, t }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> { isOpen, onToggle } = useDisclosure();
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">InputGroup</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
        <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">{isOpen</span> ? "<span class="hljs-attr">text</span>" <span class="hljs-attr">:</span> "<span class="hljs-attr">password</span>"}
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">{t(</span>"<span class="hljs-attr">login.input.passwordPlaceholder</span>")}
        {<span class="hljs-attr">...register</span>("<span class="hljs-attr">password</span>", {
          <span class="hljs-attr">required:</span> <span class="hljs-attr">t</span>("<span class="hljs-attr">login.errors.password</span>"),
          <span class="hljs-attr">minLength:</span> {
            <span class="hljs-attr">value:</span> <span class="hljs-attr">6</span>,
            <span class="hljs-attr">message:</span> <span class="hljs-attr">t</span>("<span class="hljs-attr">login.errors.passwordLength</span>"),
          },
        })}
        <span class="hljs-attr">isRequired</span>
      /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">InputRightElement</span> <span class="hljs-attr">h</span>=<span class="hljs-string">"full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">IconButton</span>
          <span class="hljs-attr">bg</span>=<span class="hljs-string">"none"</span>
          <span class="hljs-attr">width</span>=<span class="hljs-string">"32px"</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onToggle}</span>
          <span class="hljs-attr">height</span>=<span class="hljs-string">"40px"</span>
          <span class="hljs-attr">aria-label</span>=<span class="hljs-string">{t(</span>"<span class="hljs-attr">login.input.toggle_password</span>")}
          <span class="hljs-attr">icon</span>=<span class="hljs-string">{</span>
            <span class="hljs-attr">isOpen</span> ? (
              &lt;<span class="hljs-attr">ViewIcon</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{18}</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"#B8B8B8"</span> /&gt;</span>
            ) : (
              <span class="hljs-tag">&lt;<span class="hljs-name">ViewOffIcon</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{18}</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"#B8B8B8"</span> /&gt;</span>
            )
          }
          _hover={{
            bg: "none",
          }}
          _active={{
            bg: "none",
          }}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">InputRightElement</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">InputGroup</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> withTranslation()(PasswordInput);
</code></pre><p>Save the changes and check the result in the browser.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_6CEBE7963D9F76707C361DE28554CD96EDC2B57BA0C4F761180E25A1B8798855_1668532736711_Screenshot+2022-11-14+at+08.08.36.png" alt /></p>
<h2 id="heading-language-switcher">Language Switcher</h2>
<p>Now, we’ll notice when we change the language in the select dropdown nothing happens, that’s because we need to create a <code>handleChangeLanguage</code> function that handles changing the user language whenever the language is changed. Add the function below to our <code>i18n.js</code> file</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handleChangeLanguage = <span class="hljs-keyword">async</span> (language = <span class="hljs-string">"en"</span>) =&gt; {
  <span class="hljs-keyword">await</span> i18n.changeLanguage(
    language,
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Language Changed to: "</span> + language)
  );
};
</code></pre><p>Next, import the function in <code>app.js</code>, then add it to the <code>onChange</code> handler for the select component used in changing the language. We’ll also need to import the <code>i18n.js</code> instance in order for us to access the current language and use it as a default value for the dropdown.</p>
<pre><code><span class="hljs-keyword">import</span> {
  Center,
  ChakraProvider,
  Flex,
  Heading,
  Select,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;
<span class="hljs-keyword">import</span> Login <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/login"</span>;
<span class="hljs-keyword">import</span> i18n, { handleChangeLanguage } <span class="hljs-keyword">from</span> <span class="hljs-string">"./i18n"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./i18n"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> handleSelectChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span>
    handleChangeLanguage(event.target.value);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ChakraProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Flex</span>
        <span class="hljs-attr">as</span>=<span class="hljs-string">"nav"</span>
        <span class="hljs-attr">mx</span>=<span class="hljs-string">"5rem"</span>
        <span class="hljs-attr">height</span>=<span class="hljs-string">"80px"</span>
        <span class="hljs-attr">justifyContent</span>=<span class="hljs-string">"space-between"</span>
        <span class="hljs-attr">alignItems</span>=<span class="hljs-string">"center"</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"h4"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"md"</span>&gt;</span>
          Logo
        <span class="hljs-tag">&lt;/<span class="hljs-name">Heading</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Select</span>
          <span class="hljs-attr">width</span>=<span class="hljs-string">"150px"</span>
          <span class="hljs-attr">defaultValue</span>=<span class="hljs-string">{i18n.language}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleSelectChange}</span>
        &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"en"</span>&gt;</span>English<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"fr"</span>&gt;</span>French<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Select</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Flex</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Center</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"calc(100vh - 80px)"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Login</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Center</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraProvider</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre><p>Now, when you save the changes and change the language in the browser, we’ll notice the language changes as expected.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_6CEBE7963D9F76707C361DE28554CD96EDC2B57BA0C4F761180E25A1B8798855_1668410454712_Screenshot+2022-11-14+at+08.20.48.png" alt /></p>
<h2 id="heading-plugins">Plugins</h2>
<p>One other cool feature react-i18next offers is the use of different plugins that can be added to the <code>i18n</code> instance during initialization. One popular plugin is the <code>i18next-browser-languagedetector</code> which can be used to automatically detect the language of the user based on the browser’s locale. In this case, we don’t have to hardcode the language to the English locale all the time, we can make it dynamic so that the user’s locale is selected when needed. For us to add this plugin to the <code>i18n</code> instance, we’ll need to import it below and also make some changes to our configurations:</p>
<pre><code><span class="hljs-keyword">import</span> i18n <span class="hljs-keyword">from</span> <span class="hljs-string">"i18next"</span>;
<span class="hljs-keyword">import</span> { initReactI18next } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-i18next"</span>;
<span class="hljs-keyword">import</span> EN_TRANSLATION <span class="hljs-keyword">from</span> <span class="hljs-string">"./locales/en/translation.json"</span>;
<span class="hljs-keyword">import</span> FR_TRANSLATION <span class="hljs-keyword">from</span> <span class="hljs-string">"./locales/fr/translation.json"</span>;
<span class="hljs-keyword">import</span> LanguageDetector <span class="hljs-keyword">from</span> <span class="hljs-string">"i18next-browser-languagedetector"</span>;

i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    <span class="hljs-attr">resources</span>: {
      <span class="hljs-attr">en</span>: {
        <span class="hljs-attr">translation</span>: EN_TRANSLATION,
      },
      <span class="hljs-attr">fr</span>: {
        <span class="hljs-attr">translation</span>: FR_TRANSLATION,
      },
    },
    <span class="hljs-attr">fallbackLng</span>: <span class="hljs-string">"en"</span>,
    <span class="hljs-attr">keySeparator</span>: <span class="hljs-string">"."</span>,
  });

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handleChangeLanguage = <span class="hljs-keyword">async</span> (language = <span class="hljs-string">"en"</span>) =&gt; {
  <span class="hljs-keyword">await</span> i18n.changeLanguage(
    language,
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Language Changed to: "</span> + language)
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> i18n;
</code></pre><p>We used the Language-Detector plugin and also changed the <code>lng</code> property to <code>fallbackLng</code>. This is because we’re no longer hardcoding our locale to <code>en</code>, instead, we want to use it as a fallback language should in case translations are unavailable for the locale selected. The Language-Detector plugin also helps us with persisting the selected locale in Local Storage so we don’t have to go through the process of changing locales again the next time we use the app.</p>
<p>Now save the changes and view the result in the browser, we’ll notice our app still works as expected. Also, when we change the language and refresh the app we notice the language stays the same.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_6CEBE7963D9F76707C361DE28554CD96EDC2B57BA0C4F761180E25A1B8798855_1668531387206_Setting_Up_Internationalization_in_React.gif" alt /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, I explained the benefits of setting up Internationalization in your applications and how you can go about setting up react-i18next in your react projects. I hope you found this guide helpful and that you would be able to set up internationalization easily in your applications moving forward. You can find the complete code for the tutorial on <a target="_blank" href="https://github.com/Young-Einstein10/internationalization-in-react/tree/feature/setup-react-i18next">GitHub</a>.</p>
<p>Feel free to reach out to me via <a target="_blank" href="https://www.linkedin.com/in/abdulrahman-yusuf-a44463176/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/zaydabdulrahman">Twitter</a> if there are any questions.</p>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Internationalization_and_localization">Internationalization and Localization</a>, Wikipedia</li>
<li><a target="_blank" href="https://locize.com/blog/react-i18next">A react-i18next guide</a>, Locize Blog</li>
<li><a target="_blank" href="https://react.i18next.com">react-i18next Documentation</a>, react-i18next</li>
<li><a target="_blank" href="https://www.i18next.com/overview/api,">i18next</a> <a target="_blank" href="https://www.i18next.com/overview/api,">API Overview</a>, i18next</li>
<li><a target="_blank" href="https://blog.shahednasser.com/how-to-internationalize-a-react-app/">How to Internationalize a React App</a>, Shahed Nasser</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to add a Prefix Icon to Ant Design Select Component.]]></title><description><![CDATA[Ant Design Select component has a lot of properties that can be passed into the component in order to enjoy it to the fullest, but one property I wished it has is the prefix icon. Recently, I was tasked with building a product that involved a lot of ...]]></description><link>https://blog.abdulyusuf.me/how-to-add-a-prefix-icon-to-ant-design-select-component</link><guid isPermaLink="true">https://blog.abdulyusuf.me/how-to-add-a-prefix-icon-to-ant-design-select-component</guid><category><![CDATA[React]]></category><category><![CDATA[styled-components]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Abdulrahman Yusuf]]></dc:creator><pubDate>Sat, 12 Feb 2022 21:10:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/p9OkL4yW3C8/upload/v1644700054089/5lLhhKxrL.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ant Design Select component has a lot of properties that can be passed into the component in order to enjoy it to the fullest, but one property I wished it has is the prefix icon. Recently, I was tasked with building a product that involved a lot of Select Dropdowns and the prefix icon was part of the component’s design, so I built an extended version of the component giving room for me to add the extra props I needed for it to work perfectly.</p>
<p>In this tutorial, I will be explaining how I extended the Select Component and how you could add other properties to it if needed.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Ensure you have the following catered for before going on with this tutorial in order to have a seamless experience going forward:</p>
<ul>
<li>A Text Editor or IDE e.g VS Code</li>
<li>Basic knowledge of React (we’ll be using Typescript)</li>
</ul>
<h3 id="heading-step-1-setting-up-our-react-project">Step 1: Setting Up our React Project</h3>
<p>I have created a starter project on CodeSandbox in order for us to focus on the actual implementation of the Select Component. You can find it <a target="_blank" href="https://codesandbox.io/s/customizing-antd-select-forked-ivm9w?file=/src/App.tsx">here</a>. </p>
<p>We’ll be making use of styled-components for our styling as it makes writing styles that are scoped to a component very easy. You can read more about styled-components in their <a target="_blank" href="https://styled-components.com/docs">docs</a>.</p>
<h3 id="heading-step-2-creating-our-customselect-file-within-the-project">Step 2: Creating our CustomSelect File within the project.</h3>
<p>Create a new file called <code>CustomSelect.tsx</code> in our project folder like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644699525293/1OQMEHgUn.png" alt="Untitled.png" /></p>
<p>This file would contain our implementation logic for how the Select Component would work with prefix icons. Now, let’s update the file we just created with the following code:</p>
<pre><code class="lang-tsx">import React, { ReactNode } from "react";
import { Select, SelectProps } from "antd";
import styled from "styled-components";

type CustomSelectProps = SelectProps &amp; {
  prefixIcon?: ReactNode;
};

const SelectWrapper = styled.div`
  position: relative;
`;

const CustomSelect = ({ prefixIcon, children, ...rest }: CustomSelectProps) =&gt; {
  return (
    &lt;SelectWrapper&gt;
      {prefixIcon &amp;&amp; &lt;div className="prefix-icon-wrapper"&gt;{prefixIcon}&lt;/div&gt;}
      &lt;Select {...rest}&gt;{children}&lt;/Select&gt;
    &lt;/SelectWrapper&gt;
  );
};

export default CustomSelect;
</code></pre>
<p>We added a styled wrapper around our default Select Component which is imported from Antd Design, then we created a condition that displays our prefix icon depending on whether it's passed down as props to the CustomSelect component.</p>
<p>We also created a custom type <code>CustomSelectProps</code> which is made up of type <code>SelectProps</code> from Antd Design and our prefix icon which is being added. Our prefix icon is of type <code>ReactNode</code> which would enable us to pass down any value that’s a ReactNode as our icon.</p>
<p>Now, update the Select Component in our <code>App.tsx</code> file like so using our newly created CustomSelect component:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644699557787/3x4X-MCI5.png" alt="custom-select.png" /></p>
<h3 id="heading-step-3-adding-a-prefix-icon-to-our-component">Step 3: Adding a Prefix Icon to our Component.</h3>
<p>Pass any icon of your choice as props to the Select Component so we can have a look at how it’s being displayed currently. I’ll be adding the <code>UserOutlined</code> icon from <code>@ant-design/icons</code> like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644699572693/dDyLc0Hvu.png" alt="custom-select-icon2.png" /></p>
<p>Currently, our icon is displayed above the Select Component which isn’t what we want. We’ll fix it by adding the appropriate styles in our <code>CustomSelect.tsx</code> we created. Update our <code>SelectWrapper</code> styles as shown below:</p>
<pre><code class="lang-tsx">const SelectWrapper = styled.div`
  position: relative;

  .prefix-icon-wrapper {
    position: absolute;
    z-index: 1;
    width: 3rem;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }

 &amp;&amp; .ant-select .ant-select-selector {
    padding-left: calc(3rem - 8px);
  }
`;
</code></pre>
<p>We’re positioning our prefix icon using the <code>prefix-icon-wrapper</code> we gave its wrapper, this would enable any icon added to the Select component to be properly aligned in our Component. Also, we subtracted the left-padding value of the Select Component from the width of our icon, this would enable the spacing between the Icon and the Select Component to be properly distributed.</p>
<p>Our CustomSelect component is now ready for use 😎.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644699591321/7tVJGo8Sf.png" alt="Untitled 1.png" /></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In this tutorial, we learned how we can  Customize Antd Design Select Component by extending its props and allowing any kind of icon to be added to it as a Prefix Icon. </p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><a target="_blank" href="https://ant.design/components/select">Ant Design Select</a></li>
<li><a target="_blank" href="https://ant.design/components/icon">Ant Design Icons</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Introduction to Typescript]]></title><description><![CDATA[Typescript has been around for a while now, and I'm sure you must have heard developers around you talk about it. According to the latest StackOverflow survey, Typescript is the second most loved programming language after Rust. In this article, I wo...]]></description><link>https://blog.abdulyusuf.me/introduction-to-typescript</link><guid isPermaLink="true">https://blog.abdulyusuf.me/introduction-to-typescript</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[Abdulrahman Yusuf]]></dc:creator><pubDate>Sat, 09 Jan 2021 19:55:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1610222073256/f-oORyabl.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Typescript has been around for a while now, and I'm sure you must have heard developers around you talk about it. According to the latest StackOverflow survey, Typescript is the second most loved programming language after Rust. In this article, I would be introducing what Typescript is, its benefits in today's world, and how to set up your Typescript development environment. </p>
<h3 id="prerequisites">Prerequisites</h3>
<p>In order to have a seamless experience while following this article, ensure you have the following catered for:</p>
<ul>
<li>Basic knowledge of Javascript</li>
<li>A Text Editor e.g VS Code</li>
<li>Node installed on your machine</li>
<li>Basic Knowledge of using the terminal</li>
<li>Yarn Installed (optional)</li>
</ul>
<h3 id="what-is-typescript">What is Typescript?</h3>
<p>TypeScript is a programming language created and maintained by Microsoft. It is a strict syntactical superset of Javascript and adds optional static typing and true Object-Oriented Programming (OOP) capabilities to the language. If you're familiar with other programming languages like C# or Java, it is impossible to declare a variable without stating the datatype it would hold. So, Typescript enables us to replicate this feature in Javascript in order to reduce runtime errors or bugs which developers face while coding. It also increases developer productivity. Since TypeScript is a superset of JavaScript, existing JavaScript programs are also valid TypeScript programs. Also, few people also consider Typescript as Javascript with superpowers😎.</p>
<h3 id="benefits-of-using-typescript">Benefits of Using Typescript</h3>
<ul>
<li><strong>Statically Typed System:</strong> Javascript is a dynamically typed language, hence it has no support for using and creating types during development. Developers can easily make an error like missing a letter in a function/variable, referencing an undeclared function/variable etc. But with Typescript, we can create a typed system that will enforce the type and properties for any given variables, functions, or object that's declared which in turn enables the developer to create more robust and scalable code.</li>
<li><strong>Code Readability:</strong> Code written in Typescript is very easy to read due to the types which have been created for it. Anyone can easily understand the developer's intent who originally wrote the code as most code blocks are self-explanatory.</li>
<li><strong>Browser Compatibility:</strong> Typescript is transpiled to Javascript that is compatible on all browsers. Developers also have the option of choosing what version of javascript they would like their code to be transpiled to among the ES Versions of Javascript.</li>
<li><strong>Code Completion and Intellisense:</strong> Using Typescript enables developers to enjoy code auto-completion and suggestion while coding which speeds up development thereby increasing productivity gains.</li>
<li><strong>Discipline:</strong> Developers who code in Typescript are disciplined because it forces them to fix any bugs they run into during the course of development. Also, the types which are created act as preventive measures that will help the developer enforce the expected properties or parameters for an object or function created.</li>
</ul>
<h3 id="setting-up-a-typescript-development-environment">Setting up a Typescript Development Environment</h3>
<p>Typescript can be installed on a local machine using either of the following commands:</p>
<pre><code class="lang-bash">npm install -g typescript
</code></pre>
<p>or</p>
<pre><code class="lang-bash">yarn global add typescript
</code></pre>
<p>This would install Typescript globally on our machine. Once the installation is completed, we now have access to the <code>tsc</code> command. The <code>tsc</code> command stands for Typescript Compiler which we would be using for most of our operations with Typescript. You can confirm if the installation was successful by using the command: </p>
<pre><code class="lang-bash">tsc -v
</code></pre>
<p>You should get a version number outputted after entering that command in your terminal.</p>
<p>Now, create a folder called <code>ts-intro</code> then create a file called <code>app.ts</code> within it. Typescript files are usually identified with a <code>.ts</code> extension.  Paste the following code in our <code>app.ts</code> file: </p>
<pre><code class="lang-tsx">console.log("Hello World");
</code></pre>
<p>Then run the Typescript compiler in order to compile our code to Javascript:</p>
<pre><code class="lang-tsx">tsc app.ts
</code></pre>
<p>You should find a new file <code>app.js</code> created automatically in your project root. That's the javascript file which our Typescript code was compiled into. </p>
<p>Now, imagine we have more than one Typescript file within our project, running the <code>tsc</code> command for each one of them would be counter-productive, we need a more efficient method for compiling all our Typescript file. We can achieve that using the <code>tsconfig.json</code> file that would be created in our project root. Run the command below to do that: </p>
<pre><code class="lang-tsx">tsc --init
</code></pre>
<p>A new file named <code>tsconfig.json</code> should be in your project root after running that command. This file is very similar to what our <code>package.json</code> file does in most projects. It contains the rules and configurations Typescript will be needing in order to work seamlessly on our machine.</p>
<p>Looking at our newly created <code>tsconfig.json</code> file, we would find a considerable amount of configurations which we need not worry ourselves about now. The only thing we might need to change is our target option. This tells us what version of javascript our Typescript code would be compiled into. The default selected option is ES5, we can change it to ES6 if we would like our javascript code to use the latest features of javascript or any other version we wish to use. Also, comments have been created alongside each property to tell us what they are for.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"compilerOptions"</span>: {
    <span class="hljs-attr">"target"</span>: <span class="hljs-string">"es5"</span>,                          <span class="hljs-comment">/* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */</span>
    <span class="hljs-attr">"module"</span>: <span class="hljs-string">"commonjs"</span>,                     <span class="hljs-comment">/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */</span>
    <span class="hljs-attr">"strict"</span>: <span class="hljs-literal">true</span>,                           <span class="hljs-comment">/* Enable all strict type-checking options. */</span>
    <span class="hljs-attr">"esModuleInterop"</span>: <span class="hljs-literal">true</span>,                  <span class="hljs-comment">/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. */</span>
    <span class="hljs-attr">"skipLibCheck"</span>: <span class="hljs-literal">true</span>,                     <span class="hljs-comment">/* Skip type checking of declaration files. */</span>
    <span class="hljs-attr">"forceConsistentCasingInFileNames"</span>: <span class="hljs-literal">true</span>  <span class="hljs-comment">/* Disallow inconsistently-cased references to the same file. */</span>
  }
}
</code></pre>
<p>So, create another file called <code>main.ts</code> and paste in the following code:</p>
<pre><code class="lang-tsx">const user = {
  firstName: "Brian",
  lastName: "Smith",
  role: "Doctor"
}

console.log(`Hello ${user.role} ${user.firstName} ${user.lastName}`)
</code></pre>
<p>Running our <code>tsc</code> command would compile all files ending with the Typescript extension in our project root. A new file called <code>main.js</code> would be created. If we inspect it, you'll notice we have javascript code that's in ES5 version.</p>
<pre><code class="lang-jsx"><span class="hljs-meta">"use strict"</span>;
<span class="hljs-keyword">var</span> user = {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">"Brian"</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">"Smith"</span>,
    <span class="hljs-attr">role</span>: <span class="hljs-string">"Doctor"</span>
};
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello "</span> + user.role + <span class="hljs-string">" "</span> + user.firstName + <span class="hljs-string">" "</span> + user.lastName);
</code></pre>
<p>Now, we can use the <code>tsc</code> command to compile any Typescript file we have in our project.</p>
<h3 id="conclusion">Conclusion</h3>
<p>In this article, we learnt what Typescript is, the benefits of Typescript in today's world, and how to set it up in your development environment. This article is just an introduction to Typescript, there's still so much about Typescript we obviously can't discuss in a single post. I hope this article has convinced you why you might need Typescript in that next project you plan to work on. In my upcoming post, I would be showing you how you can convert a project originally built with Javascript to Typescript.</p>
<h3 id="resources">Resources</h3>
<ul>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/TypeScript">What is Typescript?</a></li>
<li><a target="_blank" href="https://www.typescriptlang.org/docs/">Typescript</a> (docs)</li>
<li><a target="_blank" href="https://www.digitalocean.com/community/tutorials/typescript-typescript-benefits">Benefits of Using Typescript</a></li>
<li><a target="_blank" href="https://www.guru99.com/typescript-vs-javascript.html">Javascript vs. Typescript</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Things to know before the HNG Internship 7.0 Starts]]></title><description><![CDATA[Overview

What's HNG Internship?
Stages within the Internship
Communication within the Internship
Assignment of Tasks
Team Formation
Communication among Team Members

What's HNG Internship ?
The HNG (hotels.ng) Internship is a 3-month remote internsh...]]></description><link>https://blog.abdulyusuf.me/things-to-know-before-the-hng-internship-70-starts</link><guid isPermaLink="true">https://blog.abdulyusuf.me/things-to-know-before-the-hng-internship-70-starts</guid><category><![CDATA[Frontend Development]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Abdulrahman Yusuf]]></dc:creator><pubDate>Sat, 23 May 2020 19:20:07 GMT</pubDate><content:encoded><![CDATA[<p><strong>Overview</strong></p>
<ul>
<li>What&#39;s HNG Internship?</li>
<li>Stages within the Internship</li>
<li>Communication within the Internship</li>
<li>Assignment of Tasks</li>
<li>Team Formation</li>
<li>Communication among Team Members</li>
</ul>
<p><strong>What&#39;s HNG Internship ?</strong></p>
<p>The HNG (hotels.ng) Internship is a 3-month remote internship designed to find and develop the most talented software developers. Everyone is welcome to participate (there is no entrance exam). Anyone can log into the internship using their laptop. Each week, we give tasks. Those who complete them advance forward. We pay the interns weekly. The intern coders are introduced to complex programming frameworks and get to work on real-world software. The finalists are connected to the best companies in the tech ecosystem and get full-time jobs and contracts immediately (https://hng.tech/about). It comprises of different tracks which interns can participate in. A few of them includes:</p>
<ul>
<li>UI/UX</li>
<li>Digital Marketing</li>
<li>Frontend Development</li>
<li>Backend Development</li>
<li>Developer Operations (DevOps)</li>
<li>Project Management</li>
</ul>
<p><strong>Stages within the Internship</strong></p>
<p>The Internship is made up of 10 stages in which promotion is solely based on a team or intern&#39;s ability to deliver tasks assigned to them. Failure to deliver task results in probation for a 24 hour period during which makeup tasks are given to interns to determine whether or not they get evicted. Whoever gets to stage 10 successfully becomes a finalist and receives other perks that come with being a finalist which interns get to enjoy. </p>
<p><strong>Communication within the Internship</strong></p>
<p>Communication is mainly through Slack in which different channels have been created for their specific purposes. A few popular channels you should know about is <strong>general</strong> and <strong>random</strong>. The <strong>general</strong> channel is where any information or announcement regarding the internship are passed and mostly mentors and officials are the only one allowed sending messages here. The <strong>random</strong> channel is open to everyone whether intern or mentor, anyone can send any kind of information here as long as it&#39;s not affecting someone in anyway. Each team within the internship also gets a personal channel for collaboration among team members, a mentor is usually assigned to each team to oversee how things are being done in there. Every channel within the internship has rules of engagement that are communicated among interns during the start of the internship.</p>
<p><strong>Assignment of Tasks</strong></p>
<p>Tasks are assigned weekly to teams of different tracks which enable interns to gain and experience the real-world scenario of solving a problem. Tasks can also span more than a week depending on the complexity of the problem being solved.</p>
<p><strong>Team Formation</strong></p>
<p>Team formation is one thing that&#39;s very important during the internship as it&#39;s the main determinant of how long one will stay during the program. That&#39;s why interns are always advised to network with each other in order to determine the skill level of each other so that it won&#39;t be a blocker for a team when tasks are assigned. An Ideal team is one that comprises of all the tracks mentioned at the beginning of this article in order not to experience much difficulty while trying to deliver a task. In situations where tasks are not completed within the stipulated time given by the mentors, interns are given a probation period during which the duration for completing the said task is extended or a makeup task is assigned to the team or intern. The probation period has a channel of its own called <strong>underworld</strong> and the rule here is, the maximum amount of time an intern could spend there is 24 hours, once the probation period has elapsed, the intern or team is struck for eviction.</p>
<p><strong>Communication among Team Members</strong></p>
<p>Communication among team members includes the use of team channels and other project management tools like Git and Github, Pivotal Tracker, Google Docs e.t.c. So any familiarity with any of these tools would go a long way in helping during the course of the internship.</p>
<p>Before I end this article, I would like to drop a little hint I personally use: always be ready to learn, you never when you will be in need of it. Like my friend once said:</p>
<blockquote>
<p>If you&#39;ve learnt it, you&#39;ve known it for life.</p>
</blockquote>
<p>That&#39;s only about a few things to watch out for during the course of the internship, there&#39;s so much more I didn&#39;t mention here because there&#39;s no possible way I can in this article, if anyone needs to ask any question regarding the internship, you can find me on twitter <a target='_blank' rel='noopener noreferrer'  href="https://twitter.com/zaydabdulrahman">@zaydabdulrahman</a>.</p>
]]></content:encoded></item></channel></rss>