<?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: Gaung Ramadhan</title>
    <description>The latest articles on Forem by Gaung Ramadhan (@mrmissx).</description>
    <link>https://forem.com/mrmissx</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%2F1189595%2F9985250f-0219-484d-9bd5-7776991ad0fb.jpeg</url>
      <title>Forem: Gaung Ramadhan</title>
      <link>https://forem.com/mrmissx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mrmissx"/>
    <language>en</language>
    <item>
      <title>Migrating Next.js App to GO + Templ &amp; HTMX</title>
      <dc:creator>Gaung Ramadhan</dc:creator>
      <pubDate>Sun, 05 May 2024 08:09:16 +0000</pubDate>
      <link>https://forem.com/mrmissx/migrating-nextjs-app-to-go-x-templ-x-htmx-252p</link>
      <guid>https://forem.com/mrmissx/migrating-nextjs-app-to-go-x-templ-x-htmx-252p</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Recently, I just rewrite one of my application &lt;a href="https://stashbin.xyz"&gt;Stashbin&lt;/a&gt; from Next.js to GO. Though my main motivation of this migration was to learn GO and experimenting with &lt;a href="https://htmx.org/"&gt;HTMX&lt;/a&gt;. I also aiming to reduce the resource usage of my application and simplify the deployment process. Initially, Stashbin codebase are split into two seperate repository, one for the frontend that uses Next.js and another for the backend that already uses GO. The backend repository is just a REST API responsible for storing and retreiving data from the database.&lt;/p&gt;

&lt;p&gt;With the migration, I want to combine both frontend and backend into a single repository and serve both the API and the web application from single application. This will simplify the deployment process and reduce the resource usage of the application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I also mentioned on my &lt;a href="https://blog.mrmiss.dev/react-a-mess-that-shoulnt-exist-in-web-dev"&gt;previous post&lt;/a&gt; that I'm already so frustrated with React further more Next.js. I'm not saying that they were bad, I just don't enjoy working with it anymore.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, without further ado, let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Migration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Planning and Preparation
&lt;/h3&gt;

&lt;p&gt;In this project, I'm planning to merge the backend and frontend into a single monolith application. Both of them will be served from a single web server in Go. I'm planning to use several libraries to get the project done:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://echo.labstack.com"&gt;Echo&lt;/a&gt; for the web server.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://jmoiron.github.io/sqlx"&gt;sqlx&lt;/a&gt; for the database driver.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://templ.guide"&gt;Templ&lt;/a&gt; for the templating engine. Although Go already have a decent templating engine, I'm planning to use Templ because it's more powerful and flexible. I really like this library and I'm planning to use it in my future projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Migrating the Backend
&lt;/h3&gt;

&lt;p&gt;Migrating the backend is quite simple as the previous backend is already written in Go. There will be only a few adjustments that I need to make since I'm planning to drop the ORM and use sqlx instead. All i need is to change the query done by the ORM to basic sql query.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrating the Frontend
&lt;/h3&gt;

&lt;p&gt;This is the most challenging part of the migration. I need to rewrite the frontend from Next.js to Go (Templ syntax). I also use HTMX to replace React's functionality, communicating with the backend, and updating the DOM.&lt;/p&gt;

&lt;p&gt;Here's some example of the Templ syntax for the main page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/mrmissx/stashbin/view/layout"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/mrmissx/stashbin/view/icons"&lt;/span&gt;

&lt;span class="n"&gt;templ&lt;/span&gt; &lt;span class="n"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseLayout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="n"&gt;hx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/api/document"&lt;/span&gt; &lt;span class="n"&gt;hx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;trigger&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"keydown[keyCode === 83 &amp;amp;&amp;amp; (ctrlKey || metaKey)]"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;textarea&lt;/span&gt;
                    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"editor"&lt;/span&gt;
                    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;
                    &lt;span class="n"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Write or paste, save and share the link..."&lt;/span&gt;
                &lt;span class="o"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;textarea&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Footer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"keydown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;83&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;navigator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mac"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metaKey&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctrlKey&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c"&gt;// prevent default Ctrl+S or Cmd+S&lt;/span&gt;
                    &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;p&gt;With Templ, I can just import a layout and component like what React does with the &lt;code&gt;@&lt;/code&gt; syntax. I also use the &lt;code&gt;hx-*&lt;/code&gt; attribute to communicate with the backend using HTMX API. In build time, Templ will generate a Go code that represents the HTML code above and compile it to the final binary file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;With the new monolith application, I can simplify the docker container deployments. I just need to build the application and run the binary file. I don't need to build the frontend and backend separately and deploy them to different containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.21-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apk update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; nodejs npm

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.mod go.sum package.json package-lock.json ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;go mod download &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    go mod verify &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/a-h/templ/cmd/templ@latest &lt;span class="se"&gt;\
&lt;/span&gt;    npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;templ generate &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt; &lt;span class="c"&gt;# generate the Go code from the Templ syntax&lt;/span&gt;
    npm run build        &lt;span class="c"&gt;# run the tailwindcss build&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; stashbin  &lt;span class="c"&gt;# build the final binary&lt;/span&gt;


