<?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: Denis</title>
    <description>The latest articles on Forem by Denis (@fbjorn).</description>
    <link>https://forem.com/fbjorn</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%2F598857%2F68ae0164-0080-4427-92fd-1c3cd5214957.jpeg</url>
      <title>Forem: Denis</title>
      <link>https://forem.com/fbjorn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fbjorn"/>
    <language>en</language>
    <item>
      <title>Reduce memory usage of NodeJS apps inside Docker</title>
      <dc:creator>Denis</dc:creator>
      <pubDate>Thu, 27 Jul 2023 10:59:35 +0000</pubDate>
      <link>https://forem.com/fbjorn/reduce-memory-usage-of-nodejs-apps-inside-docker-3588</link>
      <guid>https://forem.com/fbjorn/reduce-memory-usage-of-nodejs-apps-inside-docker-3588</guid>
      <description>&lt;p&gt;Before diving in, I must admit that the title is a bit vague. Let me describe the issue first, cause the solution below is not a silver bullet and it's suitable for specific runtime environments.&lt;/p&gt;

&lt;p&gt;In our company we use &lt;a href="https://cloud.google.com/run" rel="noopener noreferrer"&gt;Google Cloud Run&lt;/a&gt; to deploy web applications, and every app is built into a docker image. For now we use the default memory limit by Cloud Run which is 256 MB per container. Recently we started to notice that the part of applications go beyond this limit, causing a container to restart and in some cases even resulting to downtime of a service. &lt;/p&gt;

&lt;p&gt;These applications run as Node processes (NextJS server and SvelteKit server), and docker entrypoint is &lt;em&gt;just&lt;/em&gt; a &lt;code&gt;pnpm run start&lt;/code&gt;, that executes the corresponding command under the hood.&lt;/p&gt;

&lt;h1&gt;
  
  
  Troubleshooting
&lt;/h1&gt;

&lt;p&gt;Unfortunately, it's impossible to get inside a running instance in Cloud Run, so the only way to debug a problem is via logs. Web interface doesn't provide you any information about running processes, just a chart with memory utilization from your containers:&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%2Fxigcbgsxgbib7xm1dqoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxigcbgsxgbib7xm1dqoa.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On this chart, we can see that sometimes it's just not enough memory for a service.&lt;/p&gt;

&lt;p&gt;My initial idea was to periodically run &lt;code&gt;top&lt;/code&gt; inside a container and log the output. Then try to see how different conditions like huge traffic affect the memory. There's a tool that helps you run multiple processes inside a docker container called &lt;a href="https://github.com/ioxiocom/multi-start" rel="noopener noreferrer"&gt;multi-start&lt;/a&gt;. I slightly modified its code to execute &lt;code&gt;top -bcn1 -o %MEM -w256&lt;/code&gt; by some interval and log the result to stdout. But just after installing it to the image and deploying it to Google Cloud I noticed something strange:&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%2Faqtj0woeqosfie2y00hm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqtj0woeqosfie2y00hm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1) Total memory consumption according to &lt;code&gt;top&lt;/code&gt; is &lt;code&gt;160 MB&lt;/code&gt;. But the chart above says it takes up to 90% of memory. Well, memory calculation can be interesting sometimes&lt;br&gt;
2) For some reason, the container thinks it has &lt;code&gt;1 Gb&lt;/code&gt; RAM allocated, yet the limit in Cloud Run is set to &lt;code&gt;256 MB&lt;/code&gt;&lt;br&gt;
3) &lt;code&gt;pnpm run start&lt;/code&gt; consumes almost the same amount of memory as NextJS server! Yet it's just a runner for an actual command&lt;/p&gt;

&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;In fact, the only thing I had to do is to replace &lt;code&gt;pnpm run start&lt;/code&gt; with a corresponding script from &lt;code&gt;package.json&lt;/code&gt;, so in case of NextJS apps it was &lt;code&gt;node ./node_modules/next/dist/bin/next start&lt;/code&gt; and &lt;code&gt;node ./build&lt;/code&gt; for SvelteKit (you might have a different setup).&lt;/p&gt;

