<?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>Forem: Chan Ro</title>
    <description>The latest articles on Forem by Chan Ro (@chanro).</description>
    <link>https://forem.com/chanro</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%2F1109696%2Ff7bba5f8-6abf-422d-acc5-e3b72ecf327a.png</url>
      <title>Forem: Chan Ro</title>
      <link>https://forem.com/chanro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/chanro"/>
    <language>en</language>
    <item>
      <title>Massive node_modules in production issue</title>
      <dc:creator>Chan Ro</dc:creator>
      <pubDate>Wed, 25 Oct 2023 02:21:48 +0000</pubDate>
      <link>https://forem.com/chanro/production-nodemodules-massive-edm</link>
      <guid>https://forem.com/chanro/production-nodemodules-massive-edm</guid>
      <description>&lt;p&gt;Sometimes node_modules become massive that it makes hard and longer to deploy codes to the production environment. In this blog, I want to cover a few things that can be done to reduce node_modules size.&lt;/p&gt;

&lt;h2&gt;
  
  
  npm commands
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When deploying codes to production, &lt;code&gt;devDependencies&lt;/code&gt; should be excluded as dependencies under that property literally for development purposes Eg. jest, typescript references etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run &lt;strong&gt;&lt;code&gt;npm ci --production&lt;/code&gt;&lt;/strong&gt; command to exclude &lt;code&gt;devDependencies&lt;/code&gt; from &lt;code&gt;node_modules&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sometimes after &lt;code&gt;npm install&lt;/code&gt;, npm list shows the dependency tree which isn't necessarily the same as the &lt;code&gt;node_modules&lt;/code&gt; file tree. However, this can be simplified by running&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run &lt;strong&gt;&lt;code&gt;npm dedupe&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Unify sub dependencies version
&lt;/h2&gt;

&lt;p&gt;Sometimes developer faces a situation where multiple dependencies require sub-dependency but npm install multiple as they use different versions from each other. Eg axios, aws-sdk.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In case, those dependencies are client libraries from your side, then you can simply update &lt;code&gt;package.json&lt;/code&gt; in client libraries to use the same dependency version
Eg. 
Below will install 2 &lt;code&gt;aws-sdk&lt;/code&gt; packages into node_modules
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;library-a
 |-----&amp;gt; aws-sdk@2.1.0
library-b
 |-----&amp;gt; aws-sdk@2.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below will install 1 &lt;code&gt;aws-sdk&lt;/code&gt; package as there's only one version&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;library-a
 |-----&amp;gt; aws-sdk@2.2.0
library-b
 |-----&amp;gt; aws-sdk@2.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Usage of &lt;code&gt;overrides&lt;/code&gt; property from &lt;code&gt;package.json&lt;/code&gt; can also resolve multiple versions issue.