&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /app/stashbin .&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /app/public ./public&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./stashbin"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the Dockerfile that I use to build the application. I use a multi-stage build to build the application and copy the final binary with all assets to the final image. We will get the most minimal image size as possible.&lt;/p&gt;

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

&lt;p&gt;With this migration, I'm able to reduce the resource usage of my application, simplify the deployment process also improve the developer experience. Here's some of the improvements that I can see:&lt;/p&gt;

&lt;h3&gt;
  
  
  Image Size
&lt;/h3&gt;

&lt;p&gt;The most significant improvement can be seen immediately from the docker image size. With just single codebase in GO I can bring the image size down from &lt;code&gt;&amp;gt;100MB&lt;/code&gt; to just &lt;code&gt;16MB&lt;/code&gt;. Both of them are already the best optimization using docker build step without shiping the build dependencies.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzvdmkf56r8gjbunt45dt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzvdmkf56r8gjbunt45dt.png" alt="New monolith image size" width="800" height="75"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource Usage
&lt;/h3&gt;

&lt;p&gt;With the new monolith application, I can reduce the resource usage of Stashbin especially the memory usage. The old application uses around &lt;code&gt;150MB&lt;/code&gt; of memory while the new GO application only uses &lt;code&gt;4MB&lt;/code&gt; of memory.&lt;/p&gt;

&lt;p&gt;There are many other minor improvements that I can't mention here like build time, developer experience, deployment speed, etc. I'm happy with the result and I'm looking forward to experiment more with GO and HTMX. If you want to contribute or reach me out, you can check the repository &lt;a href="https://github.com/mrmissx/stashbin"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;See you in the next post! Cheers!&lt;/p&gt;

</description>
      <category>go</category>
      <category>htmx</category>
      <category>frontend</category>
      <category>backend</category>
    </item>
    <item>
      <title>React: A Mess That Shouldn't Exist In Web Development</title>
      <dc:creator>Gaung Ramadhan</dc:creator>
      <pubDate>Sat, 09 Mar 2024 15:14:02 +0000</pubDate>
      <link>https://forem.com/mrmissx/react-a-mess-that-shouldnt-exist-in-web-development-o46</link>
      <guid>https://forem.com/mrmissx/react-a-mess-that-shouldnt-exist-in-web-development-o46</guid>
      <description>&lt;h2&gt;
  
  
  Rant
&lt;/h2&gt;

&lt;p&gt;This post is about reason of &lt;strong&gt;me HATING React&lt;/strong&gt;. I've been using React quite a while, starting from the transition of &lt;em&gt;Class Component&lt;/em&gt; to &lt;em&gt;Functional Component&lt;/em&gt; on version 16.&lt;br&gt;
Additionally, I coded my first React as a curious kid fascinated by React for a very simple reason:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The logo looks very cool!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I truly mean it; the logo is super cool. However, along the way as I use React, I often think that there is something wrong: 'This doesn't seem right',&lt;br&gt;
'Why is this needed?', 'Why people are loving this?', 'is this going to the right way?', 'Isn't this more complicated than just JavaScript', etc.&lt;br&gt;
At this point, I consider that React only adds a burden to web development.&lt;/p&gt;
&lt;h2&gt;
  
  
  So Why Do I Hate React?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Huge Community &amp;amp; Ecosystem
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Wait, isn't it great that React have a huge community?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NO, &lt;strong&gt;Not at all&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;After quite a while using React and creating a few wrapper libraries for my own needs,&lt;br&gt;
I have a thought that the huge community of React are actually becomes an indicator of the biggest React problem.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;React isn't compatible with Vanilla JavaScript&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most of frontend libraries are made with Vanilla JS. An example of library that you might frequently use is "&lt;a href="https://www.chartjs.org/"&gt;Chart.js&lt;/a&gt;". But React is not compatible with Chart.js so here it comes "&lt;a href="https://React-chartjs-2.js.org/"&gt;React-chartjs-2&lt;/a&gt;" A wrapper library to work with Chart.js in React ecosystem. Oh you want to use "&lt;a href="https://threejs.org/"&gt;three.js&lt;/a&gt;" for some cool 3D? you will need "&lt;a href="https://docs.pmnd.rs/React-three-fiber/getting-started/introduction"&gt;React-three/fiber&lt;/a&gt;". In my case, I need to implement "&lt;a href="https://core.telegram.org/bots/webapps#initializing-mini-apps"&gt;telegram-web-app&lt;/a&gt;", not so fast, I have to create my own wrapper to be able to use it.&lt;/p&gt;

