<?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[Shivam Singhal's Blog]]></title><description><![CDATA[Devrel Engineer | Community Manager | Connect with me on [GitHub](https://github.com/championshuttler) or [Twitter](https://twitter.com/idkhtml)]]></description><link>https://championshuttler.in</link><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 03:12:16 GMT</lastBuildDate><atom:link href="https://championshuttler.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Creating accordions with native HTML]]></title><description><![CDATA[Accordions are one of the most commonly used UI components for any website. For example FAQs section of the website, where only the question is shown, and when clicked the answer just opens up.
Generally, we handle this by creating 2 divs and adding ...]]></description><link>https://championshuttler.in/creating-accordions-with-native-html</link><guid isPermaLink="true">https://championshuttler.in/creating-accordions-with-native-html</guid><category><![CDATA[HTML5]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Shivam Singhal]]></dc:creator><pubDate>Sat, 12 Dec 2020 14:29:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1607777104363/Qqzw9bEmX.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607783320825/-6OUJRgjj.png" alt="html5.png" /></p>
<p>Accordions are one of the most commonly used UI components for any website. For example FAQs section of the website, where only the question is shown, and when clicked the answer just opens up.
Generally, we handle this by creating 2 <code>divs</code> and adding some javascript to handle the open and close of the accordion. But recently I stumbled upon this hidden gem in HTML that eliminates the need of all this - <a target="_blank" href="https://developer.mozilla.org/docs/Web/HTML/Element/details"><code>&lt;details&gt;</code></a></p>
<p>We can simply design a simple FAQ or summary section with <code>&lt;details&gt;</code> HTML tag without using Javascript!!! 🤯🤯🤯.
And the best part... it is supported by all the modern browsers (obviously except IE :( ) - <a target="_blank" href="https://caniuse.com/?search=details">browser compatibility</a>.  </p>
<h3 id="using-lessdetailsgreater-tag">Using <code>&lt;details&gt;</code> tag</h3>
<p>There are two elements here: <code>&lt;details&gt;</code> and <code>&lt;summary&gt;</code>. <code>&lt;details&gt;</code> is the wrapper for all the content you want to show and hide, and <code>&lt;summary&gt;</code> contains the — well, the summary and title of the section. <code>&lt;summary&gt;</code> is optional, if you do not add it, the browser will use some default text. For example, in Firefox and Chrome, it is <code>Details</code>. Below is a sample HTML markup:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">details</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">summary</span>&gt;</span>Details<span class="hljs-tag">&lt;/<span class="hljs-name">summary</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Something small enough to escape casual notice.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">details</span>&gt;</span>
</code></pre>
<p>And it will render like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607783339501/1lnJk1ska.gif" alt="1.gif" /></p>
<p>This markup can be designed with CSS as any other HTML element. Now for creating beautiful accordions all you need is just HTML and CSS (and a will to let go of IE).</p>
<p>Demo: <a target="_blank" href="https://bit.ly/htmldetails">https://itsopensource.com/demos/details/</a></p>
<h3 id="references">References</h3>
<ul>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details">MDN: details</a></li>
</ul>
<p>Cheers.</p>
]]></content:encoded></item><item><title><![CDATA[Content Security Policy - protect your website from XSS attacks]]></title><description><![CDATA[Problem
It's very common while building any project we use certain third party libraries, in the case of Javascript; npm packages, which recursively use more packages, and eventually your code includes a huge chunk of third party code.There is nothin...]]></description><link>https://championshuttler.in/content-security-policy-protect-your-website-from-xss-attacks</link><guid isPermaLink="true">https://championshuttler.in/content-security-policy-protect-your-website-from-xss-attacks</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Shivam Singhal]]></dc:creator><pubDate>Tue, 08 Dec 2020 12:48:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1607431666349/sJSHM36Mo.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="problem">Problem</h3>
<p>It's very common while building any project we use certain third party libraries, in the case of Javascript; <code>npm packages</code>, which recursively use more packages, and eventually your code includes a huge chunk of third party code.<br />There is nothing wrong with it, there is no point re-inventing the wheel. We include the required library, make our code work, write tests. Deploy to a staging environment, pass through automation and finally deploy to production.  </p>
<p>The problem is when a library tries to load remote content on our website. It can be an image, font, style, or even Javascript. This content bypasses all our tests, checks, and is executed directly on production. Even worse we don't know where the content is being served from.</p>
<h3 id="content-security-policy">Content Security Policy</h3>
<p>Content Security Policy (CSP) is a <a target="_blank" href="https://www.w3.org/TR/CSP3/">W3C specification</a> that helps to avoid <code>XSS</code> attacks. CSP enables developers to define rules for fetching the resources(images, javascript, fonts, etc.) on the client browser. Developers can define policies to allow/restrict loading any resource, restrict resources to load only from certain domains, and disallow from any other domain. For example, you can write a CSP to restrict browsers to load images only from <code>example.com</code>, any images from other domains will be not loaded and would throw errors. In addition to resources, CSP also offers control over the embeds.<br />In the following example, the CSP forces to load images/scripts only from self domain and prevents the loading of images from other domains.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607431486341/8EJu8TM2g.png" alt="image.png" /></p>
<p><em>From the <a target="_blank" href="https://www.w3.org/TR/CSP3/">W3c specification</a> docs:</em> </p>
<blockquote>
<p>One of the CSP goal is to mitigate the risk of content-injection attacks by giving developers fairly granular control over</p>
<ul>
<li>The resources which can be requested (and subsequently embedded or executed) on behalf of a specific Document or Worker</li>
<li>The execution of inline script</li>
<li>Dynamic code execution (via eval() and similar constructs)</li>
<li>The application of inline style</li>
</ul>
</blockquote>
<h3 id="how">How</h3>
<p>CSP can be implemented in following two ways:</p>
<ol>
<li>Specify in <strong>HTTP headers</strong> <pre><code class="lang-TEXT">Content-Security-Policy: __Policy__
</code></pre>
</li>
<li>Specify in <strong>META tags</strong> <pre><code class="lang-HTML"><span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"Content-Security-Policy"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">" __Policy__ "</span>&gt;</span>
</code></pre>
</li>
</ol>
<h4 id="defining-a-policy">Defining a policy</h4>
<p>The Policy is the accumulation of directives which defines the allowed location of each resource, no directive means allowed for all. Some of the useful directives are the following:</p>
<ul>
<li><em>default-src</em> : This defines the loading policy for all types of resources.</li>
<li><em>script-src</em> : This defines the loading policy for all javascript, from where javascript can be loaded.</li>
<li><em>img-src</em> : This defines the loading policy for all images, from where images can be loaded. </li>
</ul>
<p>List of directives for the other resources is <a target="_blank" href="https://developers.google.com/web/fundamentals/security/csp#policy_applies_to_a_wide_variety_of_resources">here</a>.</p>
<p>Some examples of policies are:</p>
<ol>
<li><pre><code>Content-<span class="hljs-keyword">Security</span>-<span class="hljs-keyword">Policy</span>: <span class="hljs-keyword">default</span>-src <span class="hljs-string">'self'</span>;
</code></pre>This would allow resources only from the same domain, and all other resources will fail to load.</li>
<li><pre><code>Content-<span class="hljs-keyword">Security</span>-<span class="hljs-keyword">Policy</span>: img-src example.com;
</code></pre>This would allow images only from <code>example.com</code>, and all other images will fail to load.</li>
<li><pre><code>Content-<span class="hljs-keyword">Security</span>-<span class="hljs-keyword">Policy</span>: <span class="hljs-keyword">default</span>-src <span class="hljs-string">'self'</span>; img-src example.com;
</code></pre>This would allow any resources to load only if from the same domain, except images which can be from <code>example.com</code> too.</li>
</ol>
<h4 id="reporting">Reporting</h4>
<p>CSP also provides a way to send violation reports, in case any logging is required, via <code>report-uri</code> directive. </p>
<pre><code class="lang-TEXT">`Content-Security-Policy: default-src 'self'; report-uri http://example.com/cspfails`
</code></pre>
<p>The reports will be sent as POST request and with following JSON: </p>
<pre><code class="lang-JSON">{
 <span class="hljs-attr">"csp-report"</span>: {
   <span class="hljs-attr">"document-uri"</span>: <span class="hljs-string">"http://example.com/"</span>,
   <span class="hljs-attr">"referrer"</span>: <span class="hljs-string">""</span>,
   <span class="hljs-attr">"blocked-uri"</span>: <span class="hljs-string">"http://example.com/some_malware.js"</span>,
   <span class="hljs-attr">"violated-directive"</span>: <span class="hljs-string">"default-src self"</span>,
   <span class="hljs-attr">"original-policy"</span>: <span class="hljs-string">"default-src 'self'; report-uri http://example.com/cspfails"</span>
 }
}
</code></pre>
<p><br /></p>
<h3 id="risks">Risks</h3>
<p>Before defining a CSP you should be completely aware of all the resources and respective origin required for your webapp, else some vital resources may be blocked and eventually random bugs. 
In case you are not sure what all resources are being required for running your web page smoothly, you can implement the CSP in reporting mode, in this way the violations will be reported but no resource will be blocked, once you are sure what are the resources really required, you can implement CSP. To do this instead of <code>Content-Security-Policy</code> we need to use <code>Content-Security-Policy-Report-Only</code> header. </p>
<pre><code>Content-<span class="hljs-keyword">Security</span>-<span class="hljs-keyword">Policy</span>-Report-<span class="hljs-keyword">Only</span>: __Policy__ + report-uri
</code></pre><h3 id="resources">Resources</h3>
<ul>
<li>https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP</li>
<li>https://owasp.org/www-community/attacks/Content_Security_Policy</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to call a function on URL change in javascript]]></title><description><![CDATA[Modern JS frameworks tend not to reload the page but manipulate DOM and change URL path for internal navigation, for performance and smooth UX. But since there is no page reload, window.onload event does not get triggered for subsequent navigation. W...]]></description><link>https://championshuttler.in/how-to-call-a-function-on-url-change-in-javascript</link><guid isPermaLink="true">https://championshuttler.in/how-to-call-a-function-on-url-change-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[React]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Shivam Singhal]]></dc:creator><pubDate>Sat, 05 Dec 2020 19:01:27 GMT</pubDate><content:encoded><![CDATA[<p>Modern JS frameworks tend not to reload the page but manipulate DOM and change URL path for internal navigation, for performance and smooth UX. But since there is no page reload, <code>window.onload</code> event does not get triggered for subsequent navigation. We run into a situation where we need to call a function whenever URL path changes (not the hash).</p>
<h3 id="problem">Problem</h3>
<p>The <a target="_blank" href="https://itsopensource.com/"><code>itsopensource.com</code></a> blog is built using <a target="_blank" href="https://www.gatsbyjs.org/">gatsby</a>, we wanted to add google analytics to this, but instead of using google tag manager, we tried to restrict what <a target="_blank" href="https://github.com/tsl143/itsopensource/blob/master/src/html.js#L32">data</a> is sent to google and in this process, we need to send XHR request on every page load. We created a function <code>sendTelemetry</code> and called it on <code>window.onload</code>. This works as expected (partially), whenever the page is loaded the XHR is sent, but gatsby do not reload the page while changing the URL when any blog link is clicked, so XHR is sent only once per session and not on subsequent page loads.<br />Javascript does not provide any native listener to path change (not hashchange).</p>
<h3 id="solution">Solution</h3>
<p>The <code>history</code> API maintains complete the navigation state. Whenever a new page is navigated <code>history.pushState</code> is called and page is added to the state. That means this event is called whenever the URL changes. We hooked our function on this, and done :)</p>
<pre><code class="lang-Javascript">(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">history</span>)</span>{
    <span class="hljs-keyword">var</span> pushState = history.pushState;
    history.pushState = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">state</span>) </span>{
      <span class="hljs-comment">// YOUR CUSTOM HOOK / FUNCTION</span>
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'I am called from pushStateHook'</span>);
      <span class="hljs-keyword">return</span> pushState.apply(history, <span class="hljs-built_in">arguments</span>);
    };
})(<span class="hljs-built_in">window</span>.history);
</code></pre>
<h3 id="demo">Demo</h3>
<p>A quick demo can be the following:</p>
<ol>
<li>Open the browser console on this very page.</li>
<li>Paste the above-written code snippet.</li>
<li>Keep console open and navigate various pages on this blog</li>
<li>You should see a message in console on every navigation.</li>
</ol>
<p><br /></p>
<p><em>The first choice for the title was <code>how to hook a function on history.pushState</code>.</em>  </p>
<p>Reference: <a target="_blank" href="https://stackoverflow.com/questions/4570093/how-to-get-notified-about-changes-of-the-history-via-history-pushstate">stackoverflow</a>  😉</p>
]]></content:encoded></item><item><title><![CDATA[How to Reduce Node Docker Image Size by 10X]]></title><description><![CDATA[Dockerizing an application is simple, effective, but optimizing the size of Docker Image is the tricky part. Docker is easy to use but once the application starts scaling, the image size inflates exponentially. In general, the node docker image size ...]]></description><link>https://championshuttler.in/how-to-reduce-node-docker-image-size-by-10x</link><guid isPermaLink="true">https://championshuttler.in/how-to-reduce-node-docker-image-size-by-10x</guid><category><![CDATA[Docker]]></category><category><![CDATA[docker images]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Shivam Singhal]]></dc:creator><pubDate>Fri, 04 Dec 2020 15:56:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1607097348038/HUUxBiAt3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Dockerizing an application is simple, effective, but optimizing the size of Docker Image is the tricky part. Docker is easy to use but once the application starts scaling, the image size inflates exponentially. In general, the node docker image size of the applications is over 1 GB most of the time.</p>
<h3 id="why-the-size-matters">Why the Size matters</h3>
<ol>
<li><p>Large docker image sizes - Bigger image size requires more space means increased expense.</p>
</li>
<li><p>Long build durations - It takes a longer time to push the images over the network and results in CI Pipeline delays.</p>
</li>
</ol>
<h3 id="lets-start-the-optimization">Let’s Start The Optimization</h3>
<p>Here is our <a target="_blank" href="https://github.com/championshuttler/fluentbit-dashboard">demo application</a> built using the VueJS Application. </p>
<p>Here is the initial Dockerfile.</p>
<pre><code class="lang-BASH">FROM node:10

