<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gaurav Behere</title>
    <description>The latest articles on DEV Community by Gaurav Behere (@gauravbehere).</description>
    <link>https://dev.to/gauravbehere</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F430717%2F23fe06fa-c988-4a35-a8e8-5f9dd134d28c.jpg</url>
      <title>DEV Community: Gaurav Behere</title>
      <link>https://dev.to/gauravbehere</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gauravbehere"/>
    <language>en</language>
    <item>
      <title>Time to say goodbye to Webpack?</title>
      <dc:creator>Gaurav Behere</dc:creator>
      <pubDate>Thu, 13 Jan 2022 09:50:25 +0000</pubDate>
      <link>https://dev.to/gauravbehere/time-to-say-goodbye-to-webpack-2kn8</link>
      <guid>https://dev.to/gauravbehere/time-to-say-goodbye-to-webpack-2kn8</guid>
      <description>&lt;p&gt;Before we answer the big question, lets look at why we are even considering it.&lt;/p&gt;

&lt;p&gt;If you look at bestofJS data for 2021, you would see that the rising star in the build tools category is &lt;code&gt;Vite&lt;/code&gt;, leaving &lt;code&gt;Webpack&lt;/code&gt; far behind in terms of popularity.&lt;br&gt;
Check out more stats here:&lt;br&gt;
&lt;a href="https://risingstars.js.org/2021/en#section-build" rel="noopener noreferrer"&gt;2021 JavaScript Rising Stars&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrt3d86jztveuw01blup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrt3d86jztveuw01blup.png" alt="Popular build tools"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Lets have a closer look at &lt;code&gt;Vite&lt;/code&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Vite (French word for "quick", pronounced /vit/, like "veet") is a build tool that aims to provide a faster and leaner &lt;code&gt;development&lt;/code&gt; experience for modern web projects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Please note the emphasis on &lt;code&gt;development&lt;/code&gt;. &lt;code&gt;Vite&lt;/code&gt; does not promise a multifold optimization or better production experience. So don't expect your production build to be optimized or any drastic reduction in the bundle size you generate.&lt;/p&gt;
&lt;h3&gt;
  
  
  So what does &lt;code&gt;Vite&lt;/code&gt; do to make the development experience better?
&lt;/h3&gt;

&lt;p&gt;It consists of two major parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A dev server that provides rich feature enhancements over native ES modules, for example extremely fast Hot Module Replacement (HMR).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A build command that bundles your code with Rollup, pre-configured to output highly optimized static assets for production.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Vite&lt;/code&gt; is opinionated and comes with sensible defaults out of the box, but is also highly extensible via its Plugin API and JavaScript API with full typing support.&lt;/p&gt;




&lt;p&gt;It has been long since we have been writing JS code in a modular fashion specially since ES6 modules. Since not a lot of browsers were handling loading ES6 modules natively, we have the concept of bundling our code, using tools that crawl, process and concatenate our source modules into files that can run in the browser.&lt;/p&gt;

&lt;p&gt;Tools like Webpack, parcel &amp;amp; rollup do the same job.&lt;br&gt;
When you start a project, the size &amp;amp; number of JS modules may look like a smaller problem but as you write more code, the project grows &amp;amp; you see that starting a dev server takes a long time.&lt;br&gt;
Since it has to transpile the code &amp;amp; concatenate the code in a way that can be loaded in browsers.&lt;br&gt;
The slow feedback loop can greatly affect developers' productivity and happiness.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Vite aims to address these issues by leveraging new advancements in the ecosystem: the availability of native ES modules in the browser, and the rise of JavaScript tools written in compile-to-native languages.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Vite&lt;/code&gt; splits the bundles into two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;External dependencies (Vendor code): Dependencies are mostly plain JavaScript that do not change often during development. &lt;br&gt;
&lt;strong&gt;Vite pre-bundles dependencies using esbuild.&lt;/strong&gt; Esbuild pre-bundles dependencies 10-100x faster than JavaScript-based bundlers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your code (ES modules): &lt;strong&gt;Vite serves source code over native ESM.&lt;/strong&gt; This is essentially letting the browser take over part of the job of a bundler. &lt;code&gt;Vite&lt;/code&gt; only needs to transform and serve source code on demand, as the browser requests it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here, &lt;code&gt;Vite&lt;/code&gt; assumes that while you are developing in your local machine you would have latest of browsers that support loading ES6 modules natively.&lt;/p&gt;
&lt;h2&gt;
  
  
  That essentially means no time spent on bundling your code before the server can start.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F656g1l249uei8twera71.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F656g1l249uei8twera71.png" alt="Bundling before server start"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7y8bsd1kkkxj7c69jg4s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7y8bsd1kkkxj7c69jg4s.png" alt="No Bundling"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Awesome, so why bundle for production?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Though most of the browsers now support loading ES modules natively, if not all of your target audience is on latest browsers, you still need bundling.&lt;/li&gt;