&lt;p&gt;Can you see where this is going? The large ecosystem of React is formed because of React low compatibility with vanilla JavaScript libraries. React ecosystem is big because to use it you must make a library wrapper to be able to use it on React. It's not an organic ecosystem that a new idea appear or something new created. By using React, we unknowingly increase the complexity of the web development. The thing that might be more frustrating is that, it was so hard to keep maintaining the dependecies library to keep up to date. Eventally you will be faced with breaking change that you cannot longger update your dependencies or you have to break down the codebase to fix that obviously take your time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yfuyk_np--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://enterspeed-com.euwest01.umbraco.io/media/lrtn4tm0/new-javascript-framework.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yfuyk_np--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://enterspeed-com.euwest01.umbraco.io/media/lrtn4tm0/new-javascript-framework.png" alt="some meme" width="497" height="334"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Reactive Component
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rendered&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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="nf"&gt;setText&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;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For everyone who ever dealt with user input (forms) must be familiar with those code above. Then what is the problem?&lt;br&gt;
When a user inputs, it will cause this whole component to re-render on &lt;strong&gt;EVERY INPUT&lt;/strong&gt;.&lt;br&gt;
Meaning that when someone types "hello world" the component wil be re-rendered &lt;strong&gt;11 times&lt;/strong&gt;.&lt;br&gt;
You can try to run the code and count how many "rendered" will be printed on the console. Wait it becomes 12, How? yes on dev it will be rendered 12 times, I'll also discuss that below.&lt;/p&gt;

&lt;p&gt;Imagine someone unknowingly unleashing heavy computation on a component without &lt;strong&gt;useMemo&lt;/strong&gt;. That computation will run on every component re-render. Not only that, The dependency array in your hooks (useEffect, useMemo, useCallback) are also checked in each re-render. It's like a double whammy for performance pitfalls! I know that you can avoid this by some technique like what &lt;a href="https://react-hook-form.com/"&gt;react-hook-form&lt;/a&gt; done, but remember thats an extra complexity.&lt;/p&gt;



&lt;p&gt;Then whats a better manner to achieve reactivity. Most other framework like &lt;a href="https://svelte.dev/"&gt;Svelte&lt;/a&gt;, &lt;a href="https://www.solidjs.com/"&gt;Solid&lt;/a&gt;, &lt;a href="https://vuejs.org/"&gt;Vue&lt;/a&gt;, &lt;a href="https://angular.io/"&gt;Angular&lt;/a&gt; already adopt a better and faster way to achieve this reactivity. They are &lt;code&gt;signals&lt;/code&gt;.&lt;br&gt;
What are signals, it is basically a state. But not like React when a state update it re-render the whole component, signal are built with the &lt;a href="https://refactoring.guru/design-patterns/observer"&gt;observer pattern&lt;/a&gt;. They have an observer that subscribe to the signal. Whenever the signal updates, only the one who subscribe to it will update. No need to diff the UI and re-render to perform update like what React's done by adding the complexity to re-render the component under it.&lt;/p&gt;
&lt;h3&gt;
  
  
  JSX
&lt;/h3&gt;

&lt;p&gt;Basically, React (JSX) is just a JavaScript file that supports html directly. When doing a conditional rendering, we must use the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; operator or ternary operator. Yes this is very subjective, I personaly doesn't like this. Why? this thing can bea complete mess when managing or simply reading a component with the complex state and condition. Not to mention when someone comes up with the idea of using nested ternaries (oh god, I hate my life 😅 when reading those ternaries).&lt;/p&gt;
&lt;h3&gt;
  
  
  The Footguns
&lt;/h3&gt;

&lt;p&gt;This is one of the things the most painfull when developing a React app. Infinite re-renders/loop are all too common, often triggered by mistakes in setting up the dependency array in useEffect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="nf"&gt;useEffect&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;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This snippet might appear harmless to React newcomers, but try to run it, and voilà--an infinite rerender unfolds.&lt;/p&gt;