&lt;p&gt;The results are prominent:&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%2Fy83mxs8pgo301298wodk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy83mxs8pgo301298wodk.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It immediately saved almost 60 MB or memory, which is a lot in such circumstances. See how the changes are reflected in the dashboard:&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%2Fqllg3zd8dxnygd90sg26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqllg3zd8dxnygd90sg26.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This indeed may sound like an edge case, but if you run your node application in an environment with such a limited resources, just try to invoke the scripts directly, without wrapping them into &lt;code&gt;pnpm&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;It also sounds very strange to me why &lt;code&gt;pnpm&lt;/code&gt; is this eager. If anyone has some ideas, please share them.&lt;/p&gt;

&lt;p&gt;Hope it helps 👋&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>javascript</category>
      <category>devops</category>
    </item>
    <item>
      <title>Apity: A typed HTTP client for Svelte(Kit)</title>
      <dc:creator>Denis</dc:creator>
      <pubDate>Wed, 12 Apr 2023 15:55:06 +0000</pubDate>
      <link>https://forem.com/fbjorn/a-typed-http-client-for-sveltekit-88b</link>
      <guid>https://forem.com/fbjorn/a-typed-http-client-for-sveltekit-88b</guid>
      <description>&lt;p&gt;Most frontend projects need to make HTTP requests, but there's no convention how to handle them. We have a &lt;code&gt;fetch&lt;/code&gt; function, but it would be inconvenient to call it directly each time, so often developers create their own API wrappers to call logical functions instead, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&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;API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchProducts&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;// or&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&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;listProducts&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've seen a lot of code like this. Sometimes backend is implemented with the same technology as frontend and a framework provides helpers for network communication, for example SvelteKit has &lt;a href="https://kit.svelte.dev/docs/form-actions" rel="noopener noreferrer"&gt;form actions&lt;/a&gt;. But in certain cases backend is a separate instance and you operate with its API, so such functions are unavoidable.&lt;/p&gt;

&lt;p&gt;The main question with this approach is how to manage request parameters and data in responses. If you're a TypeScript user then you know the benefits of proper typing. TS warns you when you're trying to access wrong properties of objects and a lot of mistakes can be caught even before running the code. And of course having auto completion in your IDE makes development experience much better. So by returning a raw &lt;code&gt;response.json()&lt;/code&gt; you lose a lot of benefits.&lt;/p&gt;

&lt;p&gt;However, there's a couple of issues with this approach:&lt;/p&gt;

&lt;p&gt;1) Writing the types by hand is tedious and error prone&lt;br&gt;
2) Backend changes over time, it can be a new property added to a response, or a new parameter in request body - so you have to keep both codebases in sync&lt;br&gt;
3) Sometimes the types are implemented by backend team already, so duplicating them on frontend sounds like a double work&lt;/p&gt;

&lt;p&gt;Combining all these concerns together and trying to find a proper solution resulted in &lt;a href="https://github.com/cocreators-ee/apity" rel="noopener noreferrer"&gt;Apity&lt;/a&gt; - a Svelte/SvelteKit library for making typed HTTP requests. In this article I'll try to show its bright sides and how to use it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installation and configuration
&lt;/h2&gt;

&lt;p&gt;A pre-requisite before taking Apity into use is having an &lt;a href="https://swagger.io/specification/" rel="noopener noreferrer"&gt;OpenAPI&lt;/a&gt; spec of a server. It should be either stored as a local file, or accessible by an URL. If you're not familiar with OpenAPI - it's a JSON or YAML file that lists server routes, expected parameters and responses. A lot of backend technologies support schema generation, for example &lt;a href="https://fastapi.tiangolo.com" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt; has it out of the box. &lt;/p&gt;

&lt;p&gt;In this post we'll work with &lt;a href="https://petstore3.swagger.io/" rel="noopener noreferrer"&gt;Petstore&lt;/a&gt; schema, so the first steps will be to install the library and generate types from OpenAPI schema (assuming you already have a SvelteKit application).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @cocreators-ee/apity

npx openapi-typescript https://petstore3.swagger.io/api/v3/openapi.json &lt;span class="nt"&gt;--output&lt;/span&gt; src/petstore.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have all the necessary information about the backend in &lt;code&gt;src/petstore.ts&lt;/code&gt; - it contains all the routes and schemas for requests and responses. Using these objects, we can construct and API wrapper for the routes almost automatically:&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;Apity&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;@cocreators-ee/apity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;paths&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;src/petstore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Apity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;paths&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;apity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&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://petstore.swagger.io/v2&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findPetsByStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;apity&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/pet/findByStatus&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;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&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;create&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;addPet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;apity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/pet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;'&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, you have to define each API route by hand, but this was an intentional decision. You will operate with these functions in your code, so it's up to you how to name them. Assigning the names automatically from the spec could result in worse naming, or you might want to separate several parts into different wrappers.&lt;/p&gt;