&lt;li&gt;If you don't bundle, you are going to make a lot of round trips on the network to fetch modules. To get the optimal loading performance in production, it is still better to bundle your code with tree-shaking, lazy-loading and common chunk splitting (for better caching).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Getting started with &lt;code&gt;Vite&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;With minimal dev dependencies, you can be off to a flying start&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"devDependencies": {
  "@vitejs/plugin-react": "^1.1.4",
  "vite": "^2.7.10"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A very basic &lt;code&gt;vite.config.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()]
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two simple commands to start a dev server &amp;amp; make a production build:&lt;br&gt;
&lt;code&gt;vite&lt;/code&gt; &amp;amp; &lt;code&gt;vite build&lt;/code&gt; respectively.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Vite&lt;/code&gt; looks for an index html entry in the root directory from where you need to load the root/index module of your code.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;index.html&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;div id="root"&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;script type="module" src="./index.jsx"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;index.jsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom'
import App from './src/app';

ReactDOM.render(
    &amp;lt;React.StrictMode&amp;gt;
        &amp;lt;App /&amp;gt;
    &amp;lt;/React.StrictMode&amp;gt;,
    document.querySelector('#root')
);

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;src/app.jsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';

const App = () =&amp;gt; {
  return &amp;lt;&amp;gt;
    &amp;lt;div&amp;gt;Hello There&amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;Time right now: {new Date().toTimeString()}&amp;lt;/div&amp;gt;
  &amp;lt;/&amp;gt;
}

export default App;

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

&lt;/div&gt;



&lt;p&gt;Without bundling the code, server starts in a fraction of a second&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc26w1mjhy4v0cf1wazbo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc26w1mjhy4v0cf1wazbo.png" alt="Server startup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look at how the ES modules are loaded in the browser, note that app.jsx loaded as a native ES module&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ddunvl623gn0i0dm68r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ddunvl623gn0i0dm68r.png" alt="Resources"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hot replacement of modules (HMR)
&lt;/h2&gt;

&lt;p&gt;Developers need to get immediate feedback of changes made in the code. You can't wait for full bundling to happen again &amp;amp; reloading the page which breaks the current state &amp;amp; flow.&lt;br&gt;
This is why some bundlers support Hot Module Replacement (HMR), allowing a module to "hot replace" itself without affecting the rest of the page. Again as the project grows, HMR also takes a long time which can be a productivity killer.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Vite&lt;/code&gt; takes an edge over other bundling tools by performing HMR over native ESM. When a file is edited, &lt;code&gt;Vite&lt;/code&gt; only needs to precisely invalidate the chain between the edited module and its closest HMR boundary (most of the time only the module itself), making HMR updates consistently fast regardless of the size of your application.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Vite&lt;/code&gt; also takes advantage of HTTP headers to speed up full page reloads. Source code module requests are made conditional via 304 Not Modified, and dependency module requests are strongly cached via Cache-Control: max-age=31536000,immutable so they don't hit the server again once cached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Vite&lt;/code&gt; starts your dev server fast by skipping the bundling.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Vite&lt;/code&gt; make use of HTTP status codes for a faster reload &amp;amp; caching.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Vite&lt;/code&gt; uses native ESM for hot module replacement. Thus your changes reflect in your app faster.&lt;/li&gt;
&lt;li&gt;Since &lt;code&gt;Vite&lt;/code&gt; is a bit opinionated about the config, with a minimal config you are good to go.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.pinimg.com%2Foriginals%2F0f%2F67%2F90%2F0f67908cde5b012edffeb5ff5e96bcd4.gif" alt="Wow"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Server side rendering
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Vite&lt;/code&gt; is also pre-configured to handle your build as a universal app. &lt;code&gt;Vite&lt;/code&gt; can pre-render the HTML pages, so robot crawlers can fetch your page content without executing js.&lt;br&gt;
Read more &lt;a href="https://vitejs.dev/guide/ssr.html" rel="noopener noreferrer"&gt;https://vitejs.dev/guide/ssr.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So should we just move to &lt;code&gt;Vite&lt;/code&gt; &amp;amp; stop using tools like Webpack?
&lt;/h2&gt;

&lt;p&gt;Coming back to the question that we started with. With all the benefits listed above, it seems promising to move to &lt;code&gt;Vite&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What gives you a lot of simpler APIs with a lot of abstraction and an opinion is often hard to configure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Based on this principle if you use some very specific long tail configurations of Webpack, it won't be a good idea to jump to Vite rightaway. If you use Webpack with basic configurations, you should move to &lt;code&gt;Vite&lt;/code&gt; for a better developer experience.&lt;/p&gt;

&lt;p&gt;If I am starting a new project, it will be using &lt;code&gt;Vite&lt;/code&gt; for sure.&lt;/p&gt;

&lt;p&gt;Thank you for reading. If you have moved a large scale project from Webpack to &lt;code&gt;Vite&lt;/code&gt;, do share your experience. It will be great to learn from your experience.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>webpack</category>
    </item>
    <item>
      <title>Unit testing service workers</title>
      <dc:creator>Gaurav Behere</dc:creator>
      <pubDate>Wed, 15 Dec 2021 13:03:27 +0000</pubDate>
      <link>https://dev.to/gauravbehere/unit-testing-service-workers-l9j</link>
      <guid>https://dev.to/gauravbehere/unit-testing-service-workers-l9j</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Writing unit tests for service workers made easy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fseeklogo.com%2Fimages%2FJ%2Fjest-logo-F9901EBBF7-seeklogo.com.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fseeklogo.com%2Fimages%2FJ%2Fjest-logo-F9901EBBF7-seeklogo.com.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F694%2F1%2AaO4HRVpU1zQ22rvhAeSK1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F694%2F1%2AaO4HRVpU1zQ22rvhAeSK1w.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prelude