&lt;p&gt;Ok lets try another&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now what? your app will hangs with this code. Whats happening under the hood is that a state is changed on the first render -&amp;gt; triggers a re-render -&amp;gt; the state are changed -&amp;gt; trigger a re-render and so on. Its not even updated on the DOM (it just hangs) because the update process hasn't been done yet, it keeps recursively calls update until the React throws the infinite re-render error.&lt;/p&gt;

&lt;p&gt;Those bug are probably easy to find&lt;/p&gt;

&lt;p&gt;But the thing is that when you developing a big project. You would probably use &lt;code&gt;useContext&lt;/code&gt; and this where the pain starts. A state change on the context will most likely update a component far away from what are you currently on.&lt;/p&gt;




&lt;p&gt;Again this burden doesn't seem to hapen on other frameworks that uses signals. Lets take an example with Solid&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSignal&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This syntax are nearly the same with React. Try to run it and yup you will get '1'. Lets try with the useEffect thing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSignal&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="nf"&gt;createEffect&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;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It would also display '1'. With signal aproach it becomes more &lt;strong&gt;predictable&lt;/strong&gt; than re-running the whole component to update a state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strict Mode
&lt;/h3&gt;

&lt;p&gt;What would you think the count would be on the browser when you develop this kind of code?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;React&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="nf"&gt;useEffect&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;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&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="p"&gt;[])&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Rerender Count &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;of course it would be 1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No! it is 2. I can't get it as well at first. How can it becomes 2? There is a black magic called React Strict Mode that Renders the component twice on development. Why? React need to do this to check if your app is safe and sound.&lt;/p&gt;

&lt;p&gt;There are times that I was frustrated why React is calling my API twice and take like 15 minutes thinking it was a bug on my side and in the end realizing that it was the strict mode doing its thing.&lt;br&gt;
React create strict mode to patches and prevent you to create footguns like i mention earlier.&lt;/p&gt;




&lt;p&gt;Others like Svelte, Solid, Vue doesn't have this strict mode. They don't need it because they don't have those footguns in the first place.&lt;/p&gt;

&lt;h3&gt;
  
  
  useEffect
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Now here's the devil, &lt;code&gt;useEffect()&lt;/code&gt;, the real &lt;code&gt;useFootguns()&lt;/code&gt; in React.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the most abstraction I hate from React. I don't know, why people doesn't find this burden. For me, useEffect is the worst, most dirty and overengineered hooks in React. Keep in mind that this hooks exist to replace React lifecycle method &lt;code&gt;componentWillMount&lt;/code&gt;, and &lt;code&gt;componentWillUnmount&lt;/code&gt; also &lt;code&gt;componentDidUpdate&lt;/code&gt; from class component (before React v16.7). It will be more sense and easier to read if they provide more hooks for those lifecycle like &lt;code&gt;useMount&lt;/code&gt; and &lt;code&gt;useUnmount&lt;/code&gt; but no, they stay with &lt;code&gt;useEffect&lt;/code&gt; that handles completely different lifecycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Epilogue
&lt;/h2&gt;

&lt;p&gt;Maybe most of you reading this might have a thought "&lt;em&gt;React is a library not a framework, of course you have to use other libraries to do other stuff&lt;/em&gt;". I do take React as a framework. I can't accept the fact that a library making a whole new rendering paradigm and more complex, where that complexity is not existent in the pure JavaScript ecosystem.&lt;/p&gt;

&lt;p&gt;Indeed, all points I mentioned are very subjective to me. You can take it as my skill issue. Just to be clear, (unfortunately) I still uses React on my daily basis and in the near future as I mainly work with React. But the current frustrations is enough to make me think that React is heading to the wrong path of web development.&lt;/p&gt;

&lt;p&gt;So... is React still worth learning? Yes, but do learn the basic first (HTML, CSS, JavaScript)!&lt;/p&gt;

&lt;p&gt;We can't deny that React is the most popular frontend framework. React is still the best choice for jobs in many companies. If you want to learn web development and wanting to land a job, React is the safest bet.&lt;/p&gt;

&lt;p&gt;Beside that, do try other frameworks like Svelte. You will be shocked how much easier web development will be not have to think about React paradigm (VDOM, re-render, hooks, etc). I tried svelte (sveltekit) last year and it's like the dream of development I looking for. Furthermore, if you wan't to use pure HTML with the React-like you might like &lt;a href="https://htmx.org/"&gt;htmx&lt;/a&gt;. I personaly love using it and have it on my personal project &lt;a href="https://stashbin.xyz"&gt;Stashbin&lt;/a&gt;. I migrate all the stack from Next.js to &lt;a href="https://htmx.org/"&gt;htmx&lt;/a&gt;, &lt;a href="https://go.dev/learn/"&gt;Go&lt;/a&gt; and &lt;a href="https://templ.guide/"&gt;Templ&lt;/a&gt;. Well, another blog post I guess.&lt;/p&gt;