&lt;p&gt;Don't panic however, now TS knows your backend structure, so defining the routes will be rather quick, and it will warn you if you for example try to create a GET method for a POST route:&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%2Fifustupb40bikmlwqm37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifustupb40bikmlwqm37.png" alt="Image description"&gt;&lt;/a&gt;&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%2F612nsjjzwwcv1c09gnu8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F612nsjjzwwcv1c09gnu8.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Now when you have your desired routes defined, just import the functions and call them:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;findPetsByStatus&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;available&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;response&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response object has a typed &lt;code&gt;data&lt;/code&gt; property that's available when request is finished successfully. This can be checked with &lt;code&gt;ok&lt;/code&gt; property:&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%2Fb4aiu3ei0xeg2t7lmw4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4aiu3ei0xeg2t7lmw4e.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is crucial to check if request was successful before accessing the data, because failed request is also a valid case. This semantic forces you to handle bad cases as well, for example showing an error toast to the user.&lt;/p&gt;

&lt;p&gt;Request parameters are also automatically suggested and validated for correctness:&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%2F8h75ceio5hxnim318p2c.gif" 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%2F8h75ceio5hxnim318p2c.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you've got a first impression of the library, let's dive into its features and see how it fits into different scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server Side Rendering (SSR)
&lt;/h3&gt;

&lt;p&gt;You can use the library in SvelteKit's load functions, to request data on server:&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;findPetByStatus&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;src/api.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fetch&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;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;findPetByStatus&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sold&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;fetch&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;resp&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&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;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&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;pets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resp&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="na"&gt;error&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="k"&gt;else&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;pets&lt;/span&gt;&lt;span class="p"&gt;:&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;Failed to load pets&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that in this case you need to explicitly provide server's &lt;code&gt;fetch&lt;/code&gt; implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Await syntax
&lt;/h3&gt;

&lt;p&gt;If you like to await promises in Svelte templates, then you can use &lt;code&gt;ready&lt;/code&gt; store from the request object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&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="nx"&gt;findPetByStatus&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;src/api.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;findPetByStatus&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sold&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;petsReady&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#await&lt;/span&gt; &lt;span class="nx"&gt;$petsReady&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Loading..&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;:then&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#each&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pet&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pet&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="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/each&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="k"&gt;else&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Error while loading pets&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/await&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="si"&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Reload pets
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Autosuggestion works there as well!&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%2F56z5kw8ir71zzs1k1y6t.gif" 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%2F56z5kw8ir71zzs1k1y6t.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrying a request
&lt;/h3&gt;

&lt;p&gt;The curious reader has noticed that API call doesn't return a response directly, but a request object. It's designed to satisfy different needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;subscribe to a &lt;code&gt;ready&lt;/code&gt; store and wait for updates&lt;/li&gt;
&lt;li&gt;await for response in template&lt;/li&gt;
&lt;li&gt;await the &lt;code&gt;result&lt;/code&gt; promise right away (for example in server code)&lt;/li&gt;
&lt;li&gt;trigger a reload of the same request with the same parameters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example you might want to periodically refresh the page content, and the parameters of such request stay the same:&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;components&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;src/petstore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;schemas&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;Pet&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;findPetsByStatus&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;available&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;pets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resp&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="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;setInterval&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example also shows that you can access backend types programmatically by importing them:&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%2Fyi4p3gb155lynxrxcbsi.gif" 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%2Fyi4p3gb155lynxrxcbsi.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Error handling
&lt;/h2&gt;

&lt;p&gt;Errors can be expected and unexpected. First ones usually have an HTTP status code starting from 4, e.g 404 when a resource is not found on server, or 422 when your payload is incorrect. Sometimes you even have special handlers for them on frontend side. Often these requests have a JSON body in order to indicate what was wrong.&lt;br&gt;
However under certain conditions a request can fail unexpectedly, for example when backend is down, or due to unstable network. These requests might not have a body, they usually throw an error on client side.&lt;/p&gt;

