<?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: Composite</title>
    <description>The latest articles on Forem by Composite (@composite).</description>
    <link>https://forem.com/composite</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%2F201866%2F5014b724-95d6-43af-8561-79a14911a196.png</url>
      <title>Forem: Composite</title>
      <link>https://forem.com/composite</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/composite"/>
    <language>en</language>
    <item>
      <title>Why do you hate frontend developers?</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Thu, 12 Feb 2026 08:07:12 +0000</pubDate>
      <link>https://forem.com/composite/why-do-you-hate-frontend-developers-229j</link>
      <guid>https://forem.com/composite/why-do-you-hate-frontend-developers-229j</guid>
      <description>&lt;p&gt;Every time a new LLM drops, the dev community goes into a frenzy. &lt;br&gt;
Among all the noise, one topic consistently steals the spotlight: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"AI is getting so good at frontend that frontend developers will soon be extinct!"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ve been seeing this same headline for two years straight now. &lt;br&gt;
At this point, it feels like the subtext is actually: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Frontend devs are useless. Isn't it about time they disappeared?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And yet, here we are two years later, and frontend developers are still very much alive. Why is that?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>discuss</category>
      <category>ai</category>
    </item>
    <item>
      <title>node.js Worker thread with Typescript</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Thu, 08 Jan 2026 11:34:33 +0000</pubDate>
      <link>https://forem.com/composite/nodejs-worker-thread-with-typescript-5b00</link>
      <guid>https://forem.com/composite/nodejs-worker-thread-with-typescript-5b00</guid>
      <description>&lt;p&gt;Have you encountered this frustrating error since updating to Node.js 20?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;TypeError &lt;span class="o"&gt;[&lt;/span&gt;ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension &lt;span class="s2"&gt;".ts"&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;src/App.ts

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

&lt;/div&gt;



&lt;p&gt;This isn't just a minor glitch; it’s a long-standing issue in the ecosystem. You can see the ongoing discussion here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/TypeStrong/ts-node/issues/2100" rel="noopener noreferrer"&gt;TypeStrong/ts-node#2100&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem is especially painful when trying to run &lt;code&gt;.ts&lt;/code&gt; files using &lt;code&gt;Worker&lt;/code&gt;. No matter what you try, that error often greets you. Even tools like &lt;code&gt;ts-worker&lt;/code&gt; from Bree don't fully support ESM yet, leaving many of us in a tough spot.&lt;/p&gt;

&lt;p&gt;But there is a way out! If you are using &lt;strong&gt;Vite&lt;/strong&gt; in your environment, the solution is closer than you think. The Vite team provides &lt;a href="https://github.com/antfu-collective/vite-node" rel="noopener noreferrer"&gt;vite-node&lt;/a&gt;, which allows you to run scripts within your Vite environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Using vite-node
&lt;/h2&gt;

&lt;p&gt;One tricky part remains: Node.js &lt;code&gt;Worker&lt;/code&gt; still primarily expects &lt;code&gt;.js&lt;/code&gt; or &lt;code&gt;.mjs&lt;/code&gt; extensions. To bridge this gap, we'll use a small wrapper strategy.&lt;/p&gt;

&lt;p&gt;Here’s our setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;vite-node&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;worker_wrapper.mjs&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;parent.ts&lt;/code&gt; and &lt;code&gt;child.ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It sounds a bit complex, but it's actually quite simple once you see the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;worker_wrapper.mjs&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This file uses the &lt;code&gt;vite-node&lt;/code&gt; programmatic API to load and execute our TypeScript worker.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;workerData&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="s1"&gt;node:worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createServer&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="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ViteNodeRunner&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="s1"&gt;vite-node/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ViteNodeServer&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="s1"&gt;vite-node/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;installSourcemapsSupport&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="s1"&gt;vite-node/source-map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// create vite server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;optimizeDeps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// It's recommended to disable deps optimization&lt;/span&gt;
    &lt;span class="na"&gt;noDiscovery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&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="c1"&gt;// create vite-node server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ViteNodeServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// fixes stacktraces in Errors&lt;/span&gt;
&lt;span class="nf"&gt;installSourcemapsSupport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;getSourceMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&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;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSourceMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// create vite-node runner&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ViteNodeRunner&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// when having the server and runner in a different context,&lt;/span&gt;
  &lt;span class="c1"&gt;// you will need to handle the communication between them&lt;/span&gt;
  &lt;span class="c1"&gt;// and pass to this function&lt;/span&gt;
  &lt;span class="nf"&gt;fetchModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;resolveId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;importer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolveId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;importer&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="c1"&gt;// execute the file&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;workerData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jobpath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// close the vite server&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;code&gt;parent.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When initializing the &lt;code&gt;Worker&lt;/code&gt; instance, we point it to &lt;code&gt;worker_wrapper.mjs&lt;/code&gt; instead of the &lt;code&gt;.ts&lt;/code&gt; file directly. We pass the actual target path via &lt;code&gt;workerData&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;Worker&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="s1"&gt;node:worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// in Vite, you should declare __dirname yourself.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./worker_wrapper.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;workerData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;scriptPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./child.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&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;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="s1"&gt;From Worker:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;code&gt;child.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is where your actual worker logic lives. You can write pure TypeScript here!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;parentPort&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="s1"&gt;node:worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;heavyTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&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;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Task Completed in TypeScript!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;heavyTask&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why this works
&lt;/h2&gt;

&lt;p&gt;With this approach, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test efficient thread separation (for schedulers like &lt;strong&gt;Bree&lt;/strong&gt;) during development.&lt;/li&gt;
&lt;li&gt;Avoid messy hacks with Node's experimental loaders.&lt;/li&gt;
&lt;li&gt;Ensure a seamless transition from development to build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But, you must follow real chunk path for after-built worker!&lt;/p&gt;

&lt;p&gt;Happy node.js-ing!&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>typescript</category>
    </item>
    <item>
      <title>The frondend chaos</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Thu, 19 Jun 2025 01:04:11 +0000</pubDate>
      <link>https://forem.com/composite/the-frond-end-chaos-1l4o</link>
      <guid>https://forem.com/composite/the-frond-end-chaos-1l4o</guid>
      <description>&lt;h2&gt;
  
  
  React
&lt;/h2&gt;

&lt;p&gt;The Next &lt;del&gt;.js&lt;/del&gt; of Frontend Technology. by &lt;del&gt;Meta&lt;/del&gt;Vercel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vue.js
&lt;/h2&gt;

&lt;p&gt;New Frontend Era for &lt;del&gt;Quasar&lt;/del&gt;OTAKU.&lt;/p&gt;

&lt;h2&gt;
  
  
  Svelte
&lt;/h2&gt;

&lt;p&gt;Introducing Rune, The React &lt;del&gt;ive&lt;/del&gt; state management system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solid.js
&lt;/h2&gt;

&lt;p&gt;DO NOT &lt;code&gt;use:&lt;/code&gt; OR YOUR TYPE &lt;del&gt;IN&lt;/del&gt;DEFINITION WILL FAIL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preact
&lt;/h2&gt;

&lt;p&gt;Postreact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qwik
&lt;/h2&gt;

&lt;p&gt;Run away, Qwikly!&lt;/p&gt;

&lt;h2&gt;
  
  
  Backbone
&lt;/h2&gt;

&lt;p&gt;Backbone? I can't see anything but bone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ember.js
&lt;/h2&gt;

&lt;p&gt;Only Apple &lt;del&gt;rem&lt;/del&gt;embers.&lt;/p&gt;

&lt;h2&gt;
  
  
  htmx
&lt;/h2&gt;

&lt;p&gt;SHUT UP REACT WE WILL BE THE ONE IN THE FRONTEND BECAUSE I AM THE HTML!&lt;/p&gt;

&lt;h2&gt;
  
  
  Lit
&lt;/h2&gt;

&lt;p&gt;Li &lt;del&gt;f&lt;/del&gt; ted in the frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  11ty
&lt;/h2&gt;

&lt;p&gt;1 Markdown vs 11 men&lt;/p&gt;

&lt;h2&gt;
  
  
  Marko
&lt;/h2&gt;

&lt;p&gt;We need Macro, Marco!&lt;/p&gt;

&lt;h2&gt;
  
  
  Alpine.js
&lt;/h2&gt;

&lt;p&gt;I'm not frontend, just a framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  jQuery
&lt;/h2&gt;

&lt;p&gt;The frontend winner of the whole day, ever.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxska6ugw2oqnpxdu1y3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxska6ugw2oqnpxdu1y3.gif" alt="Thanks" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>discuss</category>
      <category>frontend</category>
    </item>
    <item>
      <title>A React server feature cheat sheet</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Thu, 19 Dec 2024 06:20:37 +0000</pubDate>
      <link>https://forem.com/composite/a-react-server-feature-cheat-sheet-d9k</link>
      <guid>https://forem.com/composite/a-react-server-feature-cheat-sheet-d9k</guid>
      <description>&lt;h2&gt;
  
  
  React Server feature basics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://react.dev/reference/rsc/server-components" rel="noopener noreferrer"&gt;Server Component&lt;/a&gt; (React Server Component, RSC): A component that runs on the server and renders to the client as the same as SSR.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://react.dev/reference/rsc/server-functions" rel="noopener noreferrer"&gt;Server Function&lt;/a&gt; (a.k.a. Server Actions): A function that runs on the servers only and sends the information to the client.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Directives
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://react.dev/reference/rsc/use-client" rel="noopener noreferrer"&gt;&lt;code&gt;'use client'&lt;/code&gt;&lt;/a&gt;: If you are using a "server component" enabled environment, you should mark &lt;code&gt;use client&lt;/code&gt; at the top of the file to mark it as a client component.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://react.dev/reference/rsc/use-server" rel="noopener noreferrer"&gt;&lt;code&gt;'use server'&lt;/code&gt;&lt;/a&gt;: If you have a consideration of mutating the information on the server, you should mark &lt;code&gt;use server&lt;/code&gt; directive at the top of the function body in the server component or file to operate only on the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Server Component
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;RSC is no stateful nor lifecycle. You can't use any hook functions (&lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, etc.) on the server component.&lt;/li&gt;
&lt;li&gt;RSC can have an async function.&lt;/li&gt;
&lt;li&gt;RSC can have server functions. but you must mark &lt;code&gt;'use server'&lt;/code&gt; in the top of the function body.&lt;/li&gt;
&lt;li&gt;RSC can have children in both the server component and the client component.&lt;/li&gt;
&lt;li&gt;RSC cannot run any browser API.&lt;/li&gt;
&lt;li&gt;Your RSC can pass props of any type to RSC. also can pass props type with limitation to the client component. Check the directive types table below.
&lt;/li&gt;
&lt;/ul&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="nx"&gt;marked&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;marked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Not included in bundle&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sanitizeHtml&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sanitize-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Not included in bundle&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// NOTE: loads *during* render, when the app is built.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&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;div&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;sanitizeHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;marked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&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;div&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;
  
  
  Server Function
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;when definition, you must have the &lt;code&gt;'use server'&lt;/code&gt; directive in the function body or file.&lt;/li&gt;
&lt;li&gt;You can run any server features on the function body.&lt;/li&gt;
&lt;li&gt;You cannot run the browser API on the function body.&lt;/li&gt;
&lt;li&gt;You can call server functions on both the server and client.&lt;/li&gt;
&lt;li&gt;You can return value with limitations. Check the directive types table below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Declaring server function in the server component&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="nx"&gt;Button&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Button&lt;/span&gt;&lt;span class="dl"&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;EmptyNote&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createNoteAction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Server Function&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&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;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;createNoteAction&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;Declaring server function in the separate file&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;name&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;{&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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;Using server function in the client component&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;updateName&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="s1"&gt;./actions&lt;/span&gt;&lt;span class="dl"&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;UpdateName&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;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;updateName&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;&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;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&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;h2&gt;
  
  
  Comparison of handle value types in directives
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://react.dev/reference/rsc/use-client#serializable-types" rel="noopener noreferrer"&gt;&lt;code&gt;use client&lt;/code&gt;&lt;/a&gt;: passing prop type from server component to client component.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://react.dev/reference/rsc/use-server#serializable-parameters-and-return-values" rel="noopener noreferrer"&gt;&lt;code&gt;use server&lt;/code&gt;&lt;/a&gt;: The return type of Server functions&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;&lt;code&gt;use client&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;use server&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;both string value and iterables are supported.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bigint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Array&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Only available in the item of serializable list.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Map&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Only available in the item of serializable list.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Set&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Only available in the item of serializable list.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TypedArray&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ArrayBuffer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Date&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;object&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Support only plain object(object initializers or &lt;code&gt;JSON&lt;/code&gt;), &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#null-prototype_objects" rel="noopener noreferrer"&gt;null prototype&lt;/a&gt; not supported.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promises&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Only available in the serializable list.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ReactNode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Only Server Component can send it to Client Component via props.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FormData&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Only server functions can return &lt;code&gt;FormData&lt;/code&gt; instance.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;symbol&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;Only symbols registered in the global Symbol registry via &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for" rel="noopener noreferrer"&gt;&lt;code&gt;Symbol.for&lt;/code&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;⚠️&lt;/td&gt;
&lt;td&gt;Only server functions allowed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;class&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Any instance objects are not serializable.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;The other types and instances are not available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy react'ing!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>You don't need update to React 19</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Wed, 11 Dec 2024 06:15:11 +0000</pubDate>
      <link>https://forem.com/composite/you-dont-need-update-to-react-19-2opk</link>
      <guid>https://forem.com/composite/you-dont-need-update-to-react-19-2opk</guid>
      <description>&lt;p&gt;When you saw the &lt;a href="https://react.dev/blog/2024/12/05/react-19" rel="noopener noreferrer"&gt;new features listed on the official blog&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useTransition&lt;/code&gt;: Just &lt;code&gt;startTransition&lt;/code&gt; with pending state.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useActionState&lt;/code&gt;: &lt;code&gt;useTransition&lt;/code&gt; + &lt;code&gt;useState&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Form action as function: VS &lt;code&gt;react-hook-form&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useFormStatus&lt;/code&gt;: &lt;code&gt;useContext(&amp;lt;form&amp;gt;)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;useOptimistic&lt;/code&gt;: HERE COMES A NEW CHALLENGER!&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;use&lt;/code&gt;: &lt;code&gt;React.lazy&lt;/code&gt; without dynamic import + &lt;code&gt;@tanstack/query&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Server component and Server Action: for SSR Only&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ref&lt;/code&gt; as Prop: Yes. you can cleanup as callback ref. This feature has made other JS libraries more friendly, making it worth competing with other frontend tech stacks.&lt;/li&gt;
&lt;li&gt;Hydration error: for SSR Only 2&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Context&lt;/code&gt; is &lt;code&gt;Provider&lt;/code&gt; by default: The beginning of the end for class components.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; waterfall issue: &lt;a href="https://github.com/facebook/react/issues/29898#issuecomment-2477449973" rel="noopener noreferrer"&gt;RESOLVED!&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;script async&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;custom-element&amp;gt;&lt;/code&gt;: so what?&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  You are ready and good to upgrade!
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Next.js with &lt;strong&gt;App Router&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Any integrations with node.js backend server (e.g. express, hono, NestJS, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  No, it's not worth upgrading...
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Any SPA stack&lt;/li&gt;
&lt;li&gt;Full stack framework other than Next.js (Pages router included)&lt;/li&gt;
&lt;li&gt;Any SSG or based framework (e.g. Getsby, Docusaurus, Astro...)&lt;/li&gt;
&lt;li&gt;React Native&lt;/li&gt;
&lt;li&gt;A stack that contains non-webpack bundlers. (yes. Vite.)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;This version of React is a major update with the main goal of enhancing server functionality. So you don't need to get excited, and you don't need to upgrade quickly—just keep your version in your existing environment. React is meant to be a library like that. such as Java...&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>Make a React introvert Component (What?🤨)</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Wed, 29 May 2024 10:28:11 +0000</pubDate>
      <link>https://forem.com/composite/make-a-react-introvert-component-what-2jao</link>
      <guid>https://forem.com/composite/make-a-react-introvert-component-what-2jao</guid>
      <description>&lt;p&gt;&lt;em&gt;(2024-05-30: Added working example)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What the heck does that mean?&lt;br&gt;
Today I'm going to break a React feature that I've been using for a while now.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;React.lazy&lt;/code&gt; function is mainly for lazy importing of external components, and in general, the official documentation will tell you to write it like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyExternalComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./path/to/my/component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a popular optimization recommendation that wraps a &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; component around a component declared with the &lt;code&gt;export default&lt;/code&gt; statement in an external component file and imports it on the first call to save resources.&lt;/p&gt;

&lt;p&gt;Right. It must be the component that you declared with the &lt;code&gt;export default&lt;/code&gt; statement. not a named export.&lt;/p&gt;

&lt;p&gt;As you'll see when you write a dynamic &lt;code&gt;import&lt;/code&gt; statement, if you want to lazy load something that you've declared other than &lt;code&gt;default export&lt;/code&gt;, you have to return an object with the &lt;code&gt;default&lt;/code&gt; property.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyExternalComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./path/to/my/component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;OtherComponent&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="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OtherComponent&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;Or you can install &lt;a href="https://www.npmjs.com/package/react-lazily"&gt;&lt;code&gt;react-lazly&lt;/code&gt;&lt;/a&gt; package instead to make it more flexible.&lt;/p&gt;

&lt;p&gt;From this feature, I came up with a brilliant idea.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IntrovertComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lazy&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/path/to/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;pre&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;&amp;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;{&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&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;You might be wondering if the above code will work, right?&lt;br&gt;
The short answer is yes. It will work.&lt;/p&gt;

&lt;p&gt;Let's see in action.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/vitejs-vite-gadhoh?embed=1&amp;amp;file=src%2FApp.jsx&amp;amp;hideExplorer=1" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;React doesn't care if there's an &lt;code&gt;import&lt;/code&gt; statement in the function body or not. We're not necessarily using the Webpack bundler, so it's a pain for them to analyze the bundler's code output.&lt;br&gt;
Instead, the value is in the ability to defer the &lt;code&gt;import&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;Anyway, the argument to the &lt;code&gt;lazy&lt;/code&gt; function accepts a function that returns a &lt;code&gt;Promise&lt;/code&gt; instance, so it doesn't have to be an &lt;code&gt;import&lt;/code&gt; statement, just a &lt;code&gt;Promise&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;It'll useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lazly loads 3rd party quite complex libraries before initializing your compoenent&lt;/li&gt;
&lt;li&gt;Lazly loads API and applies to your component(but once)&lt;/li&gt;
&lt;li&gt;Lazly loads your component that avoids SSR for some external reasons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead, there is one thing to keep in mind.&lt;/p&gt;

&lt;p&gt;This behavior will be out of the purpose of the &lt;code&gt;lazy&lt;/code&gt; function.&lt;br&gt;
Its original purpose is to optimize component resources with &lt;code&gt;import&lt;/code&gt;, but since you declared this code inline, you'll be far from optimizing resources.&lt;/p&gt;

&lt;p&gt;I hope that in the upcoming React 19, do not implement this nonsense and create a normal component with a &lt;code&gt;use&lt;/code&gt; hook function.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;dynamic&lt;/code&gt; provided by Next.js can be implemented in the same way. In particular, since the initialization function of the &lt;code&gt;Plotly&lt;/code&gt; library I was using returns a &lt;code&gt;Promise&lt;/code&gt;, I implemented the following to create a pure client component away from SSR. &lt;a href="https://dev.to/composite/how-to-integrate-plotlyjs-on-nextjs-14-with-app-router-1loj"&gt;See also my original post&lt;/a&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Plotly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&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;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plotly.js/dist/plotly.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;newPlot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;purge&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Plotly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;forwardRef&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;realId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;originId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHandle&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="kc"&gt;undefined&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;originRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="nf"&gt;newPlot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;ref&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;setHandle&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nf"&gt;useImperativeHandle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;ref&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;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;originRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;handle&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;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;realId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;originRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nx"&gt;Plotly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Plotly&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="nx"&gt;Plotly&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="na"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;I named this component an introvert component.&lt;br&gt;
Funny, huh?&lt;/p&gt;

&lt;p&gt;Happy React'ing!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>How to integrate plotly.js on Next.js 14 with App Router</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Tue, 28 May 2024 11:25:34 +0000</pubDate>
      <link>https://forem.com/composite/how-to-integrate-plotlyjs-on-nextjs-14-with-app-router-1loj</link>
      <guid>https://forem.com/composite/how-to-integrate-plotlyjs-on-nextjs-14-with-app-router-1loj</guid>
      <description>&lt;p&gt;I remember struggling quite a bit with integrating the plotly.js library into Next.js in the past.&lt;br&gt;
However, now with Next.js 14 and the use of app routers, I've had to do it all over again, but this time the pain was quite painful.&lt;br&gt;
Eventually I got over it, and today I'm going to share my experience with you, along with a few tips on how to integrate plotly.js into next.js.&lt;/p&gt;

&lt;p&gt;Add the plotly.js library to your existing environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install plotly.js
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-S&lt;/span&gt; plotly.js
&lt;span class="c"&gt;# or&lt;/span&gt;
yarn add plotly.js
&lt;span class="c"&gt;# or&lt;/span&gt;
pnpm add plotly.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you're using Typescript, you can't forget about type definitions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @types/plotly.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you felt something strange, yes, you're right, plotly.js has a React wrapper. But, it hasn't been updated anymore since 2 years ago, and I don't install it because I personally felt a lot of discomfort in the Typescript environment when I first developed it.&lt;br&gt;
If you still want to install it, you can do so. However, I'm going to skip the React wrapper part and create a very simple wrapper component.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use plotly.js
&lt;/h2&gt;

&lt;p&gt;Of course, the plotly.js library is completely browser-specific, so build errors will be waiting for you the moment you import it and start using it.&lt;br&gt;
So, the react-plotly's issue suggests using it as follows:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dynamic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/dynamic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Plotly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-plotly.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason why the react-plotly component doesn't work despite the &lt;code&gt;'use client'&lt;/code&gt; directive is because it's a class component, and it was designed from the ground up assuming a browser. As if that weren't bad enough, now that I'm not touching anything but JS libraries, I'm starting to feel self-conscious about why I'm using this when there are actually better charting libraries out there.&lt;/p&gt;

&lt;p&gt;Now, let's get back to business. Here's the simple wrapper component I created.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Plotly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&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;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plotly.js/dist/plotly.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;newPlot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;purge&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Plotly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;forwardRef&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;realId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;originId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHandle&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="kc"&gt;undefined&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;originRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
            &lt;span class="nf"&gt;newPlot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;ref&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;setHandle&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nf"&gt;useImperativeHandle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;ref&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;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;originRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;handle&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;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;realId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;originRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nx"&gt;Plotly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Plotly&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="nx"&gt;Plotly&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="na"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;Is the import path weird? No, this is the import path used by the &lt;a href="https://github.com/plotly/react-plotly.js/blob/master/src/react-plotly.js#L2" rel="noopener noreferrer"&gt;react-plotly source&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Anyway, apply the component like this, and you're done.&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Plotly&lt;/span&gt;
    &lt;span class="na"&gt;style&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="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;640px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;480px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;data&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="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;layout&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="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;t&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="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;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;But if you're using Typescript, there's still one problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make typescript friendly
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;(2024-12-20 UPDATED)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Updated and modern, clean solution
&lt;/h3&gt;

&lt;p&gt;install plotly.js instead of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm remove plotly.js
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-S&lt;/span&gt; plotly.js-dist-min
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; @types/plotly.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Don't touch &lt;code&gt;next.config.js&lt;/code&gt;.&lt;/strong&gt; Just edit &lt;code&gt;tsconfig.json&lt;/code&gt; or &lt;code&gt;tsconfig.(your app stack).json&lt;/code&gt; as below:&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;"compilerOptions"&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;"paths"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;aliases...&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"plotly.js-dist-min"&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;"node_modules/@types/plotly.js"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;options...&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;options...&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;p&gt;then,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-     import('plotly.js/dist/plotly.js').then(({ newPlot, purge }) =&amp;gt; {
&lt;/span&gt;&lt;span class="gi"&gt;+     import('plotly.js-dist-min').then(({ newPlot, purge }) =&amp;gt; {
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DONE. ENJOY!&lt;/p&gt;

&lt;h3&gt;
  
  
  Old and dirty solution. DON'T TRY THIS METHOD!
&lt;/h3&gt;

&lt;p&gt;If you specify an import path like &lt;code&gt;import('plotly.js/dist/plotly.js')&lt;/code&gt;, Typescript will fail to import the type. The reason for this is simple. It's because the type definition is based on the default path, &lt;code&gt;import('plotly.js')&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are two ways to fix the problem.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;d.ts&lt;/code&gt; file that duplicates the default types in the path &lt;code&gt;'plotly.js/dist/plotly.js'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;include webpack resolve alias to bypass it (included when using turbopack)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I used method #2 because it also solved the build error.&lt;/p&gt;

&lt;p&gt;Now let's touch the &lt;code&gt;next.config.js&lt;/code&gt; file, which in my case was based on &lt;code&gt;next.config.mjs&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/** @type {import('next').NextConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;reactStrictMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;swcMinify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;standalone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;images&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="nf"&gt;bundleOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&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="nx"&gt;nextConfig&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;bundleOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plotly.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plotly.js/dist/plotly.js&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TURBOPACK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// If you are using dev with --turbo&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;experimental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;turbo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;resolveAlias&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;resolvers&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="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// otherwise, for webpack&lt;/span&gt;
    &lt;span class="na"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&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;for &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;dep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolvers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;to&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&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="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now you can modify the import path in the wrapper component as you would normally import it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-     import('plotly.js/dist/plotly.js').then(({ newPlot, purge }) =&amp;gt; {
&lt;/span&gt;&lt;span class="gi"&gt;+     import('plotly.js').then(({ newPlot, purge }) =&amp;gt; {
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, fix the required types for typescript, and voila!&lt;/p&gt;

&lt;p&gt;Done. Congratulations. You can now use plotly.js in Next.js!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conculusion
&lt;/h2&gt;

&lt;p&gt;I chose plotly.js over several popular charting libraries, especially the feature-rich Apache ECharts, because my company's algorithmic research team uses Python, and the plotly Python library is available, which is an advantage for exchanging chart data and layouts.&lt;/p&gt;

&lt;p&gt;I hope I'm not wrong in my choice for this web application product development. lol&lt;/p&gt;

&lt;p&gt;Happy Next.js-ing~!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>tutorial</category>
      <category>plotly</category>
    </item>
    <item>
      <title>A Some undocumented about Server Component on Next.js</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Fri, 18 Aug 2023 12:37:51 +0000</pubDate>
      <link>https://forem.com/composite/a-some-undocumented-about-server-component-408d</link>
      <guid>https://forem.com/composite/a-some-undocumented-about-server-component-408d</guid>
      <description>&lt;p&gt;The Server Component of Next.js is stateless component that it can get some request parameters: Headers and cookies.&lt;br&gt;
But, There is no way to get other parameters such as &lt;code&gt;request.url&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I don't understand why limited to get properties in Server Components. someone says you're not ready to use App Router yet.&lt;br&gt;
I agree. Server component is future of React, but it's still experimental feature.&lt;/p&gt;

&lt;p&gt;While I'm using App Router, I found a way of get some properties in server component, Let's get started.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Header contains in Server Components?
&lt;/h2&gt;

&lt;p&gt;I ran &lt;code&gt;console.log()&lt;/code&gt; in a server component like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;debugHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;headers&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;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I found the following header key Let's see what it contains.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;host&lt;/code&gt;: A real hostname of server. If you are using the app behind reverse proxy, do not use it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x-forwarded-proto&lt;/code&gt;: A forwarded protocol of reverse proxy server. use it if you want check &lt;code&gt;HTTPS&lt;/code&gt; behind reverse proxy.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x-forwarded-host&lt;/code&gt;: A forwarded real hostname behind a reverse proxy. use it if you are using the app behind reverse proxy.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x-middleware-invoke&lt;/code&gt;: It seems that show some infomation when proceed with middleware of Next.js.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x-invoke-path&lt;/code&gt;: A &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x-invoke-query&lt;/code&gt;: A URL encoded query string with JSON. call &lt;code&gt;DecodeURLComponent&lt;/code&gt; and &lt;code&gt;JSON.parse&lt;/code&gt; If you want use.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;x-invoke-output&lt;/code&gt;: Not sure what it is.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on your server environment, the header key may be different, so be sure to extract and verify it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get &lt;code&gt;request.url&lt;/code&gt; and query string in Server Component
&lt;/h2&gt;

&lt;p&gt;Based on the header information above, I made function to take in the URL and query string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;headers&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="s1"&gt;next/headers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-forwarded-proto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-forwarded-host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-invoke-path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;decodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-invoke-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&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;Have fun and Happy Next.js'ing!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>React와 Solid의 차이점 톺아보기</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Thu, 29 Jun 2023 08:14:49 +0000</pubDate>
      <link>https://forem.com/composite/reactwa-solidyi-caijeom-topabogi-4e23</link>
      <guid>https://forem.com/composite/reactwa-solidyi-caijeom-topabogi-4e23</guid>
      <description>&lt;p&gt;또다른 JSX 기술 라이브러리, Solid.js가 있다.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/solidjs" rel="noopener noreferrer"&gt;
        solidjs
      &lt;/a&gt; / &lt;a href="https://github.com/solidjs/solid" rel="noopener noreferrer"&gt;
        solid
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A declarative, efficient, and flexible JavaScript library for building user interfaces.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/1afe367d31d112da69f3e21022a7349e89ecacda7c2167bd663e2d73364f5555/68747470733a2f2f6173736574732e736f6c69646a732e636f6d2f62616e6e65723f70726f6a6563743d4c69627261727926747970653d636f7265"&gt;&lt;img src="https://camo.githubusercontent.com/1afe367d31d112da69f3e21022a7349e89ecacda7c2167bd663e2d73364f5555/68747470733a2f2f6173736574732e736f6c69646a732e636f6d2f62616e6e65723f70726f6a6563743d4c69627261727926747970653d636f7265" alt="SolidJS"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/solidjs/solid/actions/workflows/main-ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/958d8c8bebe3c4d727dc9e5b8d143c768d4d40406cb358b5991573a35d2ebbf4/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f736f6c69646a732f736f6c69642f6d61696e2d63692e796d6c3f6272616e63683d6d61696e266c6f676f3d676974687562267374796c653d666f722d7468652d6261646765" alt="Build Status"&gt;&lt;/a&gt;
&lt;a href="https://coveralls.io/github/solidjs/solid?branch=main" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/176585fd12e1a7e81aee11f40d59d7ee9b89bf6e0f0554177d7574d4182b5245/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f6769746875622f736f6c69646a732f736f6c69642e7376673f7374796c653d666f722d7468652d6261646765" alt="Coverage Status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.npmjs.com/package/solid-js" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b3523d5f40402fb8242720d6f3e0854794253274ef3606cba8ca566f0a4a7df1/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f736f6c69642d6a732e7376673f7374796c653d666f722d7468652d6261646765" alt="NPM Version"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/solid-js" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8189903c81c20e664b11f108bc794047b8070497bf692186c5b2c601d1d370fe/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f736f6c69642d6a732e7376673f7374796c653d666f722d7468652d6261646765" alt=""&gt;&lt;/a&gt;
&lt;a href="https://discord.com/invite/solidjs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/bad291d65cacb436133b45f8e2d0a98cdc98a2bc3c93cb07eb22a2662dce6e51/68747470733a2f2f696d672e736869656c64732e696f2f646973636f72642f3732323133313436333133383730353531303f7374796c653d666f722d7468652d6261646765" alt="Discord"&gt;&lt;/a&gt;
&lt;a href="https://www.reddit.com/r/solidjs/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b9bfe43149609fc23e9e012d60d6f55c9653ac5d790e4c081af081d2596e4b47/68747470733a2f2f696d672e736869656c64732e696f2f7265646469742f7375627265646469742d73756273637269626572732f736f6c69646a733f7374796c653d666f722d7468652d6261646765" alt="Subreddit subscribers"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.solidjs.com/" rel="nofollow noopener noreferrer"&gt;Website&lt;/a&gt; • &lt;a href="https://docs.solidjs.com/" rel="nofollow noopener noreferrer"&gt;API Docs&lt;/a&gt; • &lt;a href="https://www.solidjs.com/tutorial/introduction_basics" rel="nofollow noopener noreferrer"&gt;Features Tutorial&lt;/a&gt; • &lt;a href="https://playground.solidjs.com/?version=1.3.13#NobwRAdghgtgpmAXGGUCWEwBowBcCeADgsrgM4Ae2YZA9gK4BOAxiWGjIbY7gAQi9GcCABM4jXgF9eAM0a0YvADo1aAGzQiAtACsyAegDucAEYqA3EogcuPfr2ZCouOAGU0Ac2hqps+YpU6DW09CysrGXoIZlw0WgheAGEGCBdGAAoASn4rXgd4sj5gZhTcLF4yOFxkqNwAXV4AXgcnF3cvKDV0gAZMywT8iELeDEc4eFSm3iymgD4KqprU9JLamYBqXgBGPvCBoVwmBPTcvN4AHhN6XFx43gJiRpUrm-iVXnjEjWYAa0aQUZCCa4SSzU5nfirZaZSTgi76F63CBgga7CCwiBWISicTpGaNebnJZpXj6WblES0Zj0YEAOg8VQAompxsJcAAhfAASREJzAUEIhBUmTRYEkdSAA" rel="nofollow noopener noreferrer"&gt;Playground&lt;/a&gt; • &lt;a href="https://discord.com/invite/solidjs" rel="nofollow noopener noreferrer"&gt;Discord&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Solid is a declarative JavaScript library for creating user interfaces. Instead of using a Virtual DOM, it compiles its templates to real DOM nodes and updates them with fine-grained reactions. Declare your state and use it throughout your app, and when a piece of state changes, only the code that depends on it will rerun.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;At a Glance&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-tsx notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;createSignal&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"solid-js"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;render&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"solid-js/web"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;function&lt;/span&gt; &lt;span class="pl-smi"&gt;Counter&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s1"&gt;count&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;setCount&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;createSignal&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-c1"&gt;0&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
  &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-en"&gt;doubleCount&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-en"&gt;count&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;*&lt;/span&gt; &lt;span class="pl-c1"&gt;2&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
  
  &lt;span class="pl-smi"&gt;console&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;log&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;"The body of the function runs once..."&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

  &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;
    &lt;span class="pl-c1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="pl-c1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;button&lt;/span&gt; &lt;span class="pl-c1"&gt;onClick&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-en"&gt;setCount&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;c&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-s1"&gt;c&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-c1"&gt;1&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-en"&gt;doubleCount&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/solidjs/solid" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;이걸로 잠시 관리자 페이지를 만들다가 &lt;strong&gt;협업의 어려움&lt;/strong&gt;으로 React로 전환한 뼈아픔이 있었지만, Solid도 상당히 매력적인 라이브러리다.&lt;/p&gt;

&lt;p&gt;그래서 이제서야 꺼내게 되었다. React와 Solid.js의 차이점을.&lt;/p&gt;

&lt;h2&gt;
  
  
  가상 DOM
&lt;/h2&gt;

&lt;p&gt;기본적으로, 일단 Solid.js 들어본 적 있다면 이미 알고 있을 것이다.&lt;br&gt;
React와 Vue 는 가상 DOM을 사용하는 대표적인 라이브러리다. 아, Angular도.&lt;br&gt;
그러나 Preact, Solid.js, Svelte 등은 가상 DOM 없이 실제 DOM을 바로 렌더링한다.&lt;/p&gt;

&lt;p&gt;그래서, 이들의 장단점을 정리하면 대충 이렇다.&lt;/p&gt;

&lt;h3&gt;
  
  
  가상 DOM
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;장점: 렌더링 전의 자주 발생하는 변경사항을 빠르게 정리할 수 있다.&lt;/li&gt;
&lt;li&gt;단점: 렌더링 할때마다 가상DOM을 경유하여 실제DOM으로 옮기기 때문에 상대적으로 렌더링 속도가 느리다.&lt;/li&gt;
&lt;li&gt;적합한 케이스: 태그 변경이 많이 일어나는 데이터그리드, 차트 등의 업무 중심의 컴포넌트&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  가상 DOM 사용하지 않음
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;장점: 렌더링 빈도가 적을 수록 성능이 빨라진다.&lt;/li&gt;
&lt;li&gt;단점: 렌더링 빈도가 많을 수록 성능이 느려진다.&lt;/li&gt;
&lt;li&gt;적합한 케이스: 태그 변경이 적게 일어나는 CMS, 쇼핑몰에 쓰는 컨텐츠 중심의 컴포넌트&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;따라서, 이 문제에 대해서는, 당신의 앱이 어느 쪽이 적당할 지는 직접 써보고 판단해야 할 문제인 것이기 때문에, 존중이니 취향해 드리겠다.&lt;/p&gt;

&lt;h2&gt;
  
  
  상태관리
&lt;/h2&gt;

&lt;p&gt;리액트의 기본 상태관리 함수는 &lt;code&gt;useState&lt;/code&gt; 이다.&lt;br&gt;
Solid의 기본 상태관리 함수는 &lt;code&gt;createSignal&lt;/code&gt; 이다.&lt;/p&gt;

&lt;p&gt;이 둘의 차이점을 알아보자.&lt;/p&gt;

&lt;h3&gt;
  
  
  React 상태관리
&lt;/h3&gt;

&lt;p&gt;상태관리 함수는 React 컴포넌트 함수 내에서만 호출이 가능하다.&lt;br&gt;
(단, React 상태관리 결과물은 함수 외부에서도 호출 가능하다.)&lt;/p&gt;

&lt;p&gt;React 상태관리는 빌드 과정을 거쳐 렌더링 상태의 기준을 정의한다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solid.js 상태관리
&lt;/h3&gt;

&lt;p&gt;상태관리 함수들은 컴포넌트 내외 모두 호출이 가능하다.&lt;br&gt;
Solid.js 상태관리 함수 호출부와 결과물 모두 빌드하지 않는다.&lt;br&gt;
따라서, 스코프에 따라 유연한 상태관리 기준을 정의할 수 있다.&lt;br&gt;
심지어, &lt;code&gt;setter&lt;/code&gt; 호출만 해도 상태를 바꾸는 옵션도 설정할 수 있다.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// 두번째 인자에 옵션이 있는데, 아래처럼 하면 상태값이 같아도 상태가 바뀐다.&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;render&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="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;(만약 React 에서 같은 기능을 구현하려면, &lt;a href="https://github.com/react-hookz/web/blob/master/src/useRerender/index.ts" rel="noopener noreferrer"&gt;최대한 랜덤 수를 세팅하는 &lt;code&gt;useState&lt;/code&gt; 기반 함수&lt;/a&gt;를 만들든가, &lt;code&gt;@react-hookz/web&lt;/code&gt; 유틸리티의 &lt;a href="https://react-hookz.github.io/web/?path=/docs/lifecycle-usererender--example" rel="noopener noreferrer"&gt;&lt;code&gt;useRender&lt;/code&gt;&lt;/a&gt; 훅을 이용하면 된다.)&lt;/p&gt;

&lt;p&gt;여기서 주의사항! 솔리드의 상태관리 결과물은 대부분 함수다! 따라서 호출해야 한다! 애초에 시스템이 다른데, 리액트가 렌더링 시 컴포넌트 함수 본문를 갈아엎기 때문에 가능하지만, 솔리드는 함수 원형을 유지하고 상태관리가 별개로 작동하기 때문이다.&lt;/p&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;getter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setter&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="nf"&gt;setTimeout&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;setter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;메롱&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// react와 달리 getter 는 함수로 호출해야 한다!&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;div&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;getter&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  부작용(Side-Effect)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;설명 해봐야 손만 아프다. 리액트 개발자야 말 안해도 알지?&lt;br&gt;
그리고 이 함수 리액트 컴포넌트 본문에서만 호출 가능한 것도 알제?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="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="cm"&gt;/* 상태 바뀌면 실행할 함수 */&lt;/span&gt;
  &lt;span class="k"&gt;return &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="cm"&gt;/* 정리(Cleanup)할 함수 */&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;영향받을&lt;/span&gt; &lt;span class="nx"&gt;속성이나&lt;/span&gt; &lt;span class="nx"&gt;상태&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Solid.js
&lt;/h3&gt;

&lt;p&gt;사실 사용법은 큰 차이 없고, 당연하겠지만 리액트와 동일하게 비동기로 동작한다.&lt;br&gt;
사소한 차이점이 있는데, 이제 설명하겠다.&lt;br&gt;
먼저, 컴포넌트 함수 외에서도 호출 가능하다.&lt;br&gt;
그다음, 위 React 구문을 똑같이 적용한다는 기준으로,&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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="cm"&gt;/* 상태 바뀌면 실행할 함수 */&lt;/span&gt;
  &lt;span class="nf"&gt;onCleanup&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="cm"&gt;/* 정리(Cleanup)할 함수 */&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// 위 함수 본문에 명시한 상태값들이 영향받을 때 호출된다!&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;첫번째, 영향 받을 상태를 명시적으로 지정 가능한 React와 달리, Svelte처럼 부작용 함수 본문에 언급한 상태가 바뀔 때 함수가 실행된다. 따라서 영향받을 상태값을 따로 함수로 빼는 꼼수를 통해 영향받을 상태를 한정짓는 방식으로 해결할 수 있다.&lt;br&gt;
두번째, &lt;code&gt;useEffect&lt;/code&gt; 함수에서는 리턴 함수로 정리할 수 있지만, &lt;code&gt;createEffect&lt;/code&gt; 는 새로운 상태관리 영역 방식으로 관리하여 &lt;code&gt;onCleanup&lt;/code&gt; 같은 생명주기 함수를 컴포넌트와 별개로 사용할 수 있다.&lt;/p&gt;

&lt;h2&gt;
  
  
  범위 관리(Context)
&lt;/h2&gt;

&lt;p&gt;둘의 차이 별로 없다. 기능도 딱히 차이점 없으니 그냥 쓰던대로 쓰면 된다.&lt;/p&gt;

&lt;h2&gt;
  
  
  동적 컴포넌트
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;사실상 다이렉트로 동적 컴포넌트 호출 가능하다. 하지만, 빌드가 필요하고, 컴포넌트 함수임을 인지해야 하기 때문에 상수를 선언 후 그 상수를 컴포넌트 함수로 사용하는 살짝 번거로운 방법을 써야 한다. (JSX,TSX 한정, JS/TS일 경우 그럴 필요 없이 컴포넌트 함수임이 확실하면 함수처럼 호출하거나, 태그일 경우 &lt;code&gt;React.createElement&lt;/code&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;MyDynamicComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Dynamic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tag&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;Dynamic&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;h3&gt;
  
  
  Solid
&lt;/h3&gt;

&lt;p&gt;Vue나 Svelte 처럼 Solid 에서도 동적 컴포넌트를 정의하는 내장 컴포넌트인 &lt;code&gt;&amp;lt;Dynamic&amp;gt;&lt;/code&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;MyDynamicComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;Dynamic&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="si"&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;props&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;
  
  
  조건문 / 반복문
&lt;/h2&gt;
&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;리액트는 조건문과 반복문을 직접적으로 지원한다. 어자피 빌드하니까. 어자피 상태 바뀌면 본문 갈아 엎으니까~ 화성 갈끄니께~&lt;/p&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;MyConditionalComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isShow&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;div&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;isShow&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;앱있음&lt;/span&gt;&lt;span class="dl"&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;div&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;MyForeachComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;list&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;ul&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;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&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;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;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;ul&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;h3&gt;
  
  
  Solid.js
&lt;/h3&gt;

&lt;p&gt;솔리드는 직접적인 스크립트 렌더링을 지원하지 않는다. 본문이 안갈아엎어지는데 될 리가... 그래서 솔리드는 조건문과 반복문을 컴포넌트로 지원한다.&lt;/p&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;MyConditionalComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isShow&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Show&lt;/span&gt; &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isShow&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;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;MyForeachComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;list&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;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;For&lt;/span&gt; &lt;span class="na"&gt;each&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;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;row&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;(&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&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;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;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="nc"&gt;For&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&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;
  
  
  비동기 컴포넌트/Suspense
&lt;/h2&gt;

&lt;p&gt;둘이 비슷하다. &lt;code&gt;lazy&lt;/code&gt; 함수가 있고 &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; 컴포넌트가 두 진영 다 내장되어 있는데, 그냥 뭐 React 따라갔다고 보면 된다. 어자피 JSX가 애초에 리액트를 위해 태어난 놈이니 JSX 쓰는 다른 것들이 어쩌겠니...&lt;/p&gt;
&lt;h2&gt;
  
  
  비동기 반응성
&lt;/h2&gt;
&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;먼저 리액트는 기본적으로 상태관리가 내부적으로 비동기로 진행될 뿐, 직접적인 비동기에 대한 대응을 편리하게 지원하지 않는다. 그 때문에 이를 쉽게 해결하기 위해 많이들 찾는게 바로 TanStack Query, 구 react-query 많이들 썼을 것이다.&lt;/p&gt;
&lt;h3&gt;
  
  
  Solid.js
&lt;/h3&gt;

&lt;p&gt;TanStack Query가 Solid를 지원하기 시작했지만, 솔리드 자체적으로 &lt;code&gt;createResource&lt;/code&gt; 훅 함수를 통해 비동기를 대응할 수 있는 기본적인 유틸리티를 제공한다.&lt;/p&gt;
&lt;h2&gt;
  
  
  ref
&lt;/h2&gt;
&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;리액트는 &lt;code&gt;useRef&lt;/code&gt; 훅이 있다. 이녀석은 기본적으로 값이 바뀌어도 렌더링되지 않기 때문에, 컴포넌트 참조 뿐만 아니라 반응성이 없어야 되는 영역에서도 두루 쓰이고 있다.&lt;/p&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;RefComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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="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="nx"&gt;myDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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;div&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;myDiv&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;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;h3&gt;
  
  
  Solid.js
&lt;/h3&gt;

&lt;p&gt;솔리드는 따로 훅이 없고, 그냥 &lt;code&gt;let&lt;/code&gt; 변수를 선언한 걸 그냥 뙇 걸기만 해도 된다. 함수 본문이 유지가 되기 때문에 가능한 일. Svelte와 비슷하다 생각하면 된다.&lt;/p&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;RefComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myDiv&lt;/span&gt;

  &lt;span class="nf"&gt;onMount&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;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="nx"&gt;myDiv&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;div&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;myDiv&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;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;React 처럼 콜백으로 받을 수 있다. 하지만 Solid에서는 더 강력한 요소의 상태관리 기능을 지원하는데,&lt;/p&gt;

&lt;p&gt;바로 &lt;code&gt;use:&lt;/code&gt; 속성이다. 이건 Svelte에도 있는 기능인데, 하나의 상태관리 영역으로 취급하기 때문에, 여기서도 컴포넌트 초기화될 때 호출하는 &lt;code&gt;onMount&lt;/code&gt; 함수와 컴포넌트 정리할 때 &lt;code&gt;onCleanup&lt;/code&gt; 함수를 쓸 수 있다.&lt;br&gt;
어자피 요소 받은 뒤 호출하기 때문에 &lt;code&gt;onMount&lt;/code&gt; 함수 호출은 필요없고, &lt;code&gt;removeEventListener&lt;/code&gt; 같이 정리가 필요할 경우에 &lt;code&gt;onCleanup&lt;/code&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;clickOutside&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;accessor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&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;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;accessor&lt;/span&gt;&lt;span class="p"&gt;()?.();&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;onCleanup&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&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;타입스크립트 한정해서 단점은, &lt;code&gt;use:&lt;/code&gt; 속성은 컴포넌트 속성에 당연히 없고 정의할 수 없기 때문에, 타입 정의를 어딘가에 해줘야 한다.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;solid-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Directives&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;clickOutside&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;gt;&lt;/span&gt; &lt;span class="k"&gt;void&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="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;만약 ref 콜백을 사용한다면, 해당 컴포넌트 함수 본문에 &lt;code&gt;onCleanup&lt;/code&gt; 함수 호출하면 된다. 선택은 자유.&lt;/p&gt;

&lt;p&gt;React와 달리 앙상한 생태계에서, Svelte와 같이 생태계 의존도를 줄일 수 있는 중요한 기능이라 하겠다.&lt;/p&gt;

&lt;h2&gt;
  
  
  컴포넌트 속성
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React
&lt;/h3&gt;

&lt;p&gt;이젠 언급하기도 지쳤다. 말했지? 상태 바뀌면 함수 본문 같아엎는다고.&lt;br&gt;
그래서 얻을 수 있는 이점 중 하나가 바로 컴포넌트 속성을 분해해서 변수처럼 사용할 수 있다는 점 되겠다.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyPropsComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;some&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;others&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&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;div&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;others&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;some&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;br&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Solid&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;하지만 Solid는 상태가 바뀌어도 본문은 그대로 유지가 되기 때문에 React처럼 속성 분해하는 등의 편리한 구문을 썼다간 큰 낭패를 본다. 당장 볼 수 있는 일이라면, 초기 상태에만 한 번 반영하고 그 이후로는 아무런 미동도 없는 네 컴포넌트를 발견할 수 있다. 따라서, 객체를 분해하는 짓은 여기서는 하지 않는 것이 좋고, 만약 "범주별 분리"를 하고 싶다면, Solid에서 제공하는 &lt;code&gt;splitProps&lt;/code&gt; 유틸리티를 써야 한다.&lt;br&gt;
즉, 중요한 핵심은, &lt;strong&gt;절대 개별 속성으로 분해하지 말 것!&lt;/strong&gt;&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyPropsComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;others&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;splitProps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;some&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;children&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&lt;br&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;div&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;others&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Show&lt;/span&gt; &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;some&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;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;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;some&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  마치며&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;그밖에 더 있긴 한데 일단 핵심만 짚어줬다. 더 알아보고 싶으면 직접 비교해보라 내 손 아파서 이만.&lt;br&gt;
끗.&lt;/p&gt;

&lt;p&gt;2023-07-02: 부작용(Side-effect) 차이점 추가. 이 중요한 걸 빼먹다니...&lt;br&gt;
2023-07-02: 컴포넌트 속성 차이점 추가. 이 또한 중요한 걸 빼먹다니...&lt;/p&gt;

</description>
      <category>solidjs</category>
      <category>javascript</category>
      <category>korean</category>
      <category>react</category>
    </item>
    <item>
      <title>내가 싫어하는 JS/TS 라이브러리들</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Thu, 22 Jun 2023 05:52:54 +0000</pubDate>
      <link>https://forem.com/composite/naega-silheohaneun-jsts-raibeureorideul-272l</link>
      <guid>https://forem.com/composite/naega-silheohaneun-jsts-raibeureorideul-272l</guid>
      <description>&lt;p&gt;오랜만에 dev.to 에서 글을 쓴다.&lt;br&gt;
오늘은, 내가 JS/TS 개발을 하면서 싫어진 라이브러리들, 그리고 왜 싫어하는지, 대응 방안은 무엇인지 내가 간단하게 설명하도록 하겠다.&lt;/p&gt;

&lt;p&gt;아니, 내가 개인적으로 싫어하는 거지, 이 라이브러리 욕하고 싶어서 쓰는 거 아니다.&lt;br&gt;
내가 이렇게 오해하게 써야 너희들이 읽으니 어쩔티비.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lodash
&lt;/h2&gt;
&lt;h3&gt;
  
  
  왜?
&lt;/h3&gt;

&lt;p&gt;음... 워낙에 유명한 유틸리티 라이브러리면서, 워낙에 유명하도록 몇몇이 선동하면서까지 안쓰려 하는 라이브러리고, 나도 거기에 동의하는 바이다.&lt;/p&gt;

&lt;p&gt;이유는 간단하다. 너무나 간단해서 여기까지 쓰고 다음 석션♂으로 넘어가고 싶어졌다.&lt;/p&gt;

&lt;p&gt;만약 IE 호환을 위해 써야 한다면, 차라리 친절하게 어느정도 폴리필 API를 제공하는 corejs 쓰지 말길 바란다.&lt;/p&gt;
&lt;h3&gt;
  
  
  대응 방안
&lt;/h3&gt;

&lt;p&gt;표준 API 로 대체할 게 많다!&lt;br&gt;
심지어 이를 소개하는 Github 이 있고, 16.9K의 별을 당당히 받았다!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/you-dont-need" rel="noopener noreferrer"&gt;
        you-dont-need
      &lt;/a&gt; / &lt;a href="https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore" rel="noopener noreferrer"&gt;
        You-Dont-Need-Lodash-Underscore
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      List of JavaScript methods which you can use natively + ESLint Plugin
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;&lt;a href="https://you-dont-need.github.io/You-Dont-Need-Lodash-Underscore/#/" rel="nofollow noopener noreferrer"&gt;You don't (may not) need Lodash/Underscore&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://spectrum.chat/you-dont-need/lodash-underscore" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a75281b75fb7681260f4d4b1102ca5ff9bfc3c369ce4b4f50b81a1582de875f5/68747470733a2f2f77697468737065637472756d2e6769746875622e696f2f62616467652f62616467652e737667" alt="Join the community on Spectrum"&gt;&lt;/a&gt;
&lt;a href="https://gitter.im/cht8687/You-Dont-Need-Lodash-Underscore" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ef3705254e766b5edea93f49291c6d9239f29b942cfdb84f3296d0e37898b067/68747470733a2f2f6261646765732e6769747465722e696d2f4a6f696e253230436861742e737667" alt="Gitter"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Lodash and Underscore are great modern JavaScript utility libraries, and they are widely used by Front-end developers. However, when you are targeting modern browsers, you may find out that there are many methods which are already supported natively thanks to ECMAScript5 [ES5] and ECMAScript2015 [ES6]. If you want your project to require fewer dependencies, and you know your target browser clearly, then you may not need Lodash/Underscore.&lt;/p&gt;
&lt;p&gt;You are welcome to contribute with more items provided below.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If you are targeting legacy JavaScript engine with those ES5 methods, you can use &lt;a href="https://github.com/es-shims/es5-shim" rel="noopener noreferrer"&gt;es5-shim&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Please note that, the examples used below are just showing you the native alternative of performing certain tasks. For some functions, Lodash provides you more options than native built-ins. This list is not a 1:1 comparison.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Please send a PR if you want to add or modify the code. No need to…&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  예외
&lt;/h3&gt;

&lt;p&gt;이미 lodash를 적용한 기존 프로젝트 뿐이다.&lt;/p&gt;

&lt;h2&gt;
  
  
  Axios
&lt;/h2&gt;

&lt;h3&gt;
  
  
  왜?
&lt;/h3&gt;

&lt;p&gt;표준 API인 &lt;code&gt;fetch&lt;/code&gt;가 떡하니 있다. 아니, 오히려 &lt;code&gt;fetch&lt;/code&gt; 함수가 강력할 수밖에 없다.&lt;br&gt;
물론 일부 예외가 있긴 하다. 전역 옵션이 없다는 것 뿐. (요청 응답 전후 hook 등)&lt;br&gt;
게다가 어자피 axios 도 &lt;code&gt;fetch&lt;/code&gt; 에서 사용하는 클래스들 다 빌려쓸 수밖에 없다. 특히 스트리밍 응답이나 이진 데이터를 자체적으로 관리할 수가 없다.&lt;/p&gt;

&lt;p&gt;내가 이 라이브러리를 싫어하는 진짜 이유는 중구난방 프로그래밍 패턴을 양산하는 원흉(?)이기 때문이다. 내가 협업하면서 제일 애먹었던게, 이 axios를 누구는 호출할 때마다 인스턴스 갖다 쓰고, 또 누구는 어따가 인스턴스 쳐박고 갖다 쓰도록 유도하고, 또 누구는 공통에다 인스턴스 만들게 하고 갖다 쓰고...&lt;br&gt;
이뿐만이 아니다. 누구는 &lt;code&gt;axios&lt;/code&gt;만 딸랑 호출하고, 또 누구는 &lt;code&gt;axios.get&lt;/code&gt; 등의 메소드를 호출한다. 이런 편의적 API가 오히려 중구난방 패턴을 유발하는 원인인 것 같다.&lt;br&gt;
그럼 &lt;code&gt;fetch&lt;/code&gt;라고 다를게 있냐 하는데, 얘는 &lt;code&gt;fetch&lt;/code&gt; 함수 뿐이다.&lt;/p&gt;
&lt;h3&gt;
  
  
  대응 방안
&lt;/h3&gt;

&lt;p&gt;왜에다가 다 써버렸네...&lt;/p&gt;

&lt;p&gt;node.js 서버단에서 쓴다면, LTS 기준 18 부터는 &lt;code&gt;fetch&lt;/code&gt; 함수 기본 제공이나 axios가 필요 없다. 하지만 16 이하 서버단에 써야 한다면, 난 아래 라이브러를 추천하겠다. axios보다 상당히 가볍고, &lt;code&gt;fetch&lt;/code&gt; 와 유사한 API를 제공하여 표준 &lt;code&gt;fetch&lt;/code&gt; 마이그레이션의 수고를 줄여준다.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/sindresorhus" rel="noopener noreferrer"&gt;
        sindresorhus
      &lt;/a&gt; / &lt;a href="https://github.com/sindresorhus/ky-universal" rel="noopener noreferrer"&gt;
        ky-universal
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Use Ky in both Node.js and browsers
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ky-universal&lt;/h1&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Use Ky in both Node.js and browsers&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;As of &lt;a href="https://github.com/sindresorhus/ky/releases/tag/v1.0.0" rel="noopener noreferrer"&gt;Ky 1.0.0&lt;/a&gt;, it runs natively on Node.js. So this package is no longer needed.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/sindresorhus/ky" rel="noopener noreferrer"&gt;Ky&lt;/a&gt; is made for browsers, but this package makes it possible to use it in Node.js too, by polyfilling most of the required browser APIs using &lt;a href="https://github.com/bitinn/node-fetch" rel="noopener noreferrer"&gt;&lt;code&gt;node-fetch&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This package can be useful for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Isomorphic code&lt;/li&gt;
&lt;li&gt;Web apps (React, Vue.js, etc.) that use server-side rendering (SSR)&lt;/li&gt;
&lt;li&gt;Testing browser libraries using a Node.js test runner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Before opening an issue, make sure it's an issue with Ky and not its polyfills. Generally, if something works in the browser, but not in Node.js, it's an issue with &lt;code&gt;node-fetch&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Keep in mind that Ky targets &lt;a href="https://github.com/sindresorhus/ky#browser-support" rel="noopener noreferrer"&gt;modern browsers&lt;/a&gt; when used in the browser. For older browsers, you will need to transpile and use a &lt;a href="https://github.com/github/fetch" rel="noopener noreferrer"&gt;&lt;code&gt;fetch&lt;/code&gt; polyfill&lt;/a&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install ky ky-universal&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Note that you also need to&lt;/em&gt;…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/sindresorhus/ky-universal" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;만약 &lt;strong&gt;한국적인&lt;/strong&gt; API 스타일에 맞는 전략 패턴(Strategy pattern) 스타일의 라이브러리를 찾는다면, 중국에서 만든 가벼운 alova란 대체제도 있다.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/alovajs" rel="noopener noreferrer"&gt;
        alovajs
      &lt;/a&gt; / &lt;a href="https://github.com/alovajs/alova" rel="noopener noreferrer"&gt;
        alova
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Workflow-Streamlined next-generation request tools. Extremely streamline API integration workflow, just one step
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/fb7a1e7be167cb31efdb85c4151bbd5021ed974a0ef0a079a38b574a9490f5f5/68747470733a2f2f616c6f76612e6a732e6f72672f696d672f6c6f676f2d746578742d766572746963616c2e737667"&gt;&lt;img width="200px" src="https://camo.githubusercontent.com/fb7a1e7be167cb31efdb85c4151bbd5021ed974a0ef0a079a38b574a9490f5f5/68747470733a2f2f616c6f76612e6a732e6f72672f696d672f6c6f676f2d746578742d766572746963616c2e737667"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Workflow-Streamlined next-generation request tools.&lt;br&gt;Extremely improve your API using efficiency and save brainpower Just one step&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;English | &lt;a href="https://github.com/alovajs/alova./README.zh-CN.md" rel="noopener noreferrer"&gt;Chinese&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/alova" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c73babaab4e10bc7f6d2c1c8fe7e9bde2369e7c7ea0164246b53b6e93ad160b5/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f616c6f7661" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://github.com/alovajs/alova/actions/workflows/release.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/alovajs/alova/actions/workflows/release.yml/badge.svg?branch=main" alt="build"&gt;&lt;/a&gt;
&lt;a href="https://coveralls.io/github/alovajs/alova?branch=main" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c4a39bd1542733b207fe80dee4b25f80fee9cfbc4cf184e451e267a888d574a7/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f616c6f76616a732f616c6f76612f62616467652e7376673f6272616e63683d6d61696e" alt="coverage status"&gt;&lt;/a&gt;
&lt;a href="https://github.com/alovajs/alova" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/3ea5c29a68e14a8a492e148c81f6c79cd032d6897b7b7b0c00409715bfd39eb8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f616c6f76616a732f616c6f76613f7374796c653d736f6369616c" alt="stars"&gt;&lt;/a&gt;
&lt;a href="https://discord.gg/S47QGJgkVb" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6a1875f43f90dab9fd35d9a29e7f032da65a58ede9fb82103be2475af56ab13e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636861742d446973636f72642d353135666631" alt="discord"&gt;&lt;/a&gt;
&lt;a href="https://alova.js.org/img/wechat_qrcode.jpg" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/76a1ed5acf17f5d86b1b5ef7e4a4a0e2bb6688695710e08909e7e949b62845f1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636861745f776974685f43482d5765636861742d303763313630" alt="wechat"&gt;&lt;/a&gt;
&lt;a href="https://bundlephobia.com/package/alova" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ff252f97d2829091cea461ccff6f967616b27291a196eaaa3f396a3922a26f35/68747470733a2f2f62616467656e2e6e65742f62756e646c6570686f6269612f747265652d7368616b696e672f616c6f7661" alt="tree shaking"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/638434cb7ee97d80dad25161f77bbd228f9311c907700a78f101a7bac67b1c3d/68747470733a2f2f62616467656e2e6e65742f62616467652f69636f6e2f747970657363726970743f69636f6e3d74797065736372697074266c6162656c"&gt;&lt;img src="https://camo.githubusercontent.com/638434cb7ee97d80dad25161f77bbd228f9311c907700a78f101a7bac67b1c3d/68747470733a2f2f62616467656e2e6e65742f62616467652f69636f6e2f747970657363726970743f69636f6e3d74797065736372697074266c6162656c" alt="typescript"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/6581c31c16c1b13ddc2efb92e2ad69a93ddc4a92fd871ff15d401c4c6c9155a4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667"&gt;&lt;img src="https://camo.githubusercontent.com/6581c31c16c1b13ddc2efb92e2ad69a93ddc4a92fd871ff15d401c4c6c9155a4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667" alt="license"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What is alova?&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;alova(pronounced /əˈləʊva/) is a workflow-streamlined next-generation request tool. Starting from front-end and back-end collaboration and API integration, it streamline API integration workflow from 7 steps to only 1 step, extremely streamline API integration workflow and making network requests very simple. Let's see how alova can help you simplify your work.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b38379d783774bdffe11952cb32383ca0a05ee3dd37f15a830f4b95e4b541cef/68747470733a2f2f616c6f76612e6a732e6f72672f696d672f6f766572766965775f666c6f775f656e2e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/b38379d783774bdffe11952cb32383ca0a05ee3dd37f15a830f4b95e4b541cef/68747470733a2f2f616c6f76612e6a732e6f72672f696d672f6f766572766965775f666c6f775f656e2e706e67" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Is there any difference?&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Unlike other request libraries, alova aims to make requests very simple and maintain more efficient data interaction.&lt;/p&gt;
&lt;p&gt;We consider both developers and App users. For developers, alova provides them with the ultimate user experience, and for application users, they can enjoy the smooth experience brought by alova's high-performance data interaction.&lt;/p&gt;
&lt;p&gt;In addition, let's take a look at the specific features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The API design similar to Axios makes the learning cost of users lower;&lt;/li&gt;
&lt;li&gt;High-performance…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/alovajs/alova" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;내가 다시한번 얘기하는데 한국에서 필요로 하는 개발 라이브러리들은 중국에서 정말 귀신같이 잘 만든다니까.&lt;/p&gt;

&lt;h3&gt;
  
  
  예외
&lt;/h3&gt;

&lt;p&gt;기존 프로젝트에 axios를 &lt;code&gt;fetch&lt;/code&gt;로 바꾸려는 멍청한 짓 할 개발자는 없을 거라 믿는다.&lt;br&gt;
&lt;strong&gt;IE를 챙겨야 한다면 할 말이 없다. 그냥 써라.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  끗
&lt;/h2&gt;

&lt;p&gt;정말 끗이다.&lt;/p&gt;

&lt;h2&gt;
  
  
  너 jQuery 싫어한다면서 왜 안 꺼내?
&lt;/h2&gt;

&lt;p&gt;내가 언제? jQuery 쓸 시대가 지났을 뿐, jquery 는 여전히 메이저한 프론트엔드 도구가 없을 때는 여전히 최강이다. 찬양하라 존 레식!&lt;/p&gt;

&lt;p&gt;근데 왜 이런 미적지근한 반응이냐고? 위에 있는 lodash와 axios 는 금방 질리는 라이브러리다. 그냥 기존 프로젝트에 이미 적용했다면 할 수 없이 쓸 뿐, 새로 파거나 대안이 있으면 난 과감히 있든 말든 신경 안쓰고 대안을 쓰는 파렴치한 놈이다. 하지만 jQuery는 내 10여년 경력에서 절반 이상은 함께해오던 라이브러리다. 이런 애증의 라이브러리를 싫어하다니, 내가 아무리 역사공부 하는 게 싫다 하지만 이건 좀 아니다...&lt;/p&gt;

&lt;p&gt;혹시 react, vue, svelte 같은 컴포넌트 라이브러리 쓰면서 jQuery 쓰니?&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%2F112q9yw58nihenk9qe2f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F112q9yw58nihenk9qe2f.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;아, SI 가면 볼 수 있다. 지랄같은 SI.&lt;/p&gt;

&lt;p&gt;진짜끗.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>discuss</category>
      <category>korean</category>
    </item>
    <item>
      <title>Vue.js 3 이벤트 뻐-스</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Sun, 16 Oct 2022 12:42:39 +0000</pubDate>
      <link>https://forem.com/composite/vuejs-3-ibenteu-bbeo-seu-ajc</link>
      <guid>https://forem.com/composite/vuejs-3-ibenteu-bbeo-seu-ajc</guid>
      <description>&lt;p&gt;내가 살다살다 이딴 포스트 하나 쓰려고 포토샵까지 꺼내들게 하다니...&lt;/p&gt;

&lt;p&gt;SI 아니랄까봐 2022년 Vue 에서 밀고있는 Pinia 도 안쓰고&lt;br&gt;
아 그래 너무 최신 기술이라 거부감 느낀다 쳐.&lt;br&gt;
아니, 하다못해 오랫동안 SI에서 잘만 쓰고 있는 Vuex조차도 안 쓰고...&lt;br&gt;
뭐? 이벤트 버스???&lt;/p&gt;

&lt;p&gt;Vue 3 에다가 이벤트 버스???&lt;/p&gt;
&lt;h2&gt;
  
  
  징-하다.
&lt;/h2&gt;

&lt;p&gt;그래... 그래서 만들었다.&lt;br&gt;
Composition API 시대에 예전 &lt;code&gt;new Vue()&lt;/code&gt; 못 쓰니...&lt;br&gt;
하지만 &lt;code&gt;ref()&lt;/code&gt; 및 &lt;code&gt;reactive()&lt;/code&gt; 사용법을 알면 그리 어렵지 않게 만들 수 있다.&lt;br&gt;
그리고 이걸 전역으로 돌아가도록 하는 게 핵심 포인트.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;자, 여기 코드가 있다.&lt;br&gt;
코멘트 주우 늘어진 건 너희들 자동완성하기 좋으라고 해준 거니 감사히 여겨라.&lt;/p&gt;

&lt;p&gt;좋아. 원리를 설명해주지.&lt;/p&gt;

&lt;p&gt;초기화는 그저 컴포넌트 스크립트 &lt;code&gt;setup()&lt;/code&gt; 함수 및 &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt; 태그 내용 안에서 준비한 함수 &lt;code&gt;useEventBus()&lt;/code&gt; 만 호출하여 상수에 담으면 준비 끝!&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;on&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;이벤트명이 키인 객체가 메인이다. 그리고 그 속성들은 이렇다.&lt;br&gt;
당연하겠지만 콜백은 여러개 있을 수 있으니, 이를 배열로 담아둔다.&lt;br&gt;
그리고 &lt;code&gt;trigger&lt;/code&gt; 속성에 이벤트 발생 시 속성을 변경하여 반응형을 유도하기 위해 &lt;code&gt;ref&lt;/code&gt; 함수를 사용한다.&lt;br&gt;
그리고 이 &lt;code&gt;trigger&lt;/code&gt; 속성에 대한 변경을 감지할 &lt;code&gt;watch&lt;/code&gt; 함수를 정의하여, 이를 &lt;code&gt;stopper&lt;/code&gt; 에 정의하는데, 왜 &lt;code&gt;stopper&lt;/code&gt;를 정의하냐면, &lt;code&gt;watch&lt;/code&gt; 함수를 호출하면 반환하는 값이 이 &lt;code&gt;watch&lt;/code&gt; 작업을 중지하기 위해 호출할 수 있는 함수를 반환하기 때문이다. 이에 대해 다음 메소드에 후술하겠다.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;emit&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;이벤트 리스너를 만들었으면, 이제 발생을 시켜야겠지? &lt;code&gt;emit&lt;/code&gt; 메소드를 통해 이벤트를 발생시키도록 유도하면, 이벤트명 키를 찾아 이 안에 있는 &lt;code&gt;trigger&lt;/code&gt; 속성에 있는 &lt;code&gt;ref&lt;/code&gt; 객체의 값을 변경시켜 반응을 유도한다, 객체 값을 변경시키면, &lt;code&gt;watch&lt;/code&gt; 함수 콜백이 발동하는데, 변경한 값을 인자로 받아 배열 내에 있는 모든 콜백을 호출하게 된다.&lt;br&gt;
그렇게 되면 같은 이벤트명을 &lt;code&gt;A.vue&lt;/code&gt;에 정의해도, &lt;code&gt;B.vue&lt;/code&gt;에 정의하면 모두 호출하게 된다.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;off&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;하지만 이벤트를 추가했으면 삭제도 필요하겠지?&lt;br&gt;
이런 상황을 위해 준비한 게 바로 &lt;code&gt;off&lt;/code&gt; 메소드다.&lt;br&gt;
뭐 별거 없다. 이벤트명과 함수명 넣으면 이벤트 안에 함수 날라가고,&lt;br&gt;
함수 없이 이벤트명만 넣으면 이벤트 콜백은 다 사라지게 된다.&lt;br&gt;
이 때, 이벤트 콜백이 사라질 때가 바로 핵심인데,&lt;br&gt;
이벤트 콜백이 사라질 때도 &lt;code&gt;watch&lt;/code&gt; 함수가 동작하는 것은 낭비다.&lt;br&gt;
따라서 준비해둔 &lt;code&gt;stopper&lt;/code&gt; 속성에 담긴 해제 함수를 호출하여 정리하는 것이다.&lt;br&gt;
간단하지?&lt;/p&gt;
&lt;h2&gt;
  
  
  해결해야 할 것들.
&lt;/h2&gt;

&lt;p&gt;안타깝지만 완벽한 구현체는 아니다. 내가 깜박한 점도 있지만, 이들을 해결해야 한다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;이벤트 버스를 사용한 특정 컴포넌트가 해체될 때(Destroy) 해당 컴포넌트에 등록한 리스너도 사라져야 하는 부분이 구현되지 않았다. 구현 안 하면 좀비 콜백이 되어 잠재적인 스크립트 오류를 유발하고 배열이 쌓이게 되면 좋을 게 없지 않은가.&lt;/li&gt;
&lt;li&gt;그냥 Vue 에서 공식으로 넣어준 Provider/Inject 쓰면 안되겠니?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 외에도 내가 모르는 잠재적인 문제가 내재되어 있는데,&lt;br&gt;
이들의 해결은 여러분에게 맡긴다.&lt;br&gt;
어딜 날로 쳐먹으려고...&lt;/p&gt;

&lt;p&gt;아 미안, 조만간 재대로 된 이벤트 버스 구현체 만들게 되면 그때 Github 에 풀게. 언제가 될 지는 모르겠지만 어자피 Vue 코딩 업무 보게 될 수 있으니 그때를 기약하도록 하자. 아니면 뭐 Stack Overflow 가서 찾아도 되고, 그냥...&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/developit"&gt;
        developit
      &lt;/a&gt; / &lt;a href="https://github.com/developit/mitt"&gt;
        mitt
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🥊 Tiny 200 byte functional event emitter / pubsub.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/dd5d8accd6edce02615c947041d4d9250f16333beae191234b2198ee5801913b/68747470733a2f2f692e696d6775722e636f6d2f42717358394e542e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/dd5d8accd6edce02615c947041d4d9250f16333beae191234b2198ee5801913b/68747470733a2f2f692e696d6775722e636f6d2f42717358394e542e706e67" width="300" height="300" alt="mitt"&gt;&lt;/a&gt;
  &lt;br&gt;
  &lt;a href="https://www.npmjs.org/package/mitt" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/5f9cea57f895d7266dd88fcd473857bc739df190f8a4fd2eca46516b2f607188/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6d6974742e737667" alt="npm"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/developit/mitt/workflows/CI/badge.svg"&gt;&lt;img src="https://github.com/developit/mitt/workflows/CI/badge.svg" alt="build status"&gt;&lt;/a&gt;
  &lt;a href="https://unpkg.com/mitt/dist/mitt.js" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/90ec8be089051fc2a8eea807d52ed1ecac6b40ae55bfd5af0b685d486b8098e7/68747470733a2f2f696d672e626164676573697a652e696f2f68747470733a2f2f756e706b672e636f6d2f6d6974742f646973742f6d6974742e6a733f636f6d7072657373696f6e3d677a6970" alt="gzip size"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Mitt&lt;/h1&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Tiny 200b functional event emitter / pubsub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Microscopic:&lt;/strong&gt; weighs less than 200 bytes gzipped&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Useful:&lt;/strong&gt; a wildcard &lt;code&gt;"*"&lt;/code&gt; event type listens to all events&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Familiar:&lt;/strong&gt; same names &amp;amp; ideas as &lt;a href="https://nodejs.org/api/events.html#events_class_eventemitter" rel="nofollow"&gt;Node's EventEmitter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Functional:&lt;/strong&gt; methods don't rely on &lt;code&gt;this&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Great Name:&lt;/strong&gt; somehow &lt;a href="https://npm.im/mitt" rel="nofollow"&gt;mitt&lt;/a&gt; wasn't taken&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mitt was made for the browser, but works in any JavaScript runtime. It has no dependencies and supports IE9+.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Table of Contents&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/developit/mitt#install"&gt;Install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/developit/mitt#usage"&gt;Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/developit/mitt#examples--demos"&gt;Examples &amp;amp; Demos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/developit/mitt#api"&gt;API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/developit/mitt#contribute"&gt;Contribute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/developit/mitt#license"&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;This project uses &lt;a href="http://nodejs.org" rel="nofollow"&gt;node&lt;/a&gt; and &lt;a href="https://npmjs.com" rel="nofollow"&gt;npm&lt;/a&gt;. Go check them out if you don't have them locally installed.&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;$ npm install --save mitt&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then with a module bundler like &lt;a href="http://rollupjs.org/" rel="nofollow"&gt;rollup&lt;/a&gt; or &lt;a href="https://webpack.js.org/" rel="nofollow"&gt;webpack&lt;/a&gt;, use as you would anything else:&lt;/p&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// using ES6 modules&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s1"&gt;mitt&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'mitt'&lt;/span&gt;

&lt;span class="pl-c"&gt;// using CommonJS modules&lt;/span&gt;
&lt;span class="pl-k"&gt;var&lt;/span&gt; &lt;span class="pl-s1"&gt;mitt&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;require&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'mitt'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The &lt;a href="https://github.com/umdjs/umd"&gt;UMD&lt;/a&gt; build is also available on &lt;a href="https://unpkg.com" rel="nofollow"&gt;unpkg&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;script&lt;/span&gt; &lt;span class="pl-c1"&gt;src&lt;/span&gt;="&lt;span class="pl-s"&gt;https://unpkg.com/mitt/dist/mitt.umd.js&lt;/span&gt;"&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/developit/mitt"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;이거 쓰든가.&lt;/p&gt;

&lt;p&gt;끗.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>vue</category>
      <category>korean</category>
    </item>
    <item>
      <title>자바 17을 쓰도록 설득하는 방법</title>
      <dc:creator>Composite</dc:creator>
      <pubDate>Tue, 13 Sep 2022 01:54:40 +0000</pubDate>
      <link>https://forem.com/composite/jaba-17eul-sseudorog-seoldeughaneun-bangbeob-1bn4</link>
      <guid>https://forem.com/composite/jaba-17eul-sseudorog-seoldeughaneun-bangbeob-1bn4</guid>
      <description>&lt;h2&gt;
  
  
  자바 8, 11을 이은 최신 LTS 버전!
&lt;/h2&gt;

&lt;p&gt;LTS가 뭔지 알기만 해도 안심이 되는 이 약자로 충분히 설득이 가능하다. 그러나 LTS가 뭔지 모르거나 관심 없는 시니어 개발자들이 많을 것이다. 뭔지 모른다면, 자바 최신 버전이면서 공식적으로 지원하는 가장 안정적이고 최신 버전이라는 어필을 시도해 보자.&lt;/p&gt;

&lt;h2&gt;
  
  
  맥을 안정적으로 지원하는 최신 버전!
&lt;/h2&gt;

&lt;p&gt;자바 17은 맥 지원에 상당한 심혈을 기울였다. 물론 표면적으로는 자바에서 웹이 아닌 GUI 앱을 돌릴 때, OpenGL 대신 Metal 을 공식 지원하게 된 첫 버전이지만, 더 중요한 사실은, 만약 M1 이상의 맥북을 들고 있는 개발자가 많을 경우, 자바 17은 M1 프로세서 이상을 가장 안정적으로 잘 지원하는 최초의 버전이라는 것이다! 따라서 맥북 들고 다니는 개발자가 많다면 반드시 어필하여 자바 17 사용을 도모하자!&lt;/p&gt;

&lt;h2&gt;
  
  
  문단을 지원하는 최초의 안정화 버전!
&lt;/h2&gt;

&lt;p&gt;이 기능은 자바 14부터 지원했다. 하지만 17은 이 기능을 지원하는 최초의 안정화 버전이라는 것에 중점을 두어야 한다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;jonnaginmundan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nisi nunc, facilisis eget velit a, rutrum iaculis metus. Aliquam ornare eu elit ut venenatis. Maecenas placerat rutrum condimentum. Aenean sit amet est pulvinar, placerat sapien eget, varius diam. Nam quis nunc consequat, consectetur urna sit amet, posuere urna. Ut dictum tempor enim, sed auctor odio viverra elementum. Pellentesque rutrum tristique mollis. Nulla facilisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam porta urna sit amet massa fringilla dapibus. Duis eleifend quam at lacus laoreet finibus.

Donec sollicitudin sodales lacinia. Ut ut purus erat. Curabitur rhoncus odio felis, vel pellentesque enim faucibus ac. Morbi consectetur, est sed pretium lobortis, neque lacus consectetur lacus, non vulputate nulla metus rutrum lectus. Proin nec magna lobortis, ullamcorper dolor a, mollis nisl. Cras aliquam nibh est, auctor posuere dui aliquet et. Sed vehicula turpis et mauris eleifend convallis.

Quisque mollis mauris eget ligula iaculis congue. Aliquam quis est semper ipsum gravida facilisis. Nam vestibulum nulla a euismod ultrices. Sed suscipit viverra tincidunt. Integer quis sem vitae ligula varius ornare quis ac lectus. Integer aliquam aliquet massa nec finibus. Morbi eleifend facilisis libero eget imperdiet. Sed interdum viverra volutpat. Nunc massa est, vulputate vitae mi id, bibendum ornare metus. Phasellus placerat gravida lacus, at hendrerit turpis iaculis vel. Morbi porta leo quis nibh pulvinar, nec malesuada ipsum rutrum. Donec vehicula egestas magna et sodales. In non lectus mattis arcu maximus pulvinar.

Maecenas congue, quam eu pretium rhoncus, mauris velit lacinia felis, sed tincidunt ex risus et mi. Maecenas vel egestas justo, at porta ligula. Sed sagittis viverra scelerisque. Pellentesque ac diam enim. Etiam consectetur non diam nec mattis. Sed sit amet odio in tellus eleifend molestie. Morbi non velit consectetur, elementum dui eget, porttitor quam. Donec quam sapien, faucibus sit amet eros in, placerat pellentesque dolor. Aenean vulputate lectus in dui efficitur rhoncus. Morbi facilisis tortor et commodo malesuada. Suspendisse risus diam, accumsan et maximus non, molestie a nisl. Vivamus enim neque, cursus ut felis eget, imperdiet suscipit tellus. Nullam commodo arcu sodales metus venenatis tempor. Duis varius dolor et turpis placerat, ac congue arcu commodo. Fusce nibh nisl, suscipit et finibus eget, pulvinar id quam. Nullam vel semper ligula.

Sed malesuada urna sapien, nec blandit nisi suscipit ut. Aenean tincidunt sit amet nulla non ultricies. Duis consequat velit quis tristique eleifend. Sed quis lectus at sem consectetur mollis. Donec a posuere libero, in luctus diam. Sed tristique sit amet nisi vitae mollis. Nam feugiat sodales felis, sed pharetra eros feugiat eu. Fusce aliquam ac magna eu hendrerit. Praesent finibus turpis sodales tempor mattis. Nulla facilisi. Morbi imperdiet quam vel libero lacinia, eget tincidunt mi consectetur. Etiam posuere, nisl id varius viverra, elit nisl efficitur eros, ac iaculis ante ipsum sit amet ex. Quisque lacinia venenatis lobortis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nulla tincidunt lacus pulvinar ex pulvinar, sed interdum tellus bibendum. Nullam iaculis, quam eu sodales volutpat, sapien nunc cursus ante, ac condimentum nisi felis et est.
"""&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;뭐. 꼽냐? 길지? 이걸 지원한다는 건 중요하다. 특히 기본값으로 설정한 문단이나, 마크업 등에서!&lt;/p&gt;

&lt;h3&gt;
  
  
  아 자바는 그짓거리 안해도 문단 쓸 방법 많고 메모리에도 효율적이지 않아!
&lt;/h3&gt;

&lt;p&gt;그래. XML같은 외부 리소스를 활용하는 등의 방법이야 있지. 근데 니네들 그거 쓰고 메모리 관리할 줄 알면 그거 써라. 몰라? 그러면 다국어처럼 문자열을 체계적으로 쓸 거 아니면 다 의미 없는 소리다.&lt;/p&gt;

&lt;h2&gt;
  
  
  아 인텔리제이도 17 쓴다고!
&lt;/h2&gt;

&lt;p&gt;JBR 이라고 인텔리제이 구동 시 쓰는 자사 JVM이 있다. 이건 JDK가 공개되지 않았음에도 불구하고 오라클 TCL 인증까지 받은 참 요상한 런타임 모듈이다. 즉, 오라클이 보증하는 자바라는 것이다. 2022년 버전부터 자바 17을 기반으로 동작해서 좀 더 빠른 응답속도를 만들어냈다. (물론 확장 많으면 거기서 거기)&lt;/p&gt;

&lt;h2&gt;
  
  
  아 어자피 스프링 쓸거면서 17도 공식 지원하는데 왜 안 써?
&lt;/h2&gt;

&lt;p&gt;이거마따.&lt;/p&gt;

&lt;h2&gt;
  
  
  오히려 자바 17을 권장하지 않는 경우
&lt;/h2&gt;

&lt;p&gt;아마 대부분 SI/SM과 연관이 깊을 것이겠지만...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;당연하겠지만 기존 유지보수하는 모듈과 같이 관리하는 경우는 이걸 담당한 시니어 개발자에게 어필해봐야 소 귀에 경읽기다.&lt;/li&gt;
&lt;li&gt;구동해야 하는 서버가 10년 이상 오래된 경우 작동 가능성을 보장할 수 없다. 이 경우는 당시 기준으로 안정화된 버전을 시도하는 게 나을 수 있다.&lt;/li&gt;
&lt;li&gt;DB나 각종 연동 모듈에 대한 지원이 없는 경우는 더욱 더 조심해야 한다. 너무 구형 DB라던가 연동 모듈이 있다면, 어쩔 수 없이 거기서 지원하는 자바 버전을 쓰는 것이 베스트일 수밖에 없다.&lt;/li&gt;
&lt;li&gt;제일 좆같은 전자정부표준프레임워크 써야 하는 환경일 경우는 답 없다. 11도 답 없다. 8 써야 한다. 위로를 표한다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  결론
&lt;/h2&gt;

&lt;p&gt;구형 관련한 작동 보증 필요 없고 완전 쌔삥 환경이라면 반드시 자바 17을 사용하여 보안성, 안정성, 그리고 속도 모두를 챙기고 최신 언어 스펙을 누리도록 하자!&lt;br&gt;
참고로 올 말에 출시하고 1년간 안정화되어 내년에 개나소나 쓰게될 스프링 6.0 은 최소 자바 버전이 17이다!&lt;/p&gt;

&lt;p&gt;끗.&lt;/p&gt;

</description>
      <category>java</category>
      <category>korean</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