Eg.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  ...,
  "dependencies": {
    "library-a": "1.0.0",
    "library-b": "1.0.5",
    ...
  },
  "overrides": {
    "library-a": {
      "aws-sdk: "2.2.0"
    },
    "library-b": {
      "aws-sdk: "2.2.0"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Remove unnecessary packages
&lt;/h2&gt;

&lt;p&gt;Sometimes developers tend to solve problems with npm packages and sometimes it's not good practice as it will pile up the size of node_modules quickly.&lt;br&gt;
Common examples are &lt;code&gt;lodash&lt;/code&gt;, &lt;code&gt;ramda&lt;/code&gt;, and etc.&lt;br&gt;
Try to avoid using these kind of libraries. If you can create it relatively quickly then just do it. Don't be lazy&lt;/p&gt;

&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The most useful use case is AWS lambda. AWS lambda has a size limitation (250mb unzip size) thus, having too many packages or duplicated dependencies may be a big cause of the issue.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>npm</category>
    </item>
    <item>
      <title>Elasticsearch bulk reindex strategy</title>
      <dc:creator>Chan Ro</dc:creator>
      <pubDate>Fri, 08 Sep 2023 06:28:47 +0000</pubDate>
      <link>https://forem.com/chanro/elasticsearch-bulk-reindex-strategy-1mk5</link>
      <guid>https://forem.com/chanro/elasticsearch-bulk-reindex-strategy-1mk5</guid>
      <description>&lt;h3&gt;
  
  
  What is reindexing?
&lt;/h3&gt;

&lt;p&gt;Elasticsearch redindexing is rebuilding index using the data that are already stored in the Elasticsearch table to replace old index.&lt;/p&gt;

&lt;p&gt;Now, the question is &lt;strong&gt;why do we need to reindex&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Elasticsearch is NoSQL database that is not schemaless, means each object property in Elasticsearch needs a data type (Elasticsearch sets data type to &lt;code&gt;text&lt;/code&gt; and &lt;code&gt;keyword&lt;/code&gt; by default). So There's some restriction Elasticsearch when we need to change data type of a existing property.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example case
&lt;/h3&gt;

&lt;p&gt;For a simple example, let's say we have a schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "properties" : {
    "phoneNumber" : {
      "type" : "keyword"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, while developement, development team realised that the &lt;code&gt;phoneNumber&lt;/code&gt; property needs to be &lt;code&gt;number&lt;/code&gt; to support sorting by numeric. Thus, the team changed the schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "properties" : {
    "phoneNumber" : {
      "type" : "number"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when the team tries to update schema/mappings, this will throw an error because there are records already indexed and values cannot be converted into numbers so only way to resolve this is by &lt;strong&gt;running reindex sequence&lt;/strong&gt; For more &lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html#:~:text=Except%20for%20supported%20mapping%20parameters,settings%20for%20a%20data%20stream."&gt;info&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reindexing small database
&lt;/h3&gt;

&lt;p&gt;Reindexing a small database is pretty simple. You can just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST _reindex
{
  "source": {
    "index": "my-index-000001"
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reindexing large database
&lt;/h3&gt;

&lt;p&gt;There is a problom with reindexing a large database. The process reindexing needs to copy each records to new index(indice) so the process itself is not fast and in large database, it will take quite a while to complete the process. (I am talking about hours or maybe days..)&lt;/p&gt;

&lt;p&gt;But that does not mean users cannot read data from old index while reindex is happening. However, what if users adding more records while reindexing is under progress? Then we may or may not lose these new records.&lt;/p&gt;

&lt;p&gt;In reality, we need to somehow allow users to access the data while reindexing is happening (&lt;strong&gt;Dynamic reindexing&lt;/strong&gt;) because we cannot let users to wait for hours or days (Unless you have a good excuse for clients and put your application under maintenance.)&lt;/p&gt;

&lt;h4&gt;
  
  
  Alias
&lt;/h4&gt;

&lt;p&gt;Core key of the solution is &lt;strong&gt;Alias&lt;/strong&gt;. Alias is secondary name that we can set onto index(indice) and you can set same alias onto multiple indexes(indice) and then we can access those indexes by using alias name. (&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/aliases.html"&gt;Link&lt;/a&gt;)&lt;/p&gt;

&lt;h4&gt;
  
  
  Approach 1.
&lt;/h4&gt;

&lt;p&gt;Simple approach where we set alias on both old and new index so that we can read data from both indexes and ensures that none of additional records is missed while reindex is running in the background.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MFw2CnHl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1xffhfucb6m5516jm2gv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MFw2CnHl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1xffhfucb6m5516jm2gv.png" alt="Image description" width="624" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the problem with this is that this will show duplicated results on read as reindex is copying data from old to new index.&lt;/p&gt;

&lt;h4&gt;
  
  
  Approach 2.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zW0-Lir7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gst9013j6nrv02hb6me.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zW0-Lir7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2gst9013j6nrv02hb6me.png" alt="Image description" width="800" height="224"&gt;&lt;/a&gt; (Sorry for low quality img)&lt;/p&gt;

&lt;p&gt;In this approach, I separated into two indexes as well as alias, &lt;strong&gt;writer&lt;/strong&gt; and &lt;strong&gt;reader&lt;/strong&gt; but writer index with 2 alias (reader and writer). On reindexing, we will create another 2 indexes, one for writer and one for reader.&lt;/p&gt;

&lt;p&gt;Then I ran reindexing from old reader and writer to new reader index and removed writer alias from old writer index so that users can no longer add new records into old writer index. And added writer alias to the new writer index which is now the index for adding new records.&lt;/p&gt;

&lt;p&gt;After reindex finishes, I moved the reader alias to the new reader index and then removed old indexes safely.&lt;/p&gt;

&lt;p&gt;This way, users can read data while reindexing and also new records can be added without worrying reindexing (This excludes regarding available data nodes.. thats different story)&lt;/p&gt;

</description>
      <category>elasticsearch</category>
    </item>
    <item>
      <title>Queue actions in optimistic updates</title>
      <dc:creator>Chan Ro</dc:creator>
      <pubDate>Tue, 05 Sep 2023 08:46:46 +0000</pubDate>
      <link>https://forem.com/chanro/hash-actions-in-optimistic-updates-215g</link>
      <guid>https://forem.com/chanro/hash-actions-in-optimistic-updates-215g</guid>
      <description>&lt;h2&gt;
  
  
  What is Optimistic update?
&lt;/h2&gt;

&lt;p&gt;Optimistic update is a process where UI behaves as though a change was successsfully completed before backend server completes saving the data in the database. This will eventually get confirmation or error (unlikely). Overall, this provides more responsive UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  General process of Optimistic update
&lt;/h2&gt;

&lt;p&gt;In the process of updating a value in UI, the Frontend requests data change to the backend service and also changes the state on UI side &lt;strong&gt;without&lt;/strong&gt; waiting for the response data from the backend.&lt;/p&gt;

&lt;p&gt;However, sometimes we want to sync UI state with the response data from the backend since they are from &lt;em&gt;source of the truth&lt;/em&gt; (db). Thus upon completing requests, we can re-update the state in UI with the response data if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 1
&lt;/h3&gt;

&lt;p&gt;Updating states on UI before backend completes is okay. BUT what if user spams or interacts with UI very fast? or maybe change value of the same ID quick and frequently?&lt;/p&gt;

&lt;p&gt;This will cause few potential problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Possible spamming call to API&lt;/li&gt;
&lt;li&gt;Possible race condition issue on updating data in the database&lt;/li&gt;
&lt;li&gt;Unnecessary usage of database connection pool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good news is that this can be avoided by &lt;strong&gt;debouncing&lt;/strong&gt; requests on the frontend&lt;/p&gt;

&lt;h4&gt;
  
  
  "Debounce" it
&lt;/h4&gt;

&lt;p&gt;Debounce is a process that delays the processing of the event/action until the user has stopped typing for a given amount of time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const debounce = (callback, delay = 1000) =&amp;gt; {  
  let timeout;  
  return (...args) =&amp;gt; {
    clearTimeout(timeout);
    timeout = setTimeout(() =&amp;gt; {
      callback(...args);
    }, delay);
  }
}; 

const requestCall = debounce(() =&amp;gt; console.log("request"));
requestCall();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since this will not execute API call until user stops interacting for a given amount of time, All potential problems from the list should resolve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 2
&lt;/h3&gt;

&lt;p&gt;(This problem really depends on how much do you need to care about &lt;em&gt;source of truth&lt;/em&gt; data from the API response)&lt;/p&gt;

&lt;p&gt;Putting stress to the backend API and race conditioning on database part should be resolved. BUT there's one other problem with debounce that is possible &lt;strong&gt;data sync problem on the Frontend after getting response from the Backend API&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's say we have a debouncer with delay of 1 second and API request can take up to 1 second to complete. What happens if user re-updates the value right before API request completes? If we need to priortise the value on the UI side then this is no problem but what if we need to priortise the value from the API response?&lt;/p&gt;

&lt;p&gt;Then most likely, user will be seeing the value changing optimistically (changed by user) and then changing again with the value from the API response and then change again after the most recent API request.&lt;/p&gt;

&lt;p&gt;This is quite bad user experience seeing values keep jumping.&lt;/p&gt;

&lt;h4&gt;
  
  
  Hash/Stack actions
&lt;/h4&gt;

&lt;p&gt;With above problems, I decided &lt;strong&gt;not to use debounce&lt;/strong&gt; but creating my own action hash set which waits ongoing request before executing request in the hash.&lt;/p&gt;

&lt;p&gt;The approach can be &lt;strong&gt;either hash and stack&lt;/strong&gt; where we store latest action in the hash that needs to be executed after the current OR it can be stack LIFO (Last in first out) instead of hash and pop the latest action for next execution and sending rest of requests in the stack to server as well for logging purpose.&lt;/p&gt;

&lt;p&gt;For example, This is my data&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  id: 1,
  value: "Hi"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's say, I updated with following order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update the value to "Hello"&lt;/li&gt;
&lt;li&gt;Update the value to "World"&lt;/li&gt;
&lt;li&gt;Update the value to "!"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this case, I do not need to care about updating value "World" on Backend side when the client-side is still waiting for the response for "Hello". And once "Hello" is completed I extract "!" into next execution.&lt;/p&gt;

&lt;p&gt;So.. the process will be like below:&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%2F27cfznfxphbn8jtfh587.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%2F27cfznfxphbn8jtfh587.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
(Simplified diagram)&lt;br&gt;
(Blue lines indicates the life cycle after current process finishes)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update the value to "Hello" - Request sent immediately and also pushed to a hash that handles all current processings.&lt;/li&gt;
&lt;li&gt;Update the value to "World" - Request into hash using id as key&lt;/li&gt;
&lt;li&gt;Update the value to "!" - Overrides the request(from 2.) in hash &lt;/li&gt;
&lt;li&gt;On 1. completes, we will check the pending process hash and see if there is a request, then executes the request and clear the hash.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As shown above, there are &lt;strong&gt;two hashers&lt;/strong&gt; (can replace to stack w/e prefer). One for current processings and one for pending processes. &lt;br&gt;
And we have &lt;strong&gt;pending process checker&lt;/strong&gt; that only gets triggered after the current process execution and checks if there's pending process in the hash.&lt;/p&gt;

&lt;p&gt;With above approach potential client side data sync issue from optimistic UI application can be resolved&lt;/p&gt;

&lt;h3&gt;
  
  
  Possible alternative(?)
&lt;/h3&gt;

&lt;p&gt;This can also achievable using abort controller however:&lt;br&gt;
Abort controller is client-side based aborting and disregard executions on the server side thus even if we have bunch of canceled requests on the client-side, server side might be still handling those requests.&lt;/p&gt;

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

&lt;p&gt;Debouncing is really good solution to avoid making unnecessary requests to server and make data handling more efficients but there are few concerns that needs to rethink about when it comes to optimistic UI. And sometime, creating own process &lt;strong&gt;hash/stack/queue&lt;/strong&gt; handlers on the client side might work better than debouncing.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>optimisticui</category>
      <category>coding</category>
      <category>developer</category>
    </item>
    <item>
      <title>Frontend webpack optimization</title>
      <dc:creator>Chan Ro</dc:creator>
      <pubDate>Mon, 03 Jul 2023 07:39:45 +0000</pubDate>
      <link>https://forem.com/chanro/frontend-webpack-optimization-1a90</link>
      <guid>https://forem.com/chanro/frontend-webpack-optimization-1a90</guid>
      <description>&lt;p&gt;Most of developers uses webpack to build their applications to run for production environment. &lt;/p&gt;

&lt;p&gt;We all know webpack also minimizes our code during build &lt;/p&gt;

&lt;h2&gt;
  
  
  Importance of built file sizes
&lt;/h2&gt;

&lt;p&gt;The size of built files are very important as users need to download these files to run the application on the web and obviously if file size is large then it can cost performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we minimize these files?
&lt;/h2&gt;

&lt;p&gt;There are few points that can minimise files further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove all unused packages&lt;/li&gt;
&lt;li&gt;Try build your own functions instead of relying on external packages. Thats if it's simple enough to build. (Eg. underscore, jquery packages are good examples. These are quite huge packages but with recent ECMAScripts, most of core functions are covered)&lt;/li&gt;
&lt;li&gt;Tree shaking&lt;/li&gt;
&lt;li&gt;Analyse to remove any unnecessary files&lt;/li&gt;
&lt;li&gt;Removing duplicated packages&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Webpack analyzer
&lt;/h3&gt;

&lt;p&gt;Analyzining webpack output is a good way to start to investigating on the optimization. Webpack analyzer is a webpack plugin that displays all packages in the application in a diagram with interactions where developers can easily identify and find any unnecessary packages and files that can be removed to make build files size smaller.&lt;/p&gt;

&lt;p&gt;The analyzer is very simple to setup.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the package &lt;/li&gt;
&lt;li&gt;Include the plugin in the webpack config file
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find more from the link below.&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/webpack-bundle-analyzer"&gt;webpack-bundle-analyzer&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Tree shaking
&lt;/h3&gt;

&lt;p&gt;Tree shaking is a process of removing unused exports from a module. &lt;/p&gt;

&lt;p&gt;This can be done by using ECMA &lt;strong&gt;import/export&lt;/strong&gt; keyword instead &lt;strong&gt;require&lt;/strong&gt;. This way webpack will pick which dependency to export and not during build process.&lt;/p&gt;

&lt;p&gt;Also, if you are &lt;em&gt;react&lt;/em&gt; user then code splitting can help on optimization as well. For example we can set a lazy load on component level to be rendered asynchronously.&lt;br&gt;
Eg.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ComponentA= React.lazy(() =&amp;gt; import('./ComponentA'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will allow the component to be rendered only when its needed&lt;/p&gt;

&lt;h3&gt;
  
  
  Removing duplicated packages
&lt;/h3&gt;

&lt;p&gt;Sometimes when we install packages, some of them uses the same dependency but with different versions.&lt;/p&gt;

&lt;p&gt;(Resources are from Atlassian)&lt;br&gt;
For eg. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YuMdo5T8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ke5dxbh3cfwl9fyibe1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YuMdo5T8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ke5dxbh3cfwl9fyibe1.png" alt="Image description" width="359" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see there are 3 different button package verions (1.0.0, 1.3.0, 2.5.0) but ideally we can make this better to have it like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IKdX1HEn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4yoe4aa54n34m1elodhb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IKdX1HEn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4yoe4aa54n34m1elodhb.png" alt="Image description" width="353" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This way, technically it can remove 2 dependencies in total that can reduce a quite size.&lt;/p&gt;

&lt;p&gt;How it's done? it is quite simple. Atlassian provides npm package and github link for this webpack plugin and developers can simply add the plugin into webpack config.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/atlassian-labs/webpack-deduplication-plugin"&gt;webpack-deduplication-plugin&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { WebpackDeduplicationPlugin } = require('webpack-deduplication-plugin');

module.exports = {
  plugins: [
    new WebpackDeduplicationPlugin({
        cacheDir: cacheDirPath,
        rootPath: rootPath,
    }),
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, be careful before using the plugin because some of packages require a specific version of dependency and if thats the case this may cause more problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building your own functions
&lt;/h3&gt;

&lt;p&gt;Packages like &lt;strong&gt;jquery&lt;/strong&gt; and &lt;strong&gt;underscore&lt;/strong&gt; provides very useful functions which developers can immediately pick up and use it to build applications faster.&lt;br&gt;
However, most of core functions that these packages provide are covered in recent ECMAscripts, so technically developers can live without it.&lt;/p&gt;

&lt;p&gt;Speed in development is quite important because we need to hit deadlines and sometimes these deadlines are ridiculous BUT if you are building a platform/product that needs to be maintained afterward then you should rethink about using these kind of packages since:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They are generally huge&lt;/li&gt;
&lt;li&gt;Most of them are covered in recent ECMA. (Eg. map, forEach, reduce, etc)&lt;/li&gt;
&lt;li&gt;Replacing/removing these packages are pain.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;So in overall, I was able to save ~42% after applying these methods in recent project (42% is HUGE).&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Elasticsearch parent-child relation(join) field type</title>
      <dc:creator>Chan Ro</dc:creator>
      <pubDate>Sat, 01 Jul 2023 11:04:02 +0000</pubDate>
      <link>https://forem.com/chanro/elasticsearch-parent-child-relation-mal</link>
      <guid>https://forem.com/chanro/elasticsearch-parent-child-relation-mal</guid>
      <description>&lt;p&gt;(Quick Personal work note)&lt;/p&gt;

&lt;p&gt;Elasticsearch provides various of different field types in schema to support users' use cases and also for indexing data for search engine.&lt;/p&gt;

&lt;p&gt;In this thread, I will be writing brief about one of field type called &lt;strong&gt;join&lt;/strong&gt; which probably is not used often unlike other field types, use cases, and possibly something that good to know.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is join field type?
&lt;/h1&gt;

&lt;p&gt;Join field type is basically a field that forms parent/child relationship between records in the same index.&lt;/p&gt;

&lt;p&gt;This can be done by defining type property to join in the schema/mapping with name of keys that defines parent and child.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "mappings": {
    "properties": {
      "_id": {
        "type": "keyword"
      },
      "name": {
        "type": "keyword"
      },
      "document_join_field": { 
        "type": "join",
        "relations": {
          "documentSet": "document" 
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above schema will define every records in the index to have a property called "&lt;strong&gt;document_join_field&lt;/strong&gt;" and then it will take a property value called &lt;strong&gt;name&lt;/strong&gt; which takes either &lt;strong&gt;documentSet&lt;/strong&gt; or &lt;strong&gt;document&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Updating Document Set (Parent)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUT /example-index/_doc/1?routing=1
{
  "_id": "1",
  "name": "Document folderA",
  "NAME_OF_JOIN_FIELD": {
    "name": "documentSet"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Updating Document (Child)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUT /example-index/_doc/1?routing=1
{
  "_id": "1",
  "name": "Document Name A",
  "NAME_OF_JOIN_FIELD": {
    "name": "document"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see that on updating a record, there's parameter called &lt;strong&gt;routing&lt;/strong&gt;. Elasticsearch needs to index both parent and child data in the same shard when either parent or child record updates thus the &lt;strong&gt;routing&lt;/strong&gt; parameter is used to make that happen.&lt;/p&gt;

&lt;h1&gt;
  
  
  Use case and consideration
&lt;/h1&gt;

&lt;p&gt;Join field type can possibly be considered over nested field type by below points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Will each record have quite large amount of child fields?&lt;/li&gt;
&lt;li&gt;Do number of child fields need to be extended real-time? (Eg. like consumer adds new child field on app level)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If use cases need to cover points from above then I suggest using Join over nested field type.&lt;/p&gt;

&lt;h1&gt;
  
  
  Usage and challenge in Join field type
&lt;/h1&gt;

&lt;p&gt;When we try to search in index, the index will return child and parent records since child is also a record in the index. Thus, to query search or filter for join field type, we can use either &lt;strong&gt;has_child&lt;/strong&gt; or &lt;strong&gt;has_parent&lt;/strong&gt; query which can help us from targeting records that we want.&lt;/p&gt;

&lt;h2&gt;
  
  
  has_child query
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;has_child&lt;/strong&gt; query can be used on parent record which tells Elasticsearch to navigate through all child fields records from the parent record in the index and allow user to define search/filter queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /my-index/_search
{
  "query": {
    "has_child": {
      "type": "document",
      "query": {
        ...YOUR_SEARCH_QUERY_HERE
      },
      "inner_hits": {}    
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  has_parent query
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;has_parent&lt;/strong&gt; query can be used on child records to get parent data and allow user to define search/filter queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /my-index/_search
{
  "query": {
    "has_parent": {
      "parent_type": "documentSet",
      "query": {
        ...YOUR_SEARCH_QUERY_HERE
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition, we can query &lt;strong&gt;has_parent&lt;/strong&gt; query within &lt;strong&gt;has_parent&lt;/strong&gt; query and search other child record data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /my-index/_search
{
  "query": {
    "has_parent": {
      "parent_type": "documentSet",
      "query": {
        "has_child": {
            "type": "document",
            "query": {
               ...YOUR_SEARCH_QUERY_HERE
            },
            "inner_hits": {}  
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;strong&gt;has_parent&lt;/strong&gt; and &lt;strong&gt;has_child&lt;/strong&gt; queries, it can cover most of search and filter queries. BUT one thing that needs to be careful is try not to make search queries massive. (Sometimes query for join field can get ugly and hard to read so be careful on that)&lt;/p&gt;

&lt;h2&gt;
  
  
  Sorting (challenge)
&lt;/h2&gt;

&lt;p&gt;Sort query is quite challenge for join field type. In nested field type sorting can be done with a property called &lt;em&gt;nested_path&lt;/em&gt; within sort query but there's no property that can support for join field. &lt;/p&gt;

&lt;p&gt;One useful approach to make sorting work (kind of) is to use &lt;strong&gt;script_score&lt;/strong&gt; on search query and then sort by script score.&lt;/p&gt;

&lt;p&gt;This may work or may not work but this challenge still exists in now days and people are trying to solve problem (Unless Elasticsearch provides an update on this).&lt;/p&gt;

&lt;h1&gt;
  
  
  So is this better than nested field type?
&lt;/h1&gt;

&lt;p&gt;Many people will say "Can't we just use &lt;strong&gt;nested&lt;/strong&gt; field type then?" and my answer in generally will be yes. We can just use &lt;strong&gt;nested&lt;/strong&gt; field type. And &lt;em&gt;Nested field type should be faster than join field type&lt;/em&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nested field is generally &lt;strong&gt;faster&lt;/strong&gt; on read/search queries&lt;/li&gt;
&lt;li&gt;Nested field may be &lt;strong&gt;slower&lt;/strong&gt; on write/update queries (This depends on the data size but generally nested field reindexes every child data when one updates) &lt;strong&gt;While joined field just need to reindex the child/parent record user is trying to update&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Nested field need to set specific number of child fields that each nested field can have. &lt;strong&gt;While joined field does not need to worry about this.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Join field search query can become massive (May become hard to read or maintain unless you are Elasticsearch expert)&lt;/li&gt;
&lt;li&gt;Join field has sort query challenge that needs to be solved.&lt;/li&gt;
&lt;li&gt;Join field data is easier to maintain than nested field&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, both nested and join field have pros and cons and use cases are quite different. But generally if you are trying to work with massive nested data than generally join field is preferred over nested field.&lt;/p&gt;

</description>
      <category>elasticsearch</category>
    </item>
    <item>
      <title>Test</title>
      <dc:creator>Chan Ro</dc:creator>
      <pubDate>Wed, 28 Jun 2023 07:48:07 +0000</pubDate>
      <link>https://forem.com/chanro/test-1mpd</link>
      <guid>https://forem.com/chanro/test-1mpd</guid>
      <description>&lt;p&gt;test&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