&lt;p&gt;We thought that it's a good idea to provide a developer a single interface for handling both kinds of errors. Thus, each response has &lt;code&gt;ok&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt; properties to debug the issue properly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ok&lt;/code&gt; is set to &lt;code&gt;false&lt;/code&gt; for every failed request&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;status&lt;/code&gt; is a HTTP status code and it's set by backend most of the times, but for exceptional cases like network errors it will be a negative value like &lt;code&gt;-1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;error&lt;/code&gt; contains a JSON body from backend if provided or set to &lt;code&gt;undefined&lt;/code&gt; otherwise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please always care about error cases to build better services!&lt;/p&gt;
&lt;h2&gt;
  
  
  Bonus - pre-commit hooks
&lt;/h2&gt;

&lt;p&gt;Now you have a mechanism to generate frontend types from OpenAPI spec, so backend becomes a single source of truth and you don't need to repeat a lot of code by hands. But there's still no answer on how to keep types in sync. One of the possible approaches is to use pre-commit hooks, like &lt;a href="https://pre-commit.com/" rel="noopener noreferrer"&gt;pre-commit&lt;/a&gt; or &lt;a href="https://typicode.github.io/husky" rel="noopener noreferrer"&gt;Husky&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pre commit hooks are set of commands to execute every time you run &lt;code&gt;git commit&lt;/code&gt;. If you have a monorepo, then you can configure hooks to export OpenAPI spec and run &lt;code&gt;openapi-typescript&lt;/code&gt; consequently. If your spec is accessible over network, then just create an npm script with a URL as a parameter. Possible example for Petsore:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&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;"openapi-typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^6.2.0"&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;"scripts"&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;"make-api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openapi-typescript https://petstore3.swagger.io/api/v3/openapi.json --output src/lib/openapi.ts"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.pre-commit-config.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;repos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;make-api&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;make-api&lt;/span&gt;
        &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run make-api&lt;/span&gt;
        &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;system&lt;/span&gt;
        &lt;span class="na"&gt;pass_filenames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

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

&lt;/div&gt;



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

&lt;p&gt;We hope that managing your API requests will be easier now thanks to Apity. We already use it in our SvelteKit projects and the experience is rather fun so far. Please try it out if you find this approach interesting enough, and your &lt;a href="https://github.com/cocreators-ee/apity/issues" rel="noopener noreferrer"&gt;feedback&lt;/a&gt; is always appreciated.&lt;/p&gt;

&lt;p&gt;Also I built a simple demo application using same Petstore spec, you can check it out at &lt;a href="https://apity-demo.vercel.app" rel="noopener noreferrer"&gt;https://apity-demo.vercel.app&lt;/a&gt;.&lt;br&gt;
Each page has a source code snippet for your convenience.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>api</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Reducing Docker image size of a Nuxt SSR application</title>
      <dc:creator>Denis</dc:creator>
      <pubDate>Mon, 17 May 2021 14:02:17 +0000</pubDate>
      <link>https://forem.com/fbjorn/reducing-docker-image-size-of-a-nuxt-ssr-application-40oe</link>
      <guid>https://forem.com/fbjorn/reducing-docker-image-size-of-a-nuxt-ssr-application-40oe</guid>
      <description>&lt;p&gt;Recently I had to create a deployment of a NuxtJS application which is running in SSR mode. I have a separate backend that is already packed in Docker image, so it sounds pretty tempting to dockerize the frontend application as well and to run both using docker-compose. Basically, server side rendering implies that the frontend application becomes a server too, to some extent. &lt;/p&gt;

&lt;p&gt;To demonstrate the concept, I will show you two Dockerfiles, one is straightforward, without any optimizations, and another is what goes into production. &lt;/p&gt;

&lt;p&gt;First obvious idea is to get the smallest node-based image available. Of course, it's an Alpine one. &lt;/p&gt;