WORKDIR /app

COPY . /app

EXPOSE 8080

RUN npm install http-server -g

RUN npm install &amp;&amp; npm run build

CMD http-server ./dist
</code></pre>
<p>The size of this image is:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607097114681/PHdOCJy87.png" alt="docker1.png" /></p>
<p>It is 1.34GB! Whoops!</p>
<p>Let's start optimizing step by step</p>
<p>1) Use <strong>Multi-Stage</strong> Docker Builds</p>
<p>Multi-stage builds make it easy to optimize Docker images by using multiple <strong>intermediate</strong> images in a single Dockerfile. Read more about it <a target="_blank" href="https://docs.docker.com/develop/develop-images/multistage-build/">here</a>. By using multi-stage builds, we can install all dependencies in the build image and copy them to the leaner runtime image.</p>
<pre><code class="lang-BASH">FROM node:10 AS BUILD_IMAGE

WORKDIR /app

COPY . /app

EXPOSE 8080

RUN npm install &amp;&amp; npm run build

FROM node:10

WORKDIR /app

<span class="hljs-comment"># copy from build image</span>
COPY --from=BUILD_IMAGE /app/dist ./dist
COPY --from=BUILD_IMAGE /app/node_modules ./node_modules

RUN npm i -g http-server

CMD http-server ./dist
</code></pre>
<p>Now the size of this image is 1.24GB:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607097203534/bisnMUkhX.png" alt="docker2.png" />
2) Remove Development Dependencies and use <strong>Node Prune</strong> Tool</p>
<p>node-prune is an open-source tool for removing unnecessary files from the node_modules folder. Test files, markdown files, typing files and *.map files in Npm packages are not required at all in the production environment generally, most of the developers do not remove them from the production package. By using node-prune it can safely be removed.</p>
<p>We can use this to remove Development Dependencies:</p>
<pre><code class="lang-BASH">npm prune --production
</code></pre>
<p>After making these changes <code>Dockerfile</code> will look like:</p>
<pre><code class="lang-BASH">FROM node:10 AS BUILD_IMAGE

