<?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: Herat Dhruv</title>
    <description>The latest articles on DEV Community by Herat Dhruv (@herat_dhruv).</description>
    <link>https://dev.to/herat_dhruv</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%2F1870033%2F5cef6342-3a24-4b1f-9c73-45a281cc2223.jpg</url>
      <title>DEV Community: Herat Dhruv</title>
      <link>https://dev.to/herat_dhruv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/herat_dhruv"/>
    <language>en</language>
    <item>
      <title>poEditor:- Workflow Automation</title>
      <dc:creator>Herat Dhruv</dc:creator>
      <pubDate>Thu, 04 Sep 2025 06:27:55 +0000</pubDate>
      <link>https://dev.to/herat_dhruv/poeditor-workflow-automation-1goj</link>
      <guid>https://dev.to/herat_dhruv/poeditor-workflow-automation-1goj</guid>
      <description>&lt;p&gt;Automation of PoEditor can save your lot of time&lt;/p&gt;

&lt;p&gt;In my case, developers updated translations only in en.json since they lacked PoEditor access. New local translations had to be manually synced to PoEditor for stakeholders—a time-consuming and error-prone process. &lt;/p&gt;

&lt;h2&gt;
  
  
  Automation Details
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// package.json
"update:translations:poeditor": "node ./locales/scripts/sync_translation.js",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the list of API can be used , before using it you need to generate API token in poEditor using your login&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// sync_translation.js
const LIST_TERMS_API = 'https://api.poeditor.com/v2/terms/list'
const ADD_TERMS_API = 'https://api.poeditor.com/v2/terms/add'
const UPDATE_TERMS_API = 'https://api.poeditor.com/v2/terms/update'
const UPDATE_TRANSLATIONS_API = 'https://api.poeditor.com/v2/translations/update'
const ADD_TRANSLATIONS_API = 'https://api.poeditor.com/v2/translations/add'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is my workflow for automation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const LANGUAGES = ['en'] // since all the developer updated the translation on local en.json file hence in my case i was targeting en.json as updated source / only source of truth.