&lt;p&gt;So let's consider this &lt;code&gt;Dockerfile&lt;/code&gt;, assuming we don't care about a final size too much:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:15.11.0-alpine3.12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;frontend&lt;/span&gt;

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

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; frontend ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn build

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["npx", "nuxt", "start"]&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now check the size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ docker images | &lt;span class="nb"&gt;grep &lt;/span&gt;demo-frontend
demo-frontend     latest     151ebafca257   1 minute ago   782MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I couldn't bear the thought that a simple frontend application will take almost 800MB of disk space. It's not a surprise though, cause &lt;code&gt;node_modules&lt;/code&gt; is enormous. We could of course use multi-stage builds and install only production dependencies for runtime, but it would not cost the effort:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ yarn &lt;span class="nb"&gt;install&lt;/span&gt;
➜ &lt;span class="nb"&gt;du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; node_modules
386M    node_modules

➜ yarn &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--production&lt;/span&gt;
➜ &lt;span class="nb"&gt;du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; node_modules
276M node_modules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now the trick. Let's check what's inside of a &lt;code&gt;.nuxt&lt;/code&gt; folder, that is generated by &lt;code&gt;nuxt build&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ yarn build
➜ &lt;span class="nb"&gt;du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; .nuxt/dist/&lt;span class="k"&gt;*&lt;/span&gt;
5.5M    .nuxt/dist/client
1.2M    .nuxt/dist/server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks pretty strange that client-side code takes more space than the server-side, isn't it? 🤔&lt;br&gt;
Apparently, server-side code is relying on third-party libraries stored in the node modules. They are not bundled.&lt;/p&gt;

&lt;p&gt;The good thing is that Nuxt offers a solution, a &lt;code&gt;--standalone&lt;/code&gt; option that solves this issue. Let's try to rebuild and compare.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ yarn build --standalone
➜ du -sh .nuxt/dist/*
5.5M .nuxt/dist/client
 39M .nuxt/dist/server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yep, something has changed for sure. Dependencies for a server runtime are now stored in &lt;code&gt;.nuxt&lt;/code&gt; folder, so we don't need all the &lt;code&gt;node_modules&lt;/code&gt; anymore.&lt;/p&gt;

&lt;p&gt;And now the final insight: you don't need the entire &lt;code&gt;nuxt&lt;/code&gt; package to run your code using &lt;code&gt;nuxt start&lt;/code&gt;. There's a separate package that is optimized only for running bundles in SSR mode: &lt;a href="https://www.npmjs.com/package/nuxt-start"&gt;nuxt-start&lt;/a&gt;. So the final step is to install this package in a runtime Docker image and skip the rest.&lt;/p&gt;

&lt;p&gt;Let's have a look on the final &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:15.11.0-alpine3.12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;frontend-build&lt;/span&gt;

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

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; frontend/yarn.lock frontend/package.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; frontend ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn build &lt;span class="nt"&gt;--standalone&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:15.11.0-alpine3.12&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NUXT_VERSION=2.15.6&lt;/span&gt;

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

&lt;span class="k"&gt;RUN &lt;/span&gt;yarn add &lt;span class="s2"&gt;"nuxt-start@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NUXT_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=frontend-build /src/.nuxt /app/.nuxt&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=frontend-build /src/nuxt.config.ts /app/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=frontend-build /src/static /app/&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["npx", "nuxt-start"]&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case you wonder what we've just done:&lt;/p&gt;

&lt;p&gt;In build image (that is not used in production):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the dependencies from &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Build an application in a standalone mode, so &lt;code&gt;.nuxt&lt;/code&gt; folder contains everything we need&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In runtime image (that is running in production)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;code&gt;nuxt-start&lt;/code&gt;, a package that will run our app&lt;/li&gt;
&lt;li&gt;Copy the &lt;code&gt;.nuxt&lt;/code&gt; folder from the build image, as well as static folder and NuxtJS config&lt;/li&gt;
&lt;li&gt;Run the app&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, how much the final image weighs?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;demo-frontend     latest     f41a130ae000   21 seconds ago   208MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yep, that's true 🙂 We've just saved 574 MB of a disk space, final image became &lt;strong&gt;3.75 times thinner&lt;/strong&gt; than initial!&lt;/p&gt;

&lt;p&gt;Of course, it highly depends on the size of your dependencies, but I'm sure you got the idea. Please also keep in mind that it's a good idea to install &lt;code&gt;nuxt-start&lt;/code&gt; with the same version as &lt;code&gt;nuxt&lt;/code&gt; from your &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;TL;DR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get Alpine as a base image&lt;/li&gt;
&lt;li&gt;Leverage multi stage builds&lt;/li&gt;
&lt;li&gt;Bundle dependencies into server code&lt;/li&gt;
&lt;li&gt;Run server using &lt;code&gt;nuxt-start&lt;/code&gt; package&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy deploying! 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Edit on May, 21:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There was a suggestion in comments by &lt;a class="mentioned-user" href="https://dev.to/artalus"&gt;@artalus&lt;/a&gt; to not use multi-stage builds, but to put all the logic into single &lt;code&gt;RUN&lt;/code&gt; statement instead. In theory, it should result into even more space savings due to reducing the number of docker layers. Let's try it out!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:15.11.0-alpine3.12&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NUXT_VERSION=2.15.6&lt;/span&gt;

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

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; frontend ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;: &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn build &lt;span class="nt"&gt;--standalone&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; node_modules &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm &lt;/span&gt;package.json &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn add &lt;span class="s2"&gt;"nuxt-start@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NUXT_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn cache clean &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; :

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["npx", "nuxt-start"]&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🥁 ...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;demo-frontend     latest     2e2ca36f6c2e   30 seconds ago   195MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome! 13MB may not sound that great, but now the total result is less than 200! Or officially &lt;strong&gt;4x times thinner&lt;/strong&gt; than initial version.&lt;/p&gt;

&lt;p&gt;I intentionally haven't modified original post to show you the idea of applying optimizations step-by-step. &lt;/p&gt;

&lt;p&gt;Please also note that using single &lt;code&gt;RUN&lt;/code&gt; statement slows down your build to some point, cause &lt;code&gt;yarn install&lt;/code&gt; step is not cached anymore. However, this is only relevant if you have caching enabled on your CI agent.&lt;/p&gt;

&lt;p&gt;Cheers! 🎉&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>devops</category>
      <category>nuxt</category>
      <category>vue</category>
    </item>
    <item>
      <title>Deploying to GitHub Pages without extra dependencies</title>
      <dc:creator>Denis</dc:creator>
      <pubDate>Thu, 18 Mar 2021 09:06:52 +0000</pubDate>
      <link>https://forem.com/fbjorn/deploying-to-github-pages-without-extra-dependencies-3645</link>
      <guid>https://forem.com/fbjorn/deploying-to-github-pages-without-extra-dependencies-3645</guid>
      <description>&lt;p&gt;There are a lot of articles already describing how to deploy you static website to GitHub Pages from GitHub Actions. Almost all of them suggest to use 3rd party Actions available on marketplace. &lt;/p&gt;

&lt;p&gt;Some of them are extremely popular, like &lt;a href="https://github.com/peaceiris/actions-gh-pages"&gt;this one&lt;/a&gt;.&lt;br&gt;
Some &lt;a href="https://github.com/crazy-max/ghaction-github-pages"&gt;less&lt;/a&gt;, but still doing their job as you expect from them.&lt;/p&gt;

&lt;p&gt;And long story short, you can just use them, it's pretty convenient to delegate this logic to &lt;em&gt;something&lt;/em&gt; and avoid maintenance effort. However, you need to understand that it's a security implication and you pass your &lt;strong&gt;secret&lt;/strong&gt; token of the repository to 3rd party code. Which in theory can contain some sneaky bug or even be malformed. Yeah, they're open source and you can check the code and validate it yourself, but.. would you?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I still don't get why GitHub doesn't provide out-of-the-box functionality to connect 2 of their services together, and why you need to look for extra packages rather than use some built-in feature, like in Travis..&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, deploying to GitHub Actions is pretty straightforward: you just need to push desired files to some branch in your repo, and that's basically it. Why to complicate things then and use untrusted javascript code for simply invoking &lt;code&gt;git commit &amp;amp;&amp;amp; git push&lt;/code&gt;? That's a fair question.&lt;/p&gt;

&lt;p&gt;One of awesome GitHub Action features is that you can access your secret token without any extra effort. So you basically don't have to deal with git authentication in any way.&lt;/p&gt;

&lt;p&gt;Combining this together, here's a snippet of a pipeline you can use to deploy static files from your repo to GitHub Pages:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;It's simple, customisable, and most importantly, doesn't leak your secrets to anywhere. &lt;/p&gt;

&lt;p&gt;Hope it helps!&lt;/p&gt;

</description>
      <category>github</category>
      <category>ci</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