RUN curl -sfL https://install.goreleaser.com/github.com/tj/node-prune.sh | bash -s -- -b /usr/<span class="hljs-built_in">local</span>/bin

WORKDIR /app

COPY . /app

EXPOSE 8080

RUN npm install &amp;&amp; npm run build

<span class="hljs-comment"># remove development dependencies</span>
RUN npm prune --production

<span class="hljs-comment"># run node prune</span>
RUN /usr/<span class="hljs-built_in">local</span>/bin/node-prune

FROM node:10

WORKDIR /app

<span class="hljs-comment"># copy from build image</span>
COPY --from=BUILD_IMAGE /app/dist ./dist
COPY --from=BUILD_IMAGE /app/node_modules ./node_modules

RUN npm i -g http-server

CMD http-server ./dist
</code></pre>
<p>By using this we reduced the overall size to 1.09GB</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607097269694/FVYDmJnvM.png" alt="docker3.png" /></p>
<p>3) Choose <strong>Smaller Final Base Image</strong></p>
<p>When dockerizing a node application, there are lots of <a target="_blank" href="https://hub.docker.com/_/node/">base images</a> available to choose from.</p>
<p>Here we will use <strong>alpine</strong> image; alpine is a lean docker image with minimum packages but enough to run node applications.</p>
<pre><code class="lang-BASH">FROM node:10 AS BUILD_IMAGE

RUN curl -sfL https://install.goreleaser.com/github.com/tj/node-prune.sh | bash -s -- -b /usr/<span class="hljs-built_in">local</span>/bin

WORKDIR /app

COPY . /app

EXPOSE 8080

RUN npm install &amp;&amp; npm run build

<span class="hljs-comment"># remove development dependencies</span>
RUN npm prune --production

<span class="hljs-comment"># run node prune</span>
RUN /usr/<span class="hljs-built_in">local</span>/bin/node-prune

FROM node:10-alpine

WORKDIR /app

<span class="hljs-comment"># copy from build image</span>
COPY --from=BUILD_IMAGE /app/dist ./dist
COPY --from=BUILD_IMAGE /app/node_modules ./node_modules

RUN npm i -g http-server

CMD http-server ./dist
</code></pre>
<p>By using this <code>Dockerfile</code> the image size dropped to <code>157MB</code> \o/</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607097284035/eF0aF7cDw.png" alt="docker4.png" /></p>
<h3 id="conclusion">Conclusion</h3>
<p>By applying these 3 simple steps, we reduced our docker image size by 10 times.</p>
<p>Cheers!</p>
]]></content:encoded></item></channel></rss>