&lt;/h2&gt;

&lt;p&gt;While service workers amaze us with its capabilities to cache requests, edit headers before putting requests on the network etc.&lt;br&gt;
I think you will agree that unit testing service workers is not straight-forward.&lt;br&gt;
The biggest question is 'what to mock?'&lt;/p&gt;

&lt;p&gt;A big shout out to Zack Argyle for writing &lt;a href="https://github.com/zackargyle/service-workers/tree/master/packages/service-worker-mock" rel="noopener noreferrer"&gt;Service Worker Mock&lt;/a&gt;. This library prepares all the mocks &amp;amp; lets your tests have an environment where you have the recipe to test your service worker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Note
&lt;/h2&gt;

&lt;p&gt;This code sample is an enhancement on top of &lt;a href="https://github.com/zackargyle/service-workers/tree/master/packages/service-worker-mock" rel="noopener noreferrer"&gt;Service Worker Mock&lt;/a&gt;. Service Worker Mock explains how to write unit tests for service works. &lt;code&gt;Since it is not maintained any more, I am writing this code sample to unblock ourselves from the current issues in that library.&lt;/code&gt;&lt;br&gt;
Tests are written using the sample service worker given at &lt;a href="https://github.com/GoogleChrome/samples/blob/gh-pages/service-worker/basic/service-worker.js" rel="noopener noreferrer"&gt;service worker example&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem with the current version (2.0.5) of service worker mock
&lt;/h2&gt;

&lt;p&gt;Object.assign(global, makeServiceWorkerEnv()) no longer puts EventTarget methods like addEventListener into the global scope because they are no longer "own" properties of ServiceWorkerGlobalScope&lt;/p&gt;