// sync_translation.js
LANGUAGES.forEach(async (lang) =&amp;gt; {
  await syncTranslations(lang)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Workflow Automation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Fetch translations from PoEditor.&lt;/li&gt;
&lt;li&gt;Compare with en.json.&lt;/li&gt;
&lt;li&gt;Log updates in a local backup file.&lt;/li&gt;
&lt;li&gt;Add new terms to PoEditor via API with web reference.&lt;/li&gt;
&lt;li&gt;Tag updated terms so stakeholders can easily review and update.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For automation we can use reference or context of poEditor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjs0y8xvznw6wfquahavf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjs0y8xvznw6wfquahavf.png" alt="using a Reference in poEditor" width="800" height="719"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Tagging will help everyone to filter terms based on certain criteria&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F752fs97umtpc8jd8918z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F752fs97umtpc8jd8918z.png" alt="Tagging in poEditor to filter terms" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;&lt;br&gt;
In my case, I was surprised by how much time my team spent managing locale files from poEditor. Every update required a manual process before sharing with stakeholders:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the locale file from poEditor&lt;/li&gt;
&lt;li&gt;Sort translations using a third-party tool&lt;/li&gt;
&lt;li&gt;Compare poEditor files with the repository (since devs also updated translations directly)&lt;/li&gt;
&lt;li&gt;Merge changes between poEditor’s JSON and the repo’s JSON&lt;/li&gt;
&lt;li&gt;Update the repository with the final merged file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This repetitive workflow made a simple task unnecessarily time-consuming.&lt;/p&gt;

&lt;p&gt;This manual process took 2–4 days, demanded heavy focus, and often led to procrastination in pushing translations to production. As a result, it created a poor impression with operations and management—prompting me to pursue automation.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Within a couple of minutes, we can able upload the latest translation on poEditor. This saves time and efforts both. &lt;/li&gt;
&lt;li&gt;Stakeholders also aware about what they needs to be updated by using tagged filter.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>automation</category>
      <category>programming</category>
      <category>tooling</category>
    </item>
    <item>
      <title>How did i choose e2e automation framework 🩺 for my ongoing web porject</title>
      <dc:creator>Herat Dhruv</dc:creator>
      <pubDate>Sat, 04 Jan 2025 07:52:46 +0000</pubDate>
      <link>https://dev.to/herat_dhruv/lets-implement-e2e-automation-framework-in-your-project-1n41</link>
      <guid>https://dev.to/herat_dhruv/lets-implement-e2e-automation-framework-in-your-project-1n41</guid>
      <description>&lt;p&gt;This page covers intention and approach to implement e2e automation framework in your ongoing project&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Motivation&lt;/li&gt;
&lt;li&gt;Approach for Selecting e2e framework&lt;/li&gt;
&lt;li&gt;Cypress Vs Playwright POC Outcomes&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's end &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; vs &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; , it will be obvious outcome once your requirements are clear&lt;/p&gt;

&lt;h2&gt;
  
  
  My Motivation for Implementing E2E Testing
&lt;/h2&gt;

&lt;p&gt;As a web developer, my goal is to deliver changes to production as quickly as possible to evaluate their impact on end users. However, ensuring quality is crucial—I don’t want to release buggy updates. While I do write unit tests, their effectiveness often depends on tight feature deadlines, and they are limited to testing individual modules.&lt;/p&gt;

&lt;p&gt;Currently, we rely on the QA team to manually perform end-to-end (E2E) and smoke testing in lower environments like UAT. However, when there’s a strict deadline for high-priority features, I often need to wait for QA resources to become available. This delays feedback and makes the process less efficient.&lt;/p&gt;

&lt;p&gt;To address this, I discussed the situation with senior team members and began working on a proof of concept (POC) for implementing automated E2E test cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Key Considerations&lt;/em&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Budget and cost implications of the automation framework and CI/CD runners.&lt;/li&gt;
&lt;li&gt;Maintaining the speed and efficiency of the CI/CD pipeline.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Most importantly, ensuring that the QA team supports writing and maintaining test cases in the future.&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach aims to reduce dependency on manual testing, speed up feedback loops, and improve overall productivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking Down My Approach
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Research on Popular Frameworks and Their Costs
&lt;/h3&gt;

&lt;p&gt;I focused on identifying frameworks that meet the following criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong Community Support: To ensure availability of resources, troubleshooting help, and ongoing updates.
Built-in Browser Support: Should include major browsers out of the box.&lt;/li&gt;
&lt;li&gt;Reliability: Minimal flakiness to make the CI/CD pipeline more dependable.
Support for Parallel Execution: To speed up testing and enable faster rollouts.&lt;/li&gt;
&lt;li&gt;Debugging Features: Provides videos, screenshots, and analytical reports for quick debugging of failed or flaky E2E test cases.
Third-Party Integration: Easily extendable to third-party providers for comprehensive testing on various devices, operating systems, and reporting capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performing a Proof of Concept (POC)
&lt;/h3&gt;

&lt;p&gt;Based on the research, I shortlisted two frameworks: Cypress and Playwright. Other frameworks fell short due to their limitations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Puppeteer&lt;/strong&gt;: Lacks extensive built-in browser support, is less reliable, and has weaker community support compared to Cypress and Playwright. It also lacks native support for parallel execution.&lt;br&gt;
&lt;strong&gt;Selenium&lt;/strong&gt;: Although robust, it has a steeper learning curve and requires significant effort for initial setup and parallel execution, making it less efficient compared to the alternatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  POC Outcomes
&lt;/h2&gt;

&lt;p&gt;The analytical results of the POC highlight the strengths and weaknesses of the shortlisted frameworks and guide the decision for the most suitable E2E testing solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F5voqt38myo3xhvc9heui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F5voqt38myo3xhvc9heui.png" alt="out come of #cypress vs #playwright based on POC as per Requirement" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F97ohxvd3oqys3v1yh7us.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F97ohxvd3oqys3v1yh7us.png" alt="report of #cypress vs #playwright based on POC as per Requirement" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Based on the analysis above, there are significantly more negative outcomes (indicated by reds) with Cypress compared to Playwright. As a result, I chose Playwright as our E2E testing framework, tailored to meet our specific requirements.&lt;/p&gt;

&lt;p&gt;One standout feature of Playwright is its native E2E code generation tool, which is a game-changer. This makes it incredibly easy for our QA team to generate E2E tests and integrate them into the production pipeline with minimal modifications. This reduces the learning curve for the QA team and fosters better collaboration between QA and developers—a true win-win situation.&lt;/p&gt;

&lt;p&gt;While our QA team continues to play a vital role, adopting Playwright has significantly improved the reliability of our tests and the speed of rollouts in the production pipeline.&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>playwright</category>
      <category>testing</category>
      <category>automation</category>
    </item>
    <item>
      <title>Respond to the interview question about React performance optimization. 🚀</title>
      <dc:creator>Herat Dhruv</dc:creator>
      <pubDate>Mon, 21 Oct 2024 11:16:12 +0000</pubDate>
      <link>https://dev.to/herat_dhruv/how-to-answer-on-performance-optimisation-question-in-a-frontend-interview-40pc</link>
      <guid>https://dev.to/herat_dhruv/how-to-answer-on-performance-optimisation-question-in-a-frontend-interview-40pc</guid>
      <description>&lt;p&gt;I have been involved in conducting and participating in React frontend interviews many times over recent years.&lt;/p&gt;

&lt;p&gt;One observation I’ve made is that interviewers often ask about your experience with performance optimization. However, many candidates make the mistake of only discussing code-based optimizations, while interviewers are actually looking for your broader experience as a web developer, not just a React or framework-specific developer.&lt;/p&gt;

&lt;p&gt;Consider performance optimization as a system design question and provide a holistic answer based on your web development expertise. I'll share with you the best possible response based on my experience, so you can be well-prepared if you're asked this in an interview. If you deliver the following points effectively, the interviewer will view you as a strong candidate for frontend or web development roles.&lt;/p&gt;

&lt;p&gt;Let's break this answer down into six key segments:&lt;/p&gt;

&lt;p&gt;👨🏻‍💻 &lt;strong&gt;Code Performance Optimization&lt;/strong&gt;&lt;br&gt;
🌎 &lt;strong&gt;Network / API Layer Performance Optimization&lt;/strong&gt;&lt;br&gt;
🌐⛁ &lt;strong&gt;Caching / CDN&lt;/strong&gt;&lt;br&gt;
🗄️ &lt;strong&gt;Server Optimization&lt;/strong&gt;&lt;br&gt;
🛠️ &lt;strong&gt;Tools to Use&lt;/strong&gt;&lt;br&gt;
📊 &lt;strong&gt;Metrics to Follow&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Code Performance Optimization
&lt;/h2&gt;

&lt;p&gt;Here, we can discuss coding techniques that can improve performance. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hooks like &lt;code&gt;useCallback&lt;/code&gt;, &lt;code&gt;useMemo&lt;/code&gt;, and &lt;code&gt;React.memo&lt;/code&gt; can provide caching mechanisms. However, we should be cautious not to overuse them, as this can negatively impact performance.&lt;/li&gt;
&lt;li&gt;Techniques like &lt;code&gt;React.lazy&lt;/code&gt; and &lt;code&gt;Suspense&lt;/code&gt; can definitely improve performance by reducing the size of the main chunk, allowing for lazy loading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy loading images&lt;/strong&gt; on a webpage can help the HTML load faster in the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pagination&lt;/strong&gt; can also reduce the page size, thus improving performance.&lt;/li&gt;
&lt;li&gt;Using tools like &lt;strong&gt;Webpack/Vite bundle analyzers&lt;/strong&gt; can be useful in identifying heavy JS files, allowing us to reduce the file size on initial load.&lt;a href="https://dev.to/herat_dhruv/how-to-approach-for-performance-optimisation-2h4b"&gt;Resource&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Network / API Layer Performance Optimization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When navigating through the code, you should identify:&lt;/li&gt;
&lt;li&gt;Which API is "costly" or heavy (e.g., if the response is more than 9-10 MB). Such an API needs optimization.&lt;/li&gt;
&lt;li&gt;Which API is slow—consider adding server-side caching with tools like &lt;code&gt;Redis&lt;/code&gt; or &lt;code&gt;Memcached&lt;/code&gt; to get responses faster.&lt;/li&gt;
&lt;li&gt;For example, if your product API response is too large and causes loading delays, this is unacceptable. You can reduce the response size by using pagination or lazy loading images.&lt;/li&gt;
&lt;li&gt;A good practice would be to only send necessary data. For instance, in a "favourites" API, sending just the product_id to mark a product as a favourite is more efficient than sending the entire product object with all its properties.&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;GraphQL&lt;/code&gt; can also help adjust response sizes dynamically based on your needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Caching / CDN
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;As a frontend developer, we often serve assets like CSS, images, audio, or video, which can increase HTML page size and increase network retrieval times.&lt;/li&gt;
&lt;li&gt;Rather than fetching these assets directly from the server, it’s always better to retrieve them via a &lt;strong&gt;CDN (Content Delivery Network)&lt;/strong&gt;, which can be provided by services like AWS, GCP, and other major players.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Server Optimization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;React renders pages on the client side (i.e., in the browser), which uses client resources like CPU, processor, and network. While this may not be a big issue for desktop users, mobile users often have less computational power and slower network connections.&lt;/li&gt;
&lt;li&gt;To improve performance for mobile users, &lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt; can be a good solution. This allows major tasks like data fetching and HTML page generation to happen server-side, so the browser doesn’t have to wait for JavaScript files to load before rendering the HTML.&lt;/li&gt;
&lt;li&gt;Other techniques include &lt;strong&gt;database optimization&lt;/strong&gt; and applying &lt;strong&gt;ASG (Auto Scaling Group)&lt;/strong&gt; policies on servers using load balancers during peak hours to distribute the load, enhancing web performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Tools to Use
&lt;/h2&gt;

&lt;p&gt;Here are some tools you can use to analyze and enhance your website’s performance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lighthouse&lt;/li&gt;
&lt;li&gt;Sitespeed&lt;/li&gt;
&lt;li&gt;Pagespeed Insights&lt;/li&gt;
&lt;li&gt;Webpage Test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools generate reports that provide actionable insights for improving the performance score of your website.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Metrics to Follow
&lt;/h2&gt;

&lt;p&gt;Performance metrics to focus on include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FCP (First Contentful Paint)&lt;/li&gt;
&lt;li&gt;LCP (Largest Contentful Paint)&lt;/li&gt;
&lt;li&gt;CLS (Cumulative Layout Shift)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s important to note that &lt;strong&gt;LCP, CLS, and TBT&lt;/strong&gt; (Total Blocking Time) carry significant weight in performance scoring. Prioritize optimizing these metrics to eliminate performance bottlenecks on your site.&lt;/p&gt;

&lt;p&gt;Here’s how the weightage typically breaks down:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metrics&lt;/th&gt;
&lt;th&gt;Weights&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Largest Contentful Paint (LCP)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;25%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Blocking Time (TBT)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;30%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cumulative Layout Shift (CLS)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;25%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Please make sure to cover all of these points, as each one holds weight in showcasing your overall experience.&lt;/p&gt;

&lt;p&gt;Feel free to share your comments and feedback!&lt;/p&gt;

</description>
      <category>react</category>
      <category>interview</category>
      <category>frontend</category>
      <category>performance</category>
    </item>
    <item>
      <title>is it necessary to use lazy 😴 and suspense 🕵 everywhere in the repo? 👨‍💻 this could cause CLS 📊 issue in web performance.</title>
      <dc:creator>Herat Dhruv</dc:creator>
      <pubDate>Thu, 03 Oct 2024 18:21:35 +0000</pubDate>
      <link>https://dev.to/herat_dhruv/is-it-necessary-to-use-lazy-and-suspense-everywhere-in-the-repo-this-could-cause-cls-issue-in-web-performance-1cfb</link>
      <guid>https://dev.to/herat_dhruv/is-it-necessary-to-use-lazy-and-suspense-everywhere-in-the-repo-this-could-cause-cls-issue-in-web-performance-1cfb</guid>
      <description>&lt;p&gt;Recently i am working on web performance optimisation in my new organization. where i found one of the classic case which was causing a performance issue and impacting CLS webvital metric. &lt;/p&gt;

&lt;p&gt;Due to which i am excited to share this with you guys. So everyone should get benefited using this way of approaching a problem. &lt;/p&gt;

&lt;p&gt;One of the classic example when react suspense will no use.&lt;/p&gt;

&lt;p&gt;Parent component &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fetching data for child component lets say carousel&lt;/li&gt;
&lt;li&gt;passing carousel list to carousel component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Child component [Carousel component]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;display placeholder&lt;/li&gt;
&lt;li&gt;display list of carousel&lt;/li&gt;
&lt;li&gt;in case of no data it should not display placeholder as well as list of carousel and return null
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Pseudocode
import { lazy } from "react";
const CarouselComponent = lazy(() =&amp;gt; import("../pages/CarouselComponent"));

function ParentComponent(){

const {carouselData} = getCarousel();// carousel data fetching hook

return (
   &amp;lt;Suspense fallback={&amp;lt;CarouselPlaceholder /&amp;gt;}&amp;gt;
    &amp;lt;CarouselComponent carouselData={carouselData}&amp;gt;
   &amp;lt;/Suspense&amp;gt;
)};

function CarouselComponent({carouselData}){
// undefined can be received from API
if(!carouselData) return null; 

return (
  {carouselData.length &amp;gt; 0? &amp;lt;CarouselList /&amp;gt; : &amp;lt;CarouselPlaceholder /&amp;gt;})
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  What could be wrong in the above code?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fallback will not work
&lt;code&gt;CarouselComponent&lt;/code&gt; is wrapped with &lt;code&gt;Suspense&lt;/code&gt; but &lt;code&gt;CarouselComponent&lt;/code&gt; does not have any promises inside it due to which fallback ie. &lt;code&gt;&amp;lt;CarouselPlaceholder /&amp;gt;&lt;/code&gt; will never work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;by the time carouselData is undefined or null the component will not render anything. and once the data is available it will render  component with data. This will sudden shift in layout.&lt;/p&gt;

&lt;p&gt;This problem will introduce a CLS issue in your web application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;for such a small file of &lt;code&gt;CarouselComponent&lt;/code&gt;, which was not more than &lt;strong&gt;2Kb gzip&lt;/strong&gt; file it is necessary to use Lazy for code splitting? IMO we should not. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;please fill free to share your experience for such a weird issues while dealing with web performance.&lt;/p&gt;

</description>
      <category>react</category>
      <category>architecture</category>
      <category>suspense</category>
    </item>
    <item>
      <title>How did i approached for web performance optimisation at my new workplace 🚀</title>
      <dc:creator>Herat Dhruv</dc:creator>
      <pubDate>Fri, 13 Sep 2024 10:13:29 +0000</pubDate>
      <link>https://dev.to/herat_dhruv/how-to-approach-for-performance-optimisation-2h4b</link>
      <guid>https://dev.to/herat_dhruv/how-to-approach-for-performance-optimisation-2h4b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Have you used &lt;a href="https://react.dev/reference/react/lazy" rel="noopener noreferrer"&gt;React.Lazy and suspense&lt;/a&gt; but still not able to boost performance of your website in mobile devices.....Than.you are on right page to move forward&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The purpose of this page is to offer more advice on how to handle the problem of performance optimization for production websites.&lt;/p&gt;

&lt;p&gt;It appears that you attempted to divide the bundle chunks on the react production website using &lt;a href="https://react.dev/reference/react/lazy" rel="noopener noreferrer"&gt;`React.lazy}&lt;/a&gt; and `suspense} in React; however, this did not result in the anticipated improvement in your web performance score.&lt;/p&gt;

&lt;h2&gt;
  
  
  But why is it the case that lazy and suspense is not improving performance as expected for Mobile devices in 3G and 4G network Speed?
&lt;/h2&gt;

&lt;p&gt;Given that something extra was needed for your production website.....&lt;/p&gt;

&lt;p&gt;I was recently assigned a task to enhance the performance 🚀 of the production website for mobile users 📱. I initially thought 🤔 that we should load each route more lazily...💤💤💤, but I soon realised that this had already been done.&lt;/p&gt;

&lt;p&gt;I had also begun to wonder ✨ what might come next.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; First thing first that please install bundle analyzer plugin to give complete picture of bundles in repository.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my case it was webpack bundle anlyzer(&lt;a href="https://www.npmjs.com/package/webpack-bundle-analyzer" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/webpack-bundle-analyzer&lt;/a&gt;) and i installed it to existing project `` plugin and attempted to analyze each piece after that. Following that, I had a lot of suggestions about how to enhance the performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  What needs to be analyze once you install webpack bundle analyzer
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;analyze all the larger bundles

&lt;ul&gt;
&lt;li&gt;in my case main.js bundle was too large around 6 MB of Gzip size&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;analyze any duplication of bundle is there or not?

&lt;ul&gt;
&lt;li&gt;for me it was lodash.clonedeep and lodash both were available in main.js&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Are your vendor and polyfill package / chunks are separate? if not try to make it as separate chunks&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Main.bundle.js&lt;/strong&gt;&lt;br&gt;
main bundle size was too big [around 6-7 MB Gzip] which is causing increasing downloading time along with parsing time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;That means in browser, js main thread was too busy in downloading and parsing the main js file. now i am started thinking about offloading some work from main thread so one obvious approach is that we should reduce main bundle size.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to break the main bundle js file?
&lt;/h2&gt;

&lt;p&gt;in my case mine main bundle has lot of json files, which is related to translations / localization which was increasing 1.5 MB of main bundle size.&lt;/p&gt;

&lt;p&gt;Now, I did took away translations using &lt;strong&gt;lazy import&lt;/strong&gt; from main.js bundle. This gives &lt;strong&gt;40% performance score optimisation&lt;/strong&gt; 🚀. but this not done yet since we hardly reached from lighthouse performance score 25 to 35 only.&lt;/p&gt;

&lt;p&gt;then i started looking 👀 at other potential big files.&lt;/p&gt;

&lt;p&gt;One of them is moment js, which has numerous locales json files. not all of those locales was used in our website. due to which we thought of replacing moment js with a lightweight library, but doing so will require more code modifications and increase my workload in testing the entire website and lead to more errors. &lt;/p&gt;

&lt;p&gt;fortunately, a webpack plugin was already available. I was able to minimize the size of the moment.js file by utilizing that plugin [&lt;code&gt;[ContextReplacementPlugin](https://webpack.js.org/plugins/context-replacement-plugin/ )&lt;/code&gt;]. this plugin removed a lot of unnecessary locales json files from final bundle. this reduce bundle gzip size by 0.5 MB&lt;/p&gt;

&lt;p&gt;Reference Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/webpack-bundle-analyzer" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/webpack-bundle-analyzer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://webpack.js.org/plugins/context-replacement-plugin/" rel="noopener noreferrer"&gt;https://webpack.js.org/plugins/context-replacement-plugin/&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.dev/reference/react/lazy" rel="noopener noreferrer"&gt;https://react.dev/reference/react/lazy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay tuned many more will about to come... Thank you &lt;/p&gt;

</description>
      <category>performance</category>
      <category>react</category>
      <category>webpack</category>
      <category>javascript</category>
    </item>
    <item>
      <title>NX Playwright integration as a package in mono repo</title>
      <dc:creator>Herat Dhruv</dc:creator>
      <pubDate>Thu, 01 Aug 2024 19:22:40 +0000</pubDate>
      <link>https://dev.to/herat_dhruv/nx-playwright-integration-as-a-package-in-mono-repo-52c5</link>
      <guid>https://dev.to/herat_dhruv/nx-playwright-integration-as-a-package-in-mono-repo-52c5</guid>
      <description>&lt;p&gt;This post is intended for people who are having trouble integrating Playwright e2e as a separate package within the NX mono repository.&lt;/p&gt;

&lt;p&gt;Naturally, one way to handle this is to have a playwright in its own package and &lt;code&gt;package.json&lt;/code&gt; file and &lt;code&gt;node_modules&lt;/code&gt; inside that specific folder, but doing so eliminates the &lt;code&gt;node_modules&lt;/code&gt; centralization within a mono repository. ... a few more benefits that the NX mono repository offers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NX &amp;lt;= 17&lt;/li&gt;
&lt;li&gt;Playwright &amp;lt;= 1.45&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;NX provide a plugin called as &lt;a href="https://nx.dev/nx-api/playwright" rel="noopener noreferrer"&gt;@nx/playwright&lt;/a&gt; using it commands we can create a e2e app automatically, unfortunately This is not a case for NX-17&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is the solution which worked for me&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Setting up playwright E2E as NX mono repo package&lt;br&gt;
We took the following actions to integrate playwright as an NX package because the @nx/playwright plugin, which is available to set the e2e folder within an NX mono repository, did not function well with the way the project was currently built up.&lt;/p&gt;

&lt;p&gt;Final Folder structure : /apps/&lt;code&gt;&amp;lt;e2e-package-name&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP -1 Run command below commands&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;npm install playwright --save-dev&lt;/li&gt;
&lt;li&gt;npx playwright install&lt;/li&gt;
&lt;li&gt;npm i -D @playwright/test&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;STEP -2 create a folder and files&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create a folder apps/&lt;code&gt;&amp;lt;e2e-package-name&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;create apps/&lt;code&gt;&amp;lt;e2e-package-name&amp;gt;&lt;/code&gt;/tests folder and add below file as &lt;code&gt;example.spec.ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { test, expect } from '@playwright/test';

test('page has title', async ({ page }) =&amp;gt; {
  await page.goto('http://goolee.com');
  await expect(page).toHaveTitle(/Google/);
});

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;create &lt;code&gt;&amp;lt;e2e-package-name&amp;gt;&lt;/code&gt;/playwright.config.ts
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests', // Directory for test files
  fullyParallel: true,
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
//  webServer: {
//    command: 'npx nx serve my-app', // Command to start the app
//    url: 'http://localhost:8765',
//    timeout: 120 * 1000,
//    reuseExistingServer: !process.env.CI,
//  },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;STEP -3 setup command to execute&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; create a &lt;code&gt;&amp;lt;e2e-package-name&amp;gt;&lt;/code&gt;/project.json
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "name": "`&amp;lt;e2e-package-name&amp;gt;`",
    "root": "apps/`&amp;lt;e2e-package-name&amp;gt;`",
    "sourceRoot": "apps/`&amp;lt;e2e-package-name&amp;gt;`/src",
    "projectType": "application",
    "targets": {
      "e2e": {
        "executor": "nx:run-commands",
        "options": {
          "command": "npx playwright test",
          "forwardAllArgs": true
        }
      }
    }
  }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;STEP - 4 Run the command to execute e2e from Root directory&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npx nx run :e2e OR&lt;/li&gt;
&lt;li&gt;npx nx run :e2e --headed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please note &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace the URL in example.spec.ts it will work on local / eternal website. &lt;/li&gt;
&lt;li&gt;Also replace &lt;code&gt;&amp;lt;e2e-package-name&amp;gt;&lt;/code&gt; with your package name to make all the step executable.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nx</category>
      <category>playwright</category>
      <category>monorepo</category>
      <category>plugin</category>
    </item>
  </channel>
</rss>