&lt;p&gt;Thats all my viewpoint of the current React. This article has been in my draft since September 2023 and I realy want to post it before the React v19 released 😅. I do love it when they finaly &lt;a href="https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024"&gt;announce&lt;/a&gt; the uses of compiler instead of heavily hinge by the runtime reactivity.&lt;/p&gt;

&lt;p&gt;Thank you for reading, See you on another blog post😉!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>DevOps Simplified: Easy-to-Use Container Projects Deployment</title>
      <dc:creator>Gaung Ramadhan</dc:creator>
      <pubDate>Sat, 16 Dec 2023 05:37:07 +0000</pubDate>
      <link>https://forem.com/mrmissx/devops-simplified-easy-to-use-container-projects-deployment-96d</link>
      <guid>https://forem.com/mrmissx/devops-simplified-easy-to-use-container-projects-deployment-96d</guid>
      <description>&lt;p&gt;As a developer, we're constantly facing challenges in managing and deploying our projects or applications. Navigating the complexities of making application live on the internet can often seem daunting. In this article, we will explore an easy, streamlined flow for our application deployment, making the process not just manageable, but intuitive and efficient.&lt;/p&gt;

&lt;p&gt;Here, we assume you're already familiar with Docker basics and will focus on tools like Docker Compose, Portainer, and Nginx. Ready to streamline our projects from development to live environments? Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Main Tools
&lt;/h2&gt;

&lt;p&gt;There are several tools to help managing our projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://portainer.io" rel="noopener noreferrer"&gt;Portainer&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Portainer is a lightweight management tool that simplifies the way we manage our Docker containers, Docker Swarm, and Kubernetes environments. It provides a user-friendly web interface that allows us to easily manage our Docker host or Swarm cluster. We're using Portainer here to manage our containers stacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://nginxproxymanager.com/" rel="noopener noreferrer"&gt;Nginx Proxy Manager&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Nginx Proxy Manager is a tools that provide an easy way to manage an Nginx instance as a proxy host to our Application from the live internet. This tools also provide a free SSL using Let's Encrypt if we do not own a custom SSL. This Nginx Proxy Manager will act as our application gateway to the public internet.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step By Step
&lt;/h1&gt;

&lt;h3&gt;
  
  
  1. Setup Git Repo
&lt;/h3&gt;

&lt;p&gt;This git repo will be the manifest for all of our application. We can manage all docker compose file of our application here. We can upload it to private GitHub repo to have all automation versioning bump with &lt;a href="https://docs.renovatebot.com" rel="noopener noreferrer"&gt;Renovate Bot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A manifest repo file tree is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── renovate.json
├── app 1
│   └── docker-compose.yml
└── app 2
   └── docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with the &lt;code&gt;renovate.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.renovatebot.com/renovate-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"config:recomended"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"docker:enableMajor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;":dependencyDashboard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prConcurrentLimit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prHourlyLimit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"docker-compose"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fileMatch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"(^|/)(?:docker-)?compose[^/]*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.ya?ml$"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Follow &lt;a href="https://docs.renovatebot.com/" rel="noopener noreferrer"&gt;Renovate docs&lt;/a&gt; for advanced configs e.g: private image registry (gcr, ghcr, etc)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With this manifest repository, we will receive a PR from renovate every update on the docker image tag.&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%2F4k760nv7t0qjhy1yysm9.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%2F4k760nv7t0qjhy1yysm9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Create a Docker Networks
&lt;/h3&gt;

&lt;p&gt;Docker network is a feature of docker to define and manage network to connect a container. We have to connect all of our container in one network so that it will be able to communicate to each other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create my_network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Spin Up Portainer Instance
&lt;/h3&gt;

&lt;p&gt;To spin up a Portainer instance is simple, all we need is a single &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.9"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;portainer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;portainer/portainer-ce:alpine&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;portainer&lt;/span&gt;
    &lt;span class="na"&gt;privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./portainer_data:/data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;9443:9443&lt;/span&gt;
&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my_network&lt;/span&gt;
    &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that the installation is complete, we can log into Portainer dashboard on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://localhost:9443
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We might have to replace the localhost with the server IP's.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Boots up Nginx Proxy Manager
&lt;/h3&gt;

&lt;p&gt;Now we need to run the Nginx Proxy Manager for our reverse proxy. all we need also a single &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.9"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jc21/nginx-proxy-manager:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx_proxy&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;80:80&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;81:81&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;443:443&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./data:/data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./letsencrypt:/etc/letsencrypt&lt;/span&gt;
&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my_network&lt;/span&gt;
    &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Follow the &lt;a href="https://nginxproxymanager.com/setup/#running-the-app" rel="noopener noreferrer"&gt;docs&lt;/a&gt; for more advanced instruction&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are 3 core ports exposed here. &lt;code&gt;80&lt;/code&gt; and &lt;code&gt;443&lt;/code&gt; is the gateway for public HTTP and HTTPS ports. &lt;code&gt;81&lt;/code&gt; is used for the nginx proxy manager dashboard.&lt;/p&gt;

&lt;p&gt;We'll need to log into the nginx dashboard via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:81
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, we might have to replace the localhost with the server IP's. It generate a default user &lt;code&gt;admin@example.com&lt;/code&gt; and password &lt;code&gt;changeme&lt;/code&gt;. You will be asked to modify this at first.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. DNS Setup
&lt;/h3&gt;

&lt;p&gt;After running Portainer and Nginx Proxy Manager, we need to setup our DNS to point to our server. I'm using cloudflare here for the example.&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%2Fqoghktciamgvh5jzwrap.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%2Fqoghktciamgvh5jzwrap.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setup both desired Nginx and Portainer domain/subdomain.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Nginx &amp;amp; Portainer domain setup
&lt;/h3&gt;

&lt;p&gt;On the nginx proxy earlier, go to Proxy Host and add a new one&lt;/p&gt;

&lt;h5&gt;
  
  
  Nginx Host
&lt;/h5&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%2Fluempg7r0xll9s322awm.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%2Fluempg7r0xll9s322awm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Insert our domain name we setup earlier on Cloudflare and forward it to &lt;code&gt;localhost&lt;/code&gt; with the port &lt;code&gt;81&lt;/code&gt; as the dashboard we currently in are on port 81. Here we can also tell Nginx Proxy Manager to generate a new SSL.&lt;/p&gt;

&lt;h4&gt;
  
  
  Portainer Host
&lt;/h4&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%2Fuqil6osi7jd8qnpcbr26.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%2Fuqil6osi7jd8qnpcbr26.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Point this for the container name running Portainer. If you follow my compose file the name is &lt;code&gt;portainer&lt;/code&gt;, so the hostname will be portainer. This is why we need to create a global docker network as Nginx needs to communicate with the app container.&lt;/p&gt;

&lt;p&gt;After saving both of the host, we can access our dashboard by the domain we configure. and from now on, no longer need to use the Server IP's to go to the dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Deploying Application
&lt;/h3&gt;

&lt;p&gt;To deploy our application, we need to add it to our manifest repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── renovate.json
├── nginx
│   └── docker-compose.yml
├── portainer
│  └── docker-compose.yml
└── your application
    └── docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to add the Network config on our compose file of the application!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my_network&lt;/span&gt;
    &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we need to add that application on the Portainer dahsboard. Go to environment -&amp;gt; stacks -&amp;gt; add stacks&lt;/p&gt;

&lt;p&gt;Fill the name of our stack then choose 'Repository' for the build method. Enter all of the information needed and don't forget to turn on the &lt;code&gt;GitOps updates&lt;/code&gt;. With this setting, Portainer will send a polling to check updates of the compose file. We don't need to setup manually again, Portainer will automate all the deploying process.&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%2F5x3gc9k3zskr2rjbntc3.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%2F5x3gc9k3zskr2rjbntc3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deploy the stack when all done.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Seting up Domain for the application
&lt;/h3&gt;

&lt;p&gt;After our container boots up on Portainer, all we need is assigning a domain for our application. Refer to step 5 first to add it on the DNS records. Then we need to configure the proxy host on Nginx Proxy Manager.&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%2Fsuzx0c7chr7cvl4l3gap.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%2Fsuzx0c7chr7cvl4l3gap.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;That's all, it was a bit complicated at first but it is worth the time when there is a version update. All we need is merge the version bump from Renovate Bot and Portainer will spin it up automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notable Notes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Exposed Ports
&lt;/h3&gt;

&lt;p&gt;With the docker network we setup earlier, we no longer need to expose a port on each container. All communication cross-container are handled by the docker Network as long as the container are connected to the same docker network.&lt;/p&gt;

&lt;p&gt;We can safely remove the port config on Portainer and Nginx Proxy Manager except the &lt;code&gt;80:80&lt;/code&gt; and &lt;code&gt;443:443&lt;/code&gt; as it now become the gateway for all application we have to the public internet.&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%2Fkfhzkwggbf6rdrf2hk0d.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%2Fkfhzkwggbf6rdrf2hk0d.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;In this article, we have learned how to streamline an application delivery using docker compose, Portainer and Nginx Proxy Manager. &lt;/p&gt;

&lt;p&gt;It's not a one-size-fits-all solution but rather a practice that can be adapted to our specific needs. Not as powerful as Kubernetes, but this software delivery pipeline are more than enough for small to middle scale application.&lt;/p&gt;




&lt;p&gt;That's it for this article. Thank you for reading!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>React Basic Concept You Must Know!</title>
      <dc:creator>Gaung Ramadhan</dc:creator>
      <pubDate>Sat, 09 Dec 2023 05:05:33 +0000</pubDate>
      <link>https://forem.com/mrmissx/konsep-dasar-reactjs-yang-wajib-tahu-41e6</link>
      <guid>https://forem.com/mrmissx/konsep-dasar-reactjs-yang-wajib-tahu-41e6</guid>
      <description>&lt;p&gt;React.js adalah sebuah library JavaScript untuk membuat UI. React pertama kali dikembangkan oleh tim Facebook pada tahun 2013. Saat ini, React menjadi library frontend yang paling populer. Oke, kita mulai. Apa saja konsep dasar dari React.js?&lt;/p&gt;

&lt;h2&gt;
  
  
  Single Page Application (SPA)
&lt;/h2&gt;

&lt;p&gt;Sebenarnya, SPA bukan fitur eksklusif pada React, tapi kita harus tahu apa itu SPA. Single Page Application ini bukan berarti aplikasi kita hanya memiliki satu halaman (route) &lt;code&gt;/index&lt;/code&gt; ya... Lalu, SPA itu apa?&lt;/p&gt;

&lt;p&gt;SPA ini adalah sebuah implementasi Web App yang saat sebuah halaman dibuka dia hanya akan melakukan load Document satu kali. Selanjutnya, ketika ada perubahan UI, semuanya akan dilakukan dengan menggunakan JavaScript API tanpa perlu melakukan load halaman/document lagi.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSX (JavaScript XML)
&lt;/h2&gt;

&lt;p&gt;JSX adalah Sebuah extention dari JavaScript yang memungkinkan untuk menuliskan HTML pada JavaScript. Mungkin sudah banyak yang tau document.createElement pada JS. Nah dengan JSX pembuatan element  dapat langsung ditulis pada file JavaScript tanpa createElement()&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dari kode di atas bisa kita lihat, untuk membuat sebuah tag h1 dengan isi Hello World sangat mudah dan cepat pada JSX dibandingkan dengan JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual DOM
&lt;/h2&gt;

&lt;p&gt;Pada lingkungan React ada 2 konsep DOM yaitu Real DOM (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model"&gt;DOM pada browser&lt;/a&gt;) dan Virtual DOM (representasi Real DOM yang dikelola oleh React).&lt;/p&gt;

&lt;p&gt;Virtual DOM adalah sebuah abstraksi dari DOM (Document Object Model). Karena proses manipulasi Real DOM itu lambat, hadirlah Virtual DOM. Proses manipulasi DOM pada Virtual DOM ini lebih cepat karena perubahan hanya terjadi pada memori, bukan di tampilan browser.&lt;/p&gt;

&lt;p&gt;Lalu bagaimana cara Virtual DOM untuk mengubah tampilan browser?&lt;/p&gt;

&lt;p&gt;Ketika sebuah state berubah pada Virtual DOM, React akan membandingkan dengan versi Virtual DOM sebelumnya. Ketika ditemukan perbedaan, maka selanjutnya React akan melakukan re-render komponen yang berubah pada Real DOM.&lt;/p&gt;

&lt;h2&gt;
  
  
  State dan Props
&lt;/h2&gt;

&lt;p&gt;Dalam menggunakan React dapat dipastikan kita akan menggunakan kedua ini. State dan props berfungsi untuk mengelola data pada komponent.&lt;/p&gt;

&lt;h3&gt;
  
  
  State
&lt;/h3&gt;

&lt;p&gt;State adalah sebuah data yang merepresentasikan sebuah keadaan. Mudahnya ini adalah sebuah variabel yang dapat berubah seiring dengan waktu dan interaksi dari user. Ketika state berubah, React akan secara otomatis melakukan re-render pada komponen tempat state itu berada&lt;/p&gt;

&lt;h3&gt;
  
  
  Props
&lt;/h3&gt;

&lt;p&gt;Props atau properties ini memiliki definisi yang sama dengan parameter pada sebuah fungsi. Props adalah sebuah data yang dikirimkan dari komponen parent-nya.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// di sini a dan b adalah sebuah parameter yang digunakan dalam fungsi sum&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="c1"&gt;// fungsi sum memiliki props a dan b yang digunakan untuk menampilkan komponen&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; ditambah &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; adalah &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Sum&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hooks
&lt;/h2&gt;

&lt;p&gt;Nah, ini salah satu konsep React.js yang mungkin agak sulit dipahami untuk orang yang baru terjun ke dunia React. Oke, kenapa ada hooks dan apa itu?&lt;/p&gt;

&lt;p&gt;Hooks adalah sebuah fitur yang lahir akibat pergantian model komponen React yang awalnya Class Component beralih ke Functional Component. Hooks adalah sebuah fungsi JavaScript untuk membantu mengelola state dan lifecycle dari sebuah komponen React. Ada banyak macam dari Hooks pada React, tetapi 5 ini adalah yang paling banyak digunakan&lt;/p&gt;

&lt;h3&gt;
  
  
  useState
&lt;/h3&gt;

&lt;p&gt;seperti namanya ‘state’, hook ini digunakan untuk mendeklarasikan sebuah state pada komponen. Ketika state ini berubah, react akan melakukan re-render pada komponen dimana state ini berada. Ingat hanya perubahan state yang dapat memicu re-render. Ketika ada perubahan variabel biasa (&lt;code&gt;let&lt;/code&gt;) react tidak akan melakukan re-render.&lt;/p&gt;

&lt;h3&gt;
  
  
  useEffect
&lt;/h3&gt;

&lt;p&gt;Mungkin ini salah satu hook yang cukup sulit dideskripsikan karena memilik banyak sekali use case. Hook ini sangat sering digunakan pada komponen. Meskipun begitu, banyak yang tidak tahu behaviornya secara penuh.&lt;/p&gt;

&lt;p&gt;Hook ini memungkinkan kita untuk menambahkan ‘side effect' pada komponen seperti fetching data, atau berinteraksi dengan DOM.&lt;/p&gt;

&lt;p&gt;Masih bingung? mudah-mudahan alasan kenapa hook ini dibuat akan memudahkan untuk dipahami.&lt;/p&gt;

&lt;p&gt;useEffect dibuat untuk menggantikan method lifecycle pada class component React yaitu &lt;code&gt;componentWillMount&lt;/code&gt;, &lt;code&gt;componentDidMount&lt;/code&gt;, dan &lt;code&gt;componentWillUnmount&lt;/code&gt;. selain tiga tadi, hook ini juga digunakan sebagai pengganti &lt;code&gt;componentDidUpdate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Artinya, useEffect akan dijalankan ketika sebuah komponen di-mount (di-render) pada Real DOM, serta saat komponen akan di-unmount (dihapus dari Real DOM). Kita juga dapat mengatur agar useEffect dijalankan ketika ada sebuah state pada komponen yang berubah.&lt;/p&gt;

&lt;h3&gt;
  
  
  useCallback
&lt;/h3&gt;

&lt;p&gt;Hook ini bertujuan untuk melakukan memoisasi sebuah function yang terdapat di dalam komponen. Ketika react melakukan re-render, semua kode di dalam komponen akan dijalankan kembali, nah useCallback ini menghindari sebuah fungsi dibuat ulang ketika re-render.&lt;/p&gt;

&lt;h3&gt;
  
  
  useMemo
&lt;/h3&gt;

&lt;p&gt;Hook ini mirip dengan useCallback. Bedanya, useMemo digunakan untuk memoisasi sebuah value. Misalnya, kita memiliki ekspresi dengan komputasi besar, hasilnya dapat dimasukkan ke dalam useMemo untuk menghindari eksekusi pada setiap re-render komponen karena setiap render, react akan seluruh isi dari komponen yang di-rerender.&lt;/p&gt;

&lt;h3&gt;
  
  
  useContext
&lt;/h3&gt;

&lt;p&gt;Hook ini berfungsi untuk memberikan konteks pada komponen. konteks ini dapat diibaratkan sebuah global state yang dapat diakses oleh komponen children tanpa perlu melakukan passing props.&lt;/p&gt;




&lt;p&gt;Sekian pembahasan konsep dasar React.JS. Semoga membantu kalian yang baru terjun ke dunia React 🚀.&lt;/p&gt;




&lt;p&gt;This article are originaly posted on here &lt;a href="https://blog.mrmiss.dev/react-basic-concept"&gt;https://blog.mrmiss.dev/react-basic-concept&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