&lt;h2&gt;
  
  
  Workaround
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make &lt;code&gt;addEventListener&lt;/code&gt; an enumerable property
```
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;beforeEach(() =&amp;gt; {&lt;br&gt;
   const serviceWorkerEnv = makeServiceWorkerEnv();&lt;br&gt;
   Object.defineProperty(serviceWorkerEnv, 'addEventListener', {&lt;br&gt;
      value: serviceWorkerEnv.addEventListener,&lt;br&gt;
      enumerable: true&lt;br&gt;
   });&lt;br&gt;
   Object.assign(global, serviceWorkerEnv)&lt;br&gt;
   jest.resetModules();&lt;br&gt;
});&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
### Testing Event registration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it('should add listeners', async () =&amp;gt; {&lt;br&gt;
  require('../src/sample-sw');&lt;br&gt;
  await self.trigger('install');&lt;br&gt;
  expect(self.listeners.get('install')).toBeDefined();&lt;br&gt;
  expect(self.listeners.get('activate')).toBeDefined();&lt;br&gt;
  expect(self.listeners.get('fetch')).toBeDefined();&lt;br&gt;
});&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
### Testing cache deletion on activation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it('should delete old caches on activate', async () =&amp;gt; {&lt;br&gt;
  require('../src/sample-sw');&lt;/p&gt;

&lt;p&gt;// Create old cache&lt;br&gt;
  await self.caches.open('OLD_CACHE');&lt;br&gt;
  expect(self.snapshot().caches.OLD_CACHE).toBeDefined();&lt;/p&gt;

&lt;p&gt;// Activate and verify old cache is removed&lt;br&gt;
  await self.trigger('activate');&lt;br&gt;
  expect(self.snapshot().caches.OLD_CACHE).toStrictEqual({});&lt;br&gt;
});&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
### Testing fetch event to see if it returns cached response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it('should return a cached response', async () =&amp;gt; {&lt;br&gt;
  require('../src/sample-sw');&lt;/p&gt;

&lt;p&gt;const cachedResponse = { clone: () =&amp;gt; { }, data: { key: 'value' } };&lt;br&gt;
  const cachedRequest = new Request('/test');&lt;br&gt;
  const cache = await self.caches.open('TEST');&lt;br&gt;
  cache.put(cachedRequest, cachedResponse);&lt;/p&gt;

&lt;p&gt;const response = await self.trigger('fetch', cachedRequest);&lt;br&gt;
  expect(response.data.key).toEqual('value');&lt;br&gt;
});&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
### Testing if fetch event makes network call &amp;amp; updates cache. Also test any custom logic like appending a bearer token in the request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it('should fetch and cache an uncached request and append the right auth token in the header', async () =&amp;gt; {&lt;br&gt;
  const mockResponse = { clone: () =&amp;gt; { return { data: { key: 'value' } } } };&lt;br&gt;
  global.fetch = (response) =&amp;gt; Promise.resolve({ ...mockResponse, headers: response.headers });&lt;/p&gt;

&lt;p&gt;require('../src/sample-sw');&lt;/p&gt;

&lt;p&gt;const request = new Request('/test');&lt;br&gt;
  const response = await self.trigger('fetch', request);&lt;br&gt;
  expect(response.clone()).toEqual(mockResponse.clone());&lt;/p&gt;

&lt;p&gt;expect(response.headers.get('authorization')).toBe('Bearer my secret auth');&lt;/p&gt;

&lt;p&gt;const runtimeCache = self.snapshot().caches.runtime;&lt;br&gt;
  expect(runtimeCache[request.url]).toEqual(mockResponse.clone());&lt;br&gt;
});&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
### Testing if the requests to the external domains are ignored
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it('should ignore the requests to external world', async () =&amp;gt; {&lt;br&gt;
  const mockResponse = { clone: () =&amp;gt; { return { data: { key: 'value' } } } };&lt;br&gt;
  global.fetch = (response) =&amp;gt; Promise.resolve({ ...mockResponse, headers: response.headers });&lt;/p&gt;

&lt;p&gt;require('../src/sample-sw');&lt;/p&gt;

&lt;p&gt;const request = new Request('&lt;a href="http://google.com'" rel="noopener noreferrer"&gt;http://google.com'&lt;/a&gt;);&lt;br&gt;
  const response = await self.trigger('fetch', request);&lt;br&gt;
  expect(response).not.toBeDefined();&lt;br&gt;
});&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
## Coverage
&amp;lt;img src="https://raw.githubusercontent.com/gauravbehere/unit-test-service-worker/main/coverage.PNG"/&amp;gt;

## Epilogue
Check out the code repo for this sample here:
[unit-test-service-worker](https://github.com/gauravbehere/unit-test-service-worker)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Inversion of Control — A simple &amp; effective design principle</title>
      <dc:creator>Gaurav Behere</dc:creator>
      <pubDate>Sun, 17 Oct 2021 13:57:49 +0000</pubDate>
      <link>https://dev.to/gauravbehere/inversion-of-control-a-simple-effective-design-principle-5f7g</link>
      <guid>https://dev.to/gauravbehere/inversion-of-control-a-simple-effective-design-principle-5f7g</guid>
      <description>&lt;h3&gt;
  
  
  Reducing code complexity with IoC
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Inversion of control (IoC)
&lt;/h2&gt;

&lt;p&gt;If you have heard of dependency injection(DI) you have been using inversion of control but maybe not knowingly.&lt;br&gt;
IoC is often seems used interchangeably with DI but IoC as a concept is much more than that.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IoC is a design principle that helps you in reducing the complexity of code that you may want to ship as a reusable component or a library.&lt;br&gt;
&lt;strong&gt;DI&lt;/strong&gt; is one of the patterns that help in implementing IoC.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Usually, we have seen libraries/components implementing all the features for us &amp;amp; expose APIs to be called in a certain way to get the functionality we need. We may call the same API with a different set of parameters &amp;amp; value combinations to get what we want.&lt;/p&gt;

&lt;p&gt;There is a level of abstraction to us in a way that we need not bother about the library/component reusable code but we need to know the meaning of each option/parameter to be passed so that we can understand the API’s behavior better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now put yourself in the shoes of the guy who wrote that library or the reusable component.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is n number of use cases that he needs to support out of the same piece of code. There can be different values of the parameters &amp;amp; different combinations of those which may result in the same API or component to behave differently.&lt;/p&gt;
&lt;h3&gt;
  
  
  What does this translate to in code?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Lots of IF ELSE statements&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  What does it lead to?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;More cyclomatic complexity&lt;/li&gt;
&lt;li&gt;Less maintainable code&lt;/li&gt;
&lt;li&gt;Lengthier documentation about all the options &amp;amp; their combinations&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgflip.com%2F42lrta.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgflip.com%2F42lrta.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any new feature that our generic component now has to support will have to be done very carefully so that we don’t break any existing support.&lt;/p&gt;

&lt;p&gt;When we refactor the code it is not easy to get away with any option or any conditional branch as we may not know who is consuming our component using that code flow.&lt;/p&gt;

&lt;p&gt;All these are very usual problems we see almost every day, isn’t it? This is an ever-growing problem too as the request for new functionalities with more if-else will keep coming.&lt;br&gt;
Let’s look at this piece of code to understand the problem better.&lt;/p&gt;

&lt;p&gt;You are writing a function that does the sorting of an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sortArray = (array) =&amp;gt; array.sort();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At a very basic level, it just returns the native sort. This is not sufficient as it doesn’t work well with numbers &amp;amp; custom sort for objects, also the default order of sort would be ascending. Let's add these features one by one.&lt;/p&gt;

&lt;p&gt;Let us add support for descending sort:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// order = 1 -&amp;gt; ascending
// order = 2 -&amp;gt; descending
const sortArray = (array, order=1) =&amp;gt; {
  if(order === 1)
    return array.sort();
  else if(order === 2)
    return array.sort((a,b) =&amp;gt; b - a);
  else
   console.error("Unsupported sort order provided")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us add support for sorting objects with a specified key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// @param order(number) = 1 -&amp;gt; ascending
// @param order(number) = 2 -&amp;gt; descending
// @param objectSort(boolean) 
const sortArray = (array, objectSort, key, order=1) =&amp;gt; {
  if(objectSort) {
    if(order === 1)
      return array.sort((a,b) =&amp;gt; a[key] - b[key]);
    else if(order === 2)
      return array.sort((a,b) =&amp;gt; b[key] - a[key]);
    else
     console.error("Unsupported sort order provided")
  }
  else {
    if(order === 1)
      return array.sort();
    else if(order === 2)
      return array.sort((a,b) =&amp;gt; b - a);
    else
     console.error("Unsupported sort order provided")
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see that addition of features is adding code paths &amp;amp; branches in our code. Now say we need to support a case insensitive sort based on an option &amp;amp; we want to keep all the undefined values at the start of the array, that too based on an option, how many more if-else do we need?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This list of features is ever-growing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I took the example of sorting as a library function because the native sorting in JavaScript is also based on the principle of IoC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inversion of Control
&lt;/h2&gt;

&lt;p&gt;As Wikipedia explains it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls into the custom, or task-specific, code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In simple terms, in the inversion of control, the library or the reusable component lets the consumer take control of what the functionality is &amp;amp; it provides an abstraction on top of it.&lt;/p&gt;

&lt;p&gt;Now imagine passing the sorting method as a parameter to the library &amp;amp; it actually invokes your own sorting method to do the sorting.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does it help?
&lt;/h3&gt;

&lt;p&gt;The extensibility of functionality is now independent of the code complexity in the library rather the consumer gets a handle to override the default behavior in its own way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sortArray = (array, sortFunction) =&amp;gt; {
  if (sortFunction) {
    return array.sort(sortFunction);
  }
  return array.sort();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Testability&lt;/strong&gt;: We can substitute the core functionalities with mocks during the testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Substitutability&lt;/strong&gt;: We enable a &lt;em&gt;plugin architecture&lt;/em&gt; that makes it easy for us to swap out plugins, and program against code that doesn’t yet exist. All we need to do to substitute the current dependency is to create a new one that adheres to the contract defined by the interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: According to the &lt;em&gt;“Open Closed Principle”&lt;/em&gt;, a system should be open for extension but closed for modification. That means if we want to extend the system, we need only create a new plugin in order to extend the current behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegation&lt;/strong&gt;: IoC is the phenomenon we observe when we delegate behavior to be implemented by someone else but provide the hooks/plugins/callbacks to do so. We design the current component to invert control to another one. Lots of web frameworks are built on this principle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many real-life use cases where you would have seen IoC in action. A good example is a state reducer pattern.&lt;br&gt;
React, rather than providing a complex way of managing your state, lets you do that with your own reducer function &amp;amp; lets you provide your reducer as a hook before rendering your components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency Injection&lt;/strong&gt; in angular is also based on this principle. Dependency Injection (DI) is one of the implementations of IoC based on the composition of dependencies in the container (the library).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hooks in React are based on the IoC too.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Though IoC is a good principle to follow &amp;amp; there is a large number of libraries following it, it should be a conscious decision to choose IoC. In case you are aware of all the possible functionalities &amp;amp; code branches, a non-inverted control would make the consumption of the library easier. If you dealing with unknown extensibilities, it would be recommended to implement an inverted control.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>design</category>
    </item>
    <item>
      <title>Re-architecting authentication with Service Workers</title>
      <dc:creator>Gaurav Behere</dc:creator>
      <pubDate>Mon, 13 Sep 2021 06:06:42 +0000</pubDate>
      <link>https://dev.to/gauravbehere/re-architecting-authentication-with-service-workers-4j6j</link>
      <guid>https://dev.to/gauravbehere/re-architecting-authentication-with-service-workers-4j6j</guid>
      <description>&lt;p&gt;A use case of changing the authentication mechanism of a web application without touching a lot of legacy codebase&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
Many times you would encounter situations where you have a legacy codebase in front of you which has been in the market for quite a while. It may be written in a technology that is seeing a downward trend in terms of popularity. You cannot make a change very easily in the architecture of such applications as the amount of risk, testing efforts &amp;amp; impact is huge.&lt;br&gt;
Let me run you through such a use case where we recently had to change the authentication mechanism of an existing legacy web application from a JSP session &amp;amp; a cookie-based authentication mechanism to an MSAL (Microsoft Authentication Library) token-based authentication method.&lt;br&gt;
What this essentially means is the login should grant a token to the web application acquiring the token using MSAL (react-msal) in our case &amp;amp; the same token should be used for making further calls to the server.&lt;br&gt;
Read more about MSAL tokens here:&lt;br&gt;
&lt;a href="https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/acquire-token.md" rel="noopener noreferrer"&gt;https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/acquire-token.md&lt;/a&gt;&lt;br&gt;

&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;p&gt;There are two challenges we are looking at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;b&gt;Changes to the webserver&lt;/b&gt;: The web server should be able to authenticate our requests with the token that the client application is going to send as a bearer token.&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Changes to the legacy UI code written in JSP&lt;/b&gt;: The amount of legacy code which is an amalgamation of many UI technologies where there are requests like POST from FORM submits, XHR calls, calls through native JS fetch, Jquery’s $.ajax &amp;amp; a bit of axios too. It becomes very hard to avoid changes in almost every part of the code &amp;amp; still get the new authentication mechanism working where every call to our server should have a bearer token attached to the HTTP header.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1050%2F1%2AkFSS6PQtTtxIG66AVRJOwQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1050%2F1%2AkFSS6PQtTtxIG66AVRJOwQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding to the complexity of the application, the code base grew up with a lot of acquisitions of companies adding to the integrations in the existing codebase. Thus the application grew horizontally in terms of technology over the last 10 years.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1050%2F0%2A6knY-qVrAJOBwvx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1050%2F0%2A6knY-qVrAJOBwvx1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also when you have such a legacy codebase, it becomes hard to keep the knowledge fresh. There are pieces of the code that developers might not have even looked at for a long long time. Touching such code may result in unaccounted for side effects as the application has a significant number of customers who are using different versions &amp;amp; flows of the application.&lt;/p&gt;



&lt;h3&gt;
  
  
  How can we have a centralized solution which avoids making changes to a lot of files?
&lt;/h3&gt;

&lt;p&gt;&lt;b&gt;Service workers &amp;amp; promises to the rescue.&lt;/b&gt;&lt;br&gt;
We try to avoid changes in the front-end code updating the APIs to authenticate based on the incoming MSAL token.&lt;br&gt;
The solution is to capture all the network calls originated from the web application &amp;amp; append a bearer token in the HTTP header in the request.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AQpmgo07lva2ft-0iMFMusA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AQpmgo07lva2ft-0iMFMusA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Take a hold of all the network calls generated by your web application using a service worker registered at the root of your web application.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;some dummy token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This needs to be requested from MSAL library&lt;/span&gt;

  &lt;span class="c1"&gt;// Responding with a custom promise&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// edit event.request &amp;amp; respond with a fetch of a new request with new headers&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sourceHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;pair&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;sourceHeaders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sourceHeaders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bearer: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newHeaders&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;In the fetch event we need to respond with a new request that has HTTP headers we need. In the gist above, we are just adding a dummy auth token to the request. Here we do a couple of things:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a. We copy all the headers of the incoming request.
b. We create a new request with incoming headers &amp;amp; a new authorization header containing a token.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;b&gt;Now let us get the right token.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Here comes the tricky part. A service worker comes with its own limitations, it has no access to DOM &amp;amp; it can’t access shared storage between the page &amp;amp; itself. Somehow we need to get the token from the main thread &amp;amp; the container app.&lt;br&gt;
Here is a good article explaining how to establish communication between a service worker &amp;amp; the container page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://felixgerschau.com/how-to-communicate-with-service-workers/" rel="noopener noreferrer"&gt;https://felixgerschau.com/how-to-communicate-with-service-workers/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We choose the Broadcast API to get away with the need of the two parties to remember the ports to have a 1:1 communication channel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1050%2F1%2ANFN2uS3PocIlm9Y0R6Xvrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1050%2F1%2ANFN2uS3PocIlm9Y0R6Xvrg.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create a channel for communication&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BroadcastChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TOKEN_EXCHANGE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getAToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Listen to token response&lt;/span&gt;
    &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;// Send a token request to the main thread&lt;/span&gt;
    &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TOKEN_REQUEST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Changes in the container app
&lt;/h3&gt;

&lt;p&gt;The container app now needs to listen to the messages on the same broadcast channel &amp;amp; respond with a token.&lt;br&gt;
This allows up to keep the front end legacy code as-is &amp;amp; at the same time have a new authentication mechanism.&lt;/p&gt;

&lt;h4&gt;
  
  
  Things to note
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;As our solution is based on service workers, promises &amp;amp; Broadcast API, browser compatibility can be a limitation.&lt;/li&gt;
&lt;li&gt;We still had to re-factor the APIs to honor tokens in the request for authentication.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Must-Have Weapons in Your React Armory</title>
      <dc:creator>Gaurav Behere</dc:creator>
      <pubDate>Mon, 13 Sep 2021 05:48:48 +0000</pubDate>
      <link>https://dev.to/gauravbehere/must-have-weapons-in-your-react-armory-1pcc</link>
      <guid>https://dev.to/gauravbehere/must-have-weapons-in-your-react-armory-1pcc</guid>
      <description>&lt;p&gt;Weapons (tools) make a soldier (developer) effective. Advanced and effective weapons (tools) in your armory ensure you have the firepower to handle the complexity of an ever-growing code base.&lt;br&gt;
Let’s look at a few of the tools I used in my last project. These tools helped me to write code quickly yet maintain quality.&lt;/p&gt;



&lt;h2&gt;
  
  
  React Dev Tools
&lt;/h2&gt;

&lt;p&gt;Programming is 20% coding and 80% debugging. Debugging is what makes a programmer efficient in comparison to others.&lt;br&gt;
React Developer Tools let you inspect a React tree, including the component hierarchy, props, state, and more. To get started, just open the React Developer Tools and switch to the React Components or React Profiler tab.&lt;br&gt;
By selecting one of the components in the tree, you can inspect and edit its current props and state in the panel on the right. In the breadcrumbs, you can inspect the selected component, the component that created it, the component that created that one, and more.&lt;br&gt;
React developer tools are available for &lt;a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi" rel="noopener noreferrer"&gt;Chrome&lt;/a&gt; and &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/react-devtools" rel="noopener noreferrer"&gt;Firefox&lt;/a&gt; as an extension.&lt;/p&gt;



&lt;h2&gt;
  
  
  Styled Components
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F516%2F1%2ACrJ9gMVMHtMOhGgY1obVJg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F516%2F1%2ACrJ9gMVMHtMOhGgY1obVJg.png"&gt;&lt;/a&gt; &lt;br&gt;
While styling components, we also have to take care of vendor prefixes for cross-browser operability. If we’re using LESS or SASS we have to compile code to CSS.&lt;br&gt;
With a component being an individual entity and a basic building block for building apps, it’s recommended for styling to be included within the component, rather than the container app taking care of styling with class names.&lt;br&gt;
Styled components allow us to keep the styles within the component, coupled with the JavaScript code.&lt;br&gt;
Read about some more benefits &lt;a href="https://www.styled-components.com/docs/basics#motivation" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;h2&gt;
  
  
  React-Intl
&lt;/h2&gt;

&lt;p&gt;Having strings, a lot of text in the UI, and having to internationalize it can be painful at times. With the right translation based on browser locale or user preference, presenting the user interface in a different language can be tricky.&lt;br&gt;
React-Intl handles it in an elegant way, wrapping your components in a scope and rendering strings based on the locale.&lt;br&gt;
With support for formatting dates, numbers, plurals, etc out of the box, it makes handling such translations easy. Moreover, for a fully-fledged translation conversion, you can have translations based on languages you want to support and you can configure React-Intl to pick up the right translation file at runtime.&lt;br&gt;
Read more &lt;a href="https://github.com/formatjs/react-intl/blob/master/docs/Getting-Started.md#introduction" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;h2&gt;
  
  
  Storybook
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fprofile_images%2F1100804485616566273%2FsOct-Txm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fprofile_images%2F1100804485616566273%2FsOct-Txm.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; allows you to write and test components in isolation.&lt;br&gt;
When there are multiple people working on UI components that need integration at a later point in time, storybook makes it easier for individual developers to write and test their components in isolation.&lt;br&gt;
Moreover, the storybook also serves as a living document of what has been done so far. You can look at all the components at a glance and check how they behave. You can play with a component by modifying supplied props and testing its behavior.&lt;br&gt;
I may sound crazy if you’ve only worked with a smaller codebase but when projects grow, there are times when a developer ends up writing a component that already existed or a behavior variation of an existing component could have met the purpose. In such cases, the storybook acts as a go-to page to see what components &amp;amp; what behaviors already exist.&lt;br&gt;
Check out how you can add stories to your components and make it available as a storybook, &lt;a href="https://github.com/storybookjs/storybook" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;



&lt;h2&gt;
  
  
  React Testing Library
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftesting-library%2Freact-testing-library%2Fmain%2Fother%2Fgoat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Ftesting-library%2Freact-testing-library%2Fmain%2Fother%2Fgoat.png"&gt;&lt;/a&gt;&lt;br&gt;
It comes last in this piece but this is the most important one and a lifesaver when testing React apps.&lt;br&gt;
Based on this principle, and I quote the author,&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;The more your tests resemble the way your software is used, the more confidence they can give you.&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;The biggest confusion I have as a developer is when writing tests whether my suite is under mocked or over mocked. Am I testing with the right expectations?&lt;br&gt;
React Testing Library comes up with guidelines about what should be tested, allowing us to test the DOM changes and updates as good as what the end-user will perceive.&lt;br&gt;
Combine it with Jest and you get a robust set of APIs that you need to be able to render your components in isolation, mimic behavioral changes, and observe DOM changes.&lt;br&gt;
Get started &lt;a href="https://testing-library.com/docs/dom-testing-library/intro" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;br&gt;&lt;br&gt;
I have listed the tools that have helped me. That said, there may be tools that have helped you, which you think are better than the ones I’ve listed. I’d love to hear about them.

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>JavaScript - All The Things, Mostly</title>
      <dc:creator>Gaurav Behere</dc:creator>
      <pubDate>Wed, 01 Sep 2021 04:56:02 +0000</pubDate>
      <link>https://dev.to/gauravbehere/js-know-it-all-5f3b</link>
      <guid>https://dev.to/gauravbehere/js-know-it-all-5f3b</guid>
      <description>&lt;h2&gt;
  
  
  JavaScript - All The Things, Mostly
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Curated list of awesome JS resources
&lt;/h3&gt;



&lt;h2&gt;
  
  
  Books
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/javascript-the-good/9780596517748/"&gt;JavaScript: The Good Parts - Douglas Crockford&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/programming-javascript-applications/9781491950289/"&gt;Programming JavaScript Applications - Eric Elliott&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/javascript-the-definitive/9781491952016/"&gt;JavaScript: The Definitive Guide, 7th Edition - David Flanagan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://addyosmani.com/resources/essentialjsdesignpatterns/book/"&gt;Learning JavaScript Design Patterns - Addy Osmani&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/you-dont-know/9781491905241/"&gt;You Don't Know JS: ES6 &amp;amp; Beyond - Kyle Simpson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://exploringjs.com/es6/"&gt;Exploring ES6 - Axel Rauschmayer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/high-performance-javascript/9781449382308/"&gt;High Performance JavaScript - Nicholas C. Zakas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/javascript-for-kids/9781457189838/"&gt;JavaScript for Kids - Nick Morgan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/eloquent-javascript/9781593272821/"&gt;Eloquent JavaScript - Marijn Haverbeke&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://effectivejs.com/"&gt;Effective JavaScript - David Herman&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Video Tutorials
&lt;/h2&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=8aGhZQkoFbQ"&gt;What the heck is the event loop anyway? | Philip Roberts | JSConf EU&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=W6NZfCO5SIk"&gt;JavaScript Tutorial for Beginners: Learn JavaScript in 1 Hour [2020]&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Qqx_wzMmFeA"&gt;JavaScript Tutorial for Beginners - Full Course in 8 Hours [2020]&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=e-5obm1G_FY"&gt;Learning Functional Programming with JavaScript - Anjana Vakil - JSUnconf&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=hQVTIJBZook"&gt;JavaScript: The Good Parts&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=t3R3R7UyN2Y"&gt;ES6 and Beyond Workshop Part 1 at PayPal (Jan 2017)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=eOKQDh50ECU"&gt;ES6 and Beyond Workshop Part 2 at PayPal (March 2017)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=lil4YCCXRYc"&gt;Jafar Husain: Async Programming in ES7 | JSConf US 2015&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Bv_5Zv5c-Ts"&gt;JavaScript: Understanding the Weird Parts - The First 3.5 Hours&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=HF1luRD4Qmk"&gt;Debugging The Web (Chrome Dev Summit 2016)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=dxzBZpzzzo8"&gt;Rediscovering JavaScript by Venkat Subramaniam&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=p-iiEDtpy6I"&gt;Franziska Hinkelmann: JavaScript engines - how do they even? | JSConf EU&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=FmiQr4nfoPQ"&gt;Recursion, Iteration, and JavaScript: A Love Story - Anjana Vakil | JSHeroes 2018&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=PkZNo7MFNFg"&gt;Learn JavaScript - Full Course for Beginners&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=PFmuCDHHpwk"&gt;Object-oriented Programming in JavaScript: Made Super Simple | Mosh&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Courses
&lt;/h2&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://kentcdodds.com/workshops/javascript-fundamentals"&gt;JavaScript Fundamentals Workshop&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.codecademy.com/learn/introduction-to-javascript"&gt;Learn JavaScript&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.udemy.com/course/the-complete-javascript-course/"&gt;The Complete JavaScript Course 2020&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PL4cUxeGkcC9i9Ae2D9Ee1RvylH38dKuET"&gt;JavaScript Tutorials for Beginners&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLDyQo7g0_nsX8_gZAB8KD1lL4j4halQBJ"&gt;Getting Started With Javascript | Javascript Tutorial For Beginners&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.pluralsight.com/courses/javascript-best-practices"&gt;JavaScript Best Practices&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;a href="https://hackr.io/tutorials/learn-javascript"&gt;JavaScript Tutorials and Courses&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful Blogs/Articles
&lt;/h2&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/previous-versions/msdn10/ff852808(v=msdn.10)"&gt;Prototypes and Inheritance in JavaScript&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.sitepoint.com/proper-error-handling-javascript/"&gt;A Guide to Proper Error Handling in JavaScript&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developers.google.com/web/fundamentals/primers/service-workers"&gt;Service Workers: an Introduction&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;a href="https://dev.to/arnavaggarwal/10-javascript-concepts-you-need-to-know-for-interviews"&gt;10 JavaScript concepts you need to know for interviews&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Websites
&lt;/h2&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developers.google.com/web"&gt;Google Web Developers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://es6-features.org/"&gt;ECMAScript 6&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nodejs.org/en/docs/es6/"&gt;Node JS&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/JavaScript_basics"&gt;MDN&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://javascript.info/"&gt;JavaScript.info&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;a href="http://superherojs.com/"&gt;Superhero.js&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Dev Channels
&lt;/h2&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/c/JSConfEU/videos"&gt;JSConf&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/c/GoogleChromeDevelopers/videos"&gt;Google Chrome Developers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://web.dev/learn/"&gt;web.dev&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;a href="https://twitter.com/JavaScriptDaily"&gt;JavaScript Daily&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Publications/Magazines
&lt;/h2&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/tag/javascript"&gt;JavaScript on Medium&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.smashingmagazine.com/category/javascript"&gt;JavaScript on Smashing Magazine&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/t/javascript"&gt;JavaScript on Dev.to&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://javascriptweekly.com/"&gt;JavaScript Weekly&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;a href="https://nodeweekly.com/"&gt;Node Weekly&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful Github Links
&lt;/h2&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/leonardomso/33-js-concepts"&gt;33-js-concepts&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/lydiahallie/javascript-questions"&gt;JavaScript Questions&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/master/src/questions/javascript-questions.md"&gt;Front-end-Developer-Interview-Questions&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/DrkSephy/es6-cheatsheet"&gt;es6-cheatsheet&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;a href="https://github.com/ryanmcdermott/clean-code-javascript"&gt;clean-code-javascript&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  People
&lt;/h2&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/BrendanEich"&gt;BrendanEich&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/kentcdodds"&gt;Kent C. Dodds&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/addyosmani"&gt;Addy Osmani&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/paul_irish"&gt;Paul Irish&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/douglascrockford"&gt;Douglas Crockford&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/benawad/"&gt;Ben Awad&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/_ericelliott"&gt;Eric Elliott&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/dan_abramov"&gt;Dan Abramov&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/MarijnJH"&gt;Marijn Haverbeke&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/getify"&gt;Kyle Simpson&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/wesbos"&gt;Wes Bos&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;&lt;a href="https://github.com/DanWahlin"&gt;Dan Wahlin&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;




These resources have helped me a lot in keeping up with JS.
If you have a suggestion, please comment. I would love to read &amp;amp; add to this.&lt;/li&gt;
&lt;/ul&gt;

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