<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Max Core</title>
    <description>The latest articles on DEV Community by Max Core (@maxcore).</description>
    <link>https://dev.to/maxcore</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%2F892973%2F5b79b8a9-8cfa-4b3e-999e-f6bcb9d32dbf.jpeg</url>
      <title>DEV Community: Max Core</title>
      <link>https://dev.to/maxcore</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxcore"/>
    <language>en</language>
    <item>
      <title>SvelteKit 2: Code-based router instead of file-based router now is just a Gist!</title>
      <dc:creator>Max Core</dc:creator>
      <pubDate>Sun, 19 Apr 2026 19:57:11 +0000</pubDate>
      <link>https://dev.to/maxcore/sveltekit-2-code-based-router-instead-of-file-based-router-now-is-just-a-gist-28cm</link>
      <guid>https://dev.to/maxcore/sveltekit-2-code-based-router-instead-of-file-based-router-now-is-just-a-gist-28cm</guid>
      <description>&lt;p&gt;The idea is simple — just create universal &lt;code&gt;[...path]&lt;/code&gt; folder and proxy everything through it specifying patterns in some &lt;code&gt;urls.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, we have to create minimal and universal &lt;code&gt;+page.js&lt;/code&gt; and &lt;code&gt;+page.server.js&lt;/code&gt; with &lt;code&gt;load&lt;/code&gt; functions, find there 'pattern' in &lt;code&gt;urls.ts&lt;/code&gt; by &lt;code&gt;url.pathname&lt;/code&gt; we know in &lt;code&gt;load&lt;/code&gt;, set some &lt;code&gt;routeStore&lt;/code&gt;, containing desired page, and get it in &lt;code&gt;+page.svelte&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's kinda tricky, so we also need copy &lt;code&gt;router.ts&lt;/code&gt; from here:&lt;br&gt;
&lt;a href="https://github.com/webentlib/gists/blob/main/router.ts" rel="noopener noreferrer"&gt;https://github.com/webentlib/gists/blob/main/router.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Further message — just a copy of &lt;a href="https://github.com/webentlib/gists/blob/main/router.md" rel="noopener noreferrer"&gt;router.md&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please, let me know what do u think.&lt;br&gt;
Please share if you use something similar.&lt;/p&gt;
&lt;h2&gt;
  
  
  Minimal Example:
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;urls.ts&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;page&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;/src/base.svelte&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;patterns&lt;/span&gt; &lt;span class="o"&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;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                   &lt;span class="na"&gt;page&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;/src/home.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;        &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;{&lt;/span&gt;&lt;span class="na"&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;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="na"&gt;page&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;/src/users/users.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;{&lt;/span&gt;&lt;span class="na"&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;users/(&amp;lt;id&amp;gt;[0-9]+)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;page&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;/src/users/user.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;users.svelte&lt;/code&gt;&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;module&lt;/span&gt;&lt;span class="nt"&gt;&amp;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="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;users&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installation:
&lt;/h2&gt;

&lt;p&gt;1) Download &lt;a href="https://github.com/webentlib/gists/blob/main/router.ts" rel="noopener noreferrer"&gt;router.ts&lt;/a&gt; to some folder all external gists live, e.g.: /lab/.&lt;/p&gt;

&lt;p&gt;2) Move &lt;code&gt;routes/&lt;/code&gt; folder wherever you like, create &lt;code&gt;[...path]&lt;/code&gt; folder inside.&lt;/p&gt;

&lt;p&gt;3) Create 4 files:&lt;br&gt;&lt;br&gt;
&lt;code&gt;[...path]/+page.ts&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;Router&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;/lab/router.ts&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;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&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;[...path]/+page.server.ts&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;Router&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;/lab/router.ts&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;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;[...path]/+page.svelte&lt;/code&gt;:&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&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;routeStore&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;/lab/router.ts&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="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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;snippet&lt;/span&gt; &lt;span class="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routeStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&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="nd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routeStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&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="nd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routeStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&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;routeStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;routeStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Layout&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&amp;gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;render&lt;/span&gt; &lt;span class="nf"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routeStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Layout&amp;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;Page&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/&amp;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="sr"&gt;/snippet&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;@render draw&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;$routeStore, 0&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;+error.svelte&lt;/code&gt; (note — must be in &lt;code&gt;routes/&lt;/code&gt;, not &lt;code&gt;[...path]&lt;/code&gt;):&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;page&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;$app/state&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;Router&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;/lab/router.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&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;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&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="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="nb"&gt;Error&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="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;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;Error/&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4) Create urls in root (same level with &lt;code&gt;package.json&lt;/code&gt;):&lt;br&gt;&lt;br&gt;
&lt;code&gt;urls.ts&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;page&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;/src/base.svelte&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;patterns&lt;/span&gt; &lt;span class="o"&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;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;page&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;/src/home.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&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="c1"&gt;// {path: 'users/(&amp;lt;id&amp;gt;[0-9]+)', page: () =&amp;gt; import('/src/users/user.svelte'), layouts: [layout]},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5) Create sample pages in &lt;code&gt;/src/&lt;/code&gt;:&lt;br&gt;&lt;br&gt;
&lt;code&gt;base.svelte&lt;/code&gt;:&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&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;render&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?.()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;home.svelte&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;Hello, world!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6) Point svelte to routes folder you want it to be in:&lt;br&gt;&lt;br&gt;
&lt;code&gt;svelte.config.ts&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="nx"&gt;kit&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;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;routes/&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;7) Allow vite look files in root:&lt;br&gt;&lt;br&gt;
&lt;code&gt;vite.config.ts&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;allow&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="s1"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="c1"&gt;// Allow serving files from one level up to the project root&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;h2&gt;
  
  
  Extended Example:
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;urls.ts&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pattern&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="nb"&gt;Error&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;/lab/router.ts&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;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;page&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;/src/error.svelte&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;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;page&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;/src/base.svelte&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;error&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;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;page&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;/src/account.svelte&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;patterns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pattern&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="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                   &lt;span class="na"&gt;page&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;/src/home.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;          &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome&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;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;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="na"&gt;page&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;/src/users/users.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;   &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&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;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;users/(&amp;lt;id&amp;gt;[0-9]+)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;page&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;/src/users/user.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;    &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;{&lt;/span&gt;&lt;span class="na"&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;friends&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="na"&gt;page&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;/src/users/users.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;   &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&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;account&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;friends&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;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;settings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="na"&gt;page&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;/src/users/account.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&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;account&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;Yes. One can specify:&lt;br&gt;
1) Layout array for any page.&lt;br&gt;
2) For sure multiple patterns can point to same page like &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;friends&lt;/code&gt; in example in case same template but different data. &lt;br&gt;
3) Custom error for any page or layout.&lt;br&gt;
&lt;code&gt;error.svelte&lt;/code&gt;:&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;page&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;$app/state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&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="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&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;4) &lt;code&gt;Pattern&lt;/code&gt; and &lt;code&gt;Layout&lt;/code&gt; has &lt;code&gt;universal&lt;/code&gt; and &lt;code&gt;server&lt;/code&gt; properties to point to &lt;code&gt;load&lt;/code&gt; function in 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="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;universal&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;/src/home.server.js&lt;/span&gt;&lt;span class="dl"&gt;'&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="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;/src/home.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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5) Add any custom attributes like &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;h1&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt; to be used later in layout/page.&lt;br&gt;
&lt;code&gt;base.svelte&lt;/code&gt;:&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&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;routeStore&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;/lab/router.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&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="nx"&gt;$routeStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;$routeStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;render&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?.()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If one prefer both server and universal to be in &lt;code&gt;&amp;lt;script module&amp;gt;&lt;/code&gt;:&lt;br&gt;&lt;br&gt;
&lt;code&gt;user.svelte&lt;/code&gt;:&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;module&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="kd"&gt;get&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;svelte/store&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;routeStore&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;/lab/router.ts&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;server&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// in &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;could&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;named&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routeStore&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;slugs&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="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;universal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// could be named load&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routeStore&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;slugs&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="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Downsides:
&lt;/h2&gt;

&lt;p&gt;1) Both &lt;code&gt;+page.server.js&lt;/code&gt; and &lt;code&gt;+page.js&lt;/code&gt; runs on every rote. No way to say 'call only &lt;code&gt;+page.js&lt;/code&gt;'.&lt;/p&gt;

&lt;p&gt;2) &lt;code&gt;export const snapshot = {...}&lt;/code&gt; not working.&lt;/p&gt;

&lt;p&gt;3) No pragmatic way to specify options like &lt;code&gt;export let ssr = true;&lt;/code&gt; probably one can do it like (not tested):&lt;br&gt;
&lt;code&gt;urls.ts&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="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;ssr&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;+page.server.ts&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;Router&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;/lab/router.ts&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;let&lt;/span&gt; &lt;span class="nx"&gt;prerender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;let&lt;/span&gt; &lt;span class="nx"&gt;entries&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;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ssr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;let&lt;/span&gt; &lt;span class="nx"&gt;csr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;let&lt;/span&gt; &lt;span class="nx"&gt;trailingSlash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;never&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;let&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&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;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&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;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findPattern&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&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;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&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;pattern&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&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;eval&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;k&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;v&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="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same for &lt;code&gt;+page.ts&lt;/code&gt; but &lt;code&gt;return await Router.route(params, true)&lt;/code&gt; must be &lt;code&gt;return await Router.route(params)&lt;/code&gt; there.&lt;/p&gt;

&lt;h2&gt;
  
  
  P.S.
&lt;/h2&gt;

&lt;p&gt;That router is TS only, and was written with next tsconfig:&lt;br&gt;&lt;br&gt;
&lt;code&gt;tsconfig.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="nl"&gt;"rewriteRelativeImportExtensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"allowImportingTsExtensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="err"&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="nl"&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="s2"&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="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"noImplicitAny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>svelte</category>
      <category>sveltekit</category>
    </item>
    <item>
      <title>Svelte: Best practice to combine $derived and $state</title>
      <dc:creator>Max Core</dc:creator>
      <pubDate>Sat, 04 Oct 2025 12:33:06 +0000</pubDate>
      <link>https://dev.to/maxcore/svelte-best-practice-to-combine-derived-and-state-3f18</link>
      <guid>https://dev.to/maxcore/svelte-best-practice-to-combine-derived-and-state-3f18</guid>
      <description>&lt;p&gt;&lt;strong&gt;First approximation:&lt;/strong&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="kd"&gt;let&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&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;posts&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;posts&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;It is not documented, and me personally obtained it here:&lt;br&gt;
&lt;a href="https://discord.com/channels/457912077277855764/1406193849423888415/1406241130726690837" rel="noopener noreferrer"&gt;https://discord.com/channels/457912077277855764/1406193849423888415/1406241130726690837&lt;/a&gt;&lt;br&gt;
From &lt;em&gt;mjadobson&lt;/em&gt;, approved by &lt;em&gt;Patrick&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Others advice, for semantics and linters, that &lt;code&gt;let&lt;/code&gt; better be &lt;code&gt;const&lt;/code&gt;:&lt;/strong&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&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;posts&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;posts&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;Performance may depend on an engine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another way to make it one line:&lt;/strong&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&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;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&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;posts&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;_&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now, while copy-paste, there are 2 places left to change, not 4.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For sure, it COULD NOT be:&lt;/strong&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&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;$state&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;posts&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;$state(...)&lt;/code&gt; can only be used as a variable declaration initializer, a class field declaration, or the first assignment to a class field at the top level of the constructor.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Probably it'll be nice to have &lt;code&gt;$reactive&lt;/code&gt; rune one day, combining both or something&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;If one have more elegant solution — please share&lt;br&gt;
Thx&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>sveltekit</category>
    </item>
    <item>
      <title>Базовый ультимативный гайд по Nginx</title>
      <dc:creator>Max Core</dc:creator>
      <pubDate>Sat, 30 Dec 2023 17:24:34 +0000</pubDate>
      <link>https://dev.to/maxcore/basic-ultimate-guide-nginx-1ngd</link>
      <guid>https://dev.to/maxcore/basic-ultimate-guide-nginx-1ngd</guid>
      <description>&lt;p&gt;Ниже — две части.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;База — её можно быстро пролистать.&lt;/li&gt;
&lt;li&gt;Боевая имплементация — там то, что мы хотим на практике.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Важно учесть, что настройка Nginx — не только для "наших" задач.&lt;br&gt;
Все наши фреймворки, их middleware и т.д. — тоже рассчитывают на достоверные заголовки. Для корректной работы их &lt;code&gt;autoban&lt;/code&gt; и т.д.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  База. Зачем нужен Nginx. Логика &lt;code&gt;X-Forwarded-For&lt;/code&gt;.
&lt;/h2&gt;

&lt;p&gt;Тестировать будем на starlette.&lt;/p&gt;

&lt;p&gt;Создадим простой &lt;code&gt;main.py&lt;/code&gt;, который просто рисует http-мету:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;starlette.applications&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Starlette&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;starlette.responses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HTMLResponse&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;starlette.routing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Route&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;HTMLResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;pre&amp;gt;
        url: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
        client:
            host: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
            port: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
        headers:
            &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;amp;nbsp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; + v for k, v in request.headers.items())&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    &amp;lt;/pre&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Starlette&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;),])&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 plaintext"&gt;&lt;code&gt;uvicorn main:app --host=0.0.0.0 --port=2100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;И, если DNS настроены:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Его уже можно открыть в браузере по &lt;a href="http://myproject.org:2100"&gt;http://myproject.org:2100&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Он уже будет знать:

&lt;ul&gt;
&lt;li&gt;IP-пользователя в &lt;code&gt;request.client.host&lt;/code&gt; вида 'xxx.xxx.xxx.xxx'.&lt;/li&gt;
&lt;li&gt;Host-Cервера в &lt;code&gt;request.headers.host&lt;/code&gt; вида 'myproject.org:2100'.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Даже ssl/https можно прикрутить.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;И если обращаться к серверу прям так — &lt;a href="http://myproject.org:2100"&gt;http://myproject.org:2100&lt;/a&gt; — без прокси, без VPN-ов — как минимум с заголовками — всё будет нормально.&lt;/p&gt;

&lt;p&gt;Но:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Возможно — нам бы хотелось иметь возможность как-то знать о прокси/VPN-ах.&lt;/li&gt;
&lt;li&gt;Возможно — нам также хотелось бы — мапить/перемапливать урлы (чтобы по 'myproject.org/api/' открывалось 'api.org/take/some/api/dude/'); эффективней обслуживать статику (не приложением); контролировать — таймауты, размеры файловых аплоудов, размеры текстовых аплоудов; иметь возможность показать пользователю хоть что-то, пока сервер лежит/перезапускается; клёвое логирование и т.д. и т.п.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;А главное что нам хотелось бы — делать всё это через одну привычную технологию, на чём бы мы не писали наше приложение.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nginx
&lt;/h3&gt;

&lt;p&gt;Сэмулируем проксирование самих себя (может это мы сами для наших нужд):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;2200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://myproject.org:2100&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;Открываем браузер по &lt;code&gt;http://myproject.org:2200&lt;/code&gt;.&lt;br&gt;
В &lt;code&gt;request.client.host&lt;/code&gt; лежит уже не IP-Пользователя, а IP-Cервера, который к нам обратился.&lt;br&gt;
Скажем сразу — если доступа к этому конфигу у нас нет — многого мы не сделаем.&lt;/p&gt;

&lt;p&gt;Но, можем отловить "чуть более верхнего инициатора запроса" добавив "подконтрольный" нам конфиг:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;2100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://myproject.org:2000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&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;Запускаемся (но уже с портом 2000):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uvicorn main:app --host=0.0.0.0 --port=2000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Открываем браузер также по &lt;code&gt;http://myproject.org:2200&lt;/code&gt;.&lt;br&gt;
Теперь наш сервис дополнительно отображает нам некий &lt;code&gt;request.headers['x-real-ip']&lt;/code&gt; с IP отличающимся от &lt;code&gt;request.client.host&lt;/code&gt;.&lt;br&gt;
И если в &lt;code&gt;request.client.host&lt;/code&gt; у нас IP-Сервера, то в &lt;code&gt;request.headers['x-real-ip']&lt;/code&gt; похоже IP-Роутера-Сервера. (Но это не важно).&lt;/p&gt;

&lt;p&gt;А вот если бы тот первый конфиг был нам подконтролен (или просто настроен хорошо), то мы могли бы в обоих случаях добавить:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;2200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://myproject.org:2100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;# +&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&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;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;2100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://myproject.org:2000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;# +&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&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;И теперь, в &lt;code&gt;http://myproject.org:2200&lt;/code&gt; мы получим:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;В &lt;code&gt;request.headers.host&lt;/code&gt; лежит всё как надо — 'myproject.com:2200'.&lt;/li&gt;
&lt;li&gt;В &lt;code&gt;request.client.host&lt;/code&gt; всё также лежит IP-Сервера.&lt;/li&gt;
&lt;li&gt;В &lt;code&gt;request.headers['x-real-ip']&lt;/code&gt; лежит всё тот же IP-Роутера-Сервера.&lt;/li&gt;
&lt;li&gt;Но, появился ещё &lt;code&gt;request.headers['x-forwarded-for']&lt;/code&gt;, и это — цепочка IP-шников! Потерянный IP-Пользователя и IP-Роутера-Сервера.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Т.е., самый достоверный IP-пользователя — это всегда — &lt;code&gt;request.headers['x-forwarded-for'][0]&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Боевая имплементация
&lt;/h2&gt;

&lt;p&gt;Нам конечно не нужны такие двойные конфиги.&lt;br&gt;
Просто только так можно было понять 'X-Forwarded-For'.&lt;br&gt;
Что и в какой степени достоверно.&lt;/p&gt;

&lt;p&gt;И вот перед нами просто "голый" конфиг:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;2200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://headhall.com:2000&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;По &lt;code&gt;http://myproject.org:2200&lt;/code&gt; мы получим:&lt;br&gt;
Который показывает:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;В &lt;code&gt;request.headers.host&lt;/code&gt; лежит 'myproject.org:2000', хотя браузер открыт с ':2200'.&lt;/li&gt;
&lt;li&gt;В &lt;code&gt;request.client.host&lt;/code&gt; — IP-Сервера, а не IP-Пользователя.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;request.headers['x-real-ip']&lt;/code&gt; вообще нет.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;request.headers['x-forwarded-for']&lt;/code&gt; также нет.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Приводим конфиг в боевое состояние:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;2200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# Чтобы показывал :2200&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;# Пытаемся получить IP-Пользователя (и получим, если без прокси)&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;# Ещё пытаемся получить IP-Пользователя (и получим, если прокси наше или "нормальное")&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://headhall.com:2000&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;(Вместо &lt;code&gt;$http_host&lt;/code&gt; конечно можно — и &lt;code&gt;$host&lt;/code&gt; (без порта), и &lt;code&gt;$server_name&lt;/code&gt; (если хочется) и т.д. Просто &lt;code&gt;$http_host&lt;/code&gt; самый полный и универсальный.).&lt;br&gt;
(К слову, все эти &lt;code&gt;proxy_*&lt;/code&gt; можно указать и на уровне &lt;code&gt;server&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Закрепим, что мы получим в &lt;code&gt;http://myproject.org:2200&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;В &lt;code&gt;request.headers.host&lt;/code&gt; лежит гарантированный 'myproject.org:2200'.&lt;/li&gt;
&lt;li&gt;В &lt;code&gt;request.client.host&lt;/code&gt; — IP-Сервера, а не IP-Пользователя, как можно было ожидать — всегда НЕ надёжный ориентир.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;request.headers['x-real-ip']&lt;/code&gt; — IP-Пользователя, но, всё же — тоже НЕ надёжный ориентир.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;request.headers['x-forwarded-for'][0]&lt;/code&gt; — IP-Пользователя, как — наиболее надёжный ориентир.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;А вот теперь можно уже к — таймаутам, лимиту аплоудов и т.д.&lt;/p&gt;

&lt;p&gt;В помощь по всему что выше:&lt;br&gt;
Alphabetical index of variables: &lt;a href="https://nginx.org/en/docs/varindex.html"&gt;https://nginx.org/en/docs/varindex.html&lt;/a&gt;&lt;br&gt;
Злой, но золотой комментарий на SO: &lt;a href="https://stackoverflow.com/a/72586833/4117781"&gt;https://stackoverflow.com/a/72586833/4117781&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Удачи, авантюрист!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Базовый ультимативный гайд по событиям в JavaScript (на примере SvelteKit)</title>
      <dc:creator>Max Core</dc:creator>
      <pubDate>Tue, 14 Nov 2023 19:10:21 +0000</pubDate>
      <link>https://dev.to/maxcore/base-ultimate-guide-to-javascript-events-1k5f</link>
      <guid>https://dev.to/maxcore/base-ultimate-guide-to-javascript-events-1k5f</guid>
      <description>&lt;p&gt;&lt;em&gt;addEventListener? removeEventListener? useCapture? capture?&lt;br&gt;
click? mousedown? mouseup? touchstart? touchend?&lt;br&gt;
touchcancel? dragleave?&lt;br&gt;
stopPropogation? bubbling? capturing?&lt;br&gt;
mouseenter? mouseleave? mouseover? mouseout?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Был такой случай
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Выхожу из подъезда, передо мной бабушка.&lt;br&gt;
Делает шаг в сторону со словами: «Молодым везде дорога!».&lt;br&gt;
Я поблагодарил и вышел первым.&lt;br&gt;
Думаю — «Ну наконец-то — хоть одно нормальное правило.» :D&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Забавно, что, по-умолчанию — именно так и работают события в JavaScript.&lt;/p&gt;
&lt;h2&gt;
  
  
  По умолчанию — все действия Прогрессивные — сначала проходит Потомок, потом Родитель.
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('Родитель проходит вторым')}&amp;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="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('Потомок проходит первым')}&amp;gt;
        Молодым везде дорога
    &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;span class="nt"&gt;&amp;lt;/div&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;h2&gt;
  
  
  Есть только 1 способ начать пропускать старших:
&lt;/h2&gt;

&lt;p&gt;Родитель должен высказать Консервативное мнение (&lt;code&gt;capture&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;on:click&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('Родитель проходит первым')}&amp;gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Нам — старикам — почёт в любом случае.&lt;span class="nt"&gt;&amp;lt;/div&amp;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="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('Потомок проходит вторым')}&amp;gt;
        Молодым везде дорога же, не?
    &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;Если Родитель высказал Консервативное мнение — никакое Мнение Потомка не интересно.&lt;br&gt;
В этом вся логика.&lt;/p&gt;
&lt;h2&gt;
  
  
  Логика событий
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Браузер всегда проводит 2 слушания по определённому событию (&lt;code&gt;click&lt;/code&gt; в нашем случае):
Сначала — все Консервативные мнения (&lt;strong&gt;capturing&lt;/strong&gt;, события с &lt;code&gt;capture&lt;/code&gt;).
Потом — все Прогрессивные (&lt;strong&gt;bubbling&lt;/strong&gt;, обычные события без &lt;code&gt;capture&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;И, в каждом слушании начинает с мнения Родителя.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;И, если Родитель высказал Консервативное мнение,&lt;br&gt;
вот такое Консервативное мнение Потомка — не имеет смысла:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;on:click&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('Родитель проходит первым')}&amp;gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Нам — старикам — почёт в любом случае.&lt;span class="nt"&gt;&amp;lt;/div&amp;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="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('Потомок проходит вторым')}&amp;gt;
        Да, согласен — старикам у нас почёт
    &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;Также, не имеет смысла Потомку высказывать Консервативное мнение если Родитель другого мнения:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;on:click=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('Родитель проходит вторым')}&amp;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="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('Потомок проходит первым')}&amp;gt;
        Старикам у нас почёт
    &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;span class="nt"&gt;&amp;lt;/div&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;Потому что, если Потомок выскажет Консервативное мнение — в этом также не будет смысла,&lt;br&gt;
потому что у Родителя — нет Консервативного мнения.&lt;br&gt;
Значит — он не хочет идти вперёд.&lt;/p&gt;
&lt;h2&gt;
  
  
  JavaScript это не жизнь. Здесь возможны 2-е параллельные вселенные:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;on:click&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('C1')} on:click={() =&amp;gt; alert('4')}&amp;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="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; alert('2')} on:click={() =&amp;gt; alert('3')}&amp;gt;
        Кнопка
    &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;Именно поэтому, когда мы навешиваем:&lt;br&gt;
&lt;code&gt;addEventListener(process)&lt;/code&gt;&lt;br&gt;
То удаляем мы его вот так:&lt;br&gt;
&lt;code&gt;removeEventListener(process)&lt;/code&gt;&lt;br&gt;
А когда мы навешиваем:&lt;br&gt;
&lt;code&gt;addEventListener(process, true)&lt;/code&gt;&lt;br&gt;
То и удаляем мы его вот так:&lt;br&gt;
&lt;code&gt;removeEventListener(process, true)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;И, без разницы где и как именно указывать — &lt;code&gt;true&lt;/code&gt; или &lt;code&gt;{capture: true}&lt;/code&gt;.&lt;br&gt;
К слову &lt;code&gt;removeEventListener&lt;/code&gt; не будет работать, если событие навешено через html-атрибут (&lt;code&gt;onclick="..."&lt;/code&gt;), даже если «перенавесить» через &lt;code&gt;addEventListener&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Но, у нас есть не только &lt;code&gt;click&lt;/code&gt;, есть и &lt;code&gt;mousedown&lt;/code&gt;, &lt;code&gt;mouseup&lt;/code&gt; и т.д.
&lt;/h2&gt;

&lt;p&gt;Они тоже имеют свой порядок.&lt;br&gt;
Сначала отработают вообще все &lt;code&gt;mousedown&lt;/code&gt; на странице, потом &lt;code&gt;mouseup&lt;/code&gt;, и только потом &lt;code&gt;click&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;on:mousedown&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; console.log('D1')} on:mousedown={() =&amp;gt; console.log('D4')}
    on:mouseup|capture={() =&amp;gt; console.log('U1')} on:mouseup={() =&amp;gt; console.log('U4')}
    on:click|capture={() =&amp;gt; console.log('C1')} on:click={() =&amp;gt; console.log('C4')}
&amp;gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
        &lt;span class="na"&gt;on:mousedown&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; console.log('D2')} on:mousedown={() =&amp;gt; console.log('D3')}
        on:mouseup|capture={() =&amp;gt; console.log('U2')} on:mouseup={() =&amp;gt; console.log('U3')}
        on:click|capture={() =&amp;gt; console.log('C2')} on:click={() =&amp;gt; console.log('C3')}
    &amp;gt;
        Кнопка
    &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;Выведет:&lt;br&gt;
&lt;code&gt;&amp;gt; D1, D2, D3, D4, U1, U2, U3, U4, C1, C2, C3, C4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Где посмотреть достоверный список приоритетов — не знаю.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;e.stopPropagation&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Без него можно обойтись.&lt;br&gt;
В «моём кодстайле» его использовать запрещено в пользу игры с переменными &lt;code&gt;is_el_doing_smth&lt;/code&gt;.&lt;br&gt;
Но, во имя науки:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(П — Прогрессивное; К — Консервативное)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;on:mouseup&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; console.log('К1')}
     on:mouseup={() =&amp;gt; console.log('П3')}&amp;gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;on:mouseup&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;stopPropagation=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; console.log('К2')}
         on:mouseup|stopPropagation={() =&amp;gt; console.log('П2')}&amp;gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;on:mouseup&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;capture=&lt;/span&gt;&lt;span class="s"&gt;{()&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; console.log('К3')}
             on:mouseup={() =&amp;gt; console.log('П1')}&amp;gt;
            Поехали
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&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;Выведет:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;K1, K2&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Т.е. &lt;code&gt;stopPropagation&lt;/code&gt; навешанный на событие с &lt;code&gt;capture&lt;/code&gt; заблокировало все будущие &lt;code&gt;mouseup&lt;/code&gt; — и с &lt;code&gt;capture&lt;/code&gt; и без него.&lt;br&gt;
Таким образом, что &lt;code&gt;stopPropagation&lt;/code&gt;, навешанный на событие без &lt;code&gt;capture&lt;/code&gt; уже не имеет смысла.&lt;br&gt;
Однако, это никак не повлияет, если на эти же элементы навесить событие, которое вызывается позже, к примеру &lt;code&gt;click&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Если убрать все &lt;code&gt;stopPropagation&lt;/code&gt;, выведет:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;К1, К2, К3, П1, П2, П3&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;e.preventDefault&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Про него вы всё сами знаете, но, есть один момент:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
    &lt;span class="na"&gt;on:touchstart=&lt;/span&gt;&lt;span class="s"&gt;{(e)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; e.preventDefault()}
    on:click={() =&amp;gt; alert('Алерт, который НЕ отработает на телефоне')}
&amp;gt;
    Кнопка 1
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
    &lt;span class="na"&gt;on:touchmove=&lt;/span&gt;&lt;span class="s"&gt;{(e)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; e.preventDefault()}
    on:click={() =&amp;gt; alert('Алерт, который отработает везде')}
&amp;gt;
    Кнопка 2
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Подробнее:&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Touch_events"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Touch_events&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Чем отличаются &lt;code&gt;mousedown&lt;/code&gt;, &lt;code&gt;mouseup&lt;/code&gt; и &lt;code&gt;click&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;mousedown&lt;/code&gt; — нам не важно где был курсор когда мы нажали мышку, важно что отпустили его мы именно на этом элементе.&lt;br&gt;
&lt;code&gt;mouseup&lt;/code&gt; — нам не важно где мы отпустим мышку, главное, что нажата она была именно тут.&lt;br&gt;
&lt;code&gt;click&lt;/code&gt; — нажали, поводили хоть по всему экрану, вернулись на элемент, отпустили — и вот тогда это клик.&lt;/p&gt;

&lt;p&gt;Т.е. &lt;code&gt;click&lt;/code&gt; — мы могли бы реализовать сами.&lt;br&gt;
Что, кстати, бывает очень нужно для реализации некого &lt;em&gt;click-outside&lt;/em&gt; (будет в другой статье).&lt;br&gt;
Потому что — пусть &lt;code&gt;click&lt;/code&gt; — это &lt;code&gt;mousedown&lt;/code&gt; и &lt;code&gt;mouseup&lt;/code&gt; внутри одного элемента, он при этом не понимаем на каком именно элементе мы нажали, а на каком отпустили.&lt;br&gt;
Есть конечно всякие &lt;code&gt;e.target&lt;/code&gt;, &lt;code&gt;e.currentTarget&lt;/code&gt;, &lt;code&gt;e.relatedTarget&lt;/code&gt;, &lt;code&gt;e.originalTarget&lt;/code&gt; и т.д.&lt;br&gt;
Но, половина из них не работает для click, а вторая половина не везде поддерживается (всё это без меня).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Из того, что работает одинаково для всех событий:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;e.currentTarget&lt;/code&gt; — это элемент на котором висит само событие, а&lt;br&gt;
&lt;code&gt;e.target&lt;/code&gt; — это первый самый далёко-вложенных Потомок внутри этого элемента.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;click&lt;/code&gt; работает и на компе и на телефоне, т.е. никакого события &lt;code&gt;touch&lt;/code&gt; на телефоне не существует.&lt;/p&gt;

&lt;p&gt;Но, на телефоне:&lt;br&gt;
&lt;code&gt;mousedown&lt;/code&gt; — это — &lt;code&gt;touchstart&lt;/code&gt;&lt;br&gt;
&lt;code&gt;mouseup&lt;/code&gt; — это — &lt;code&gt;touchend&lt;/code&gt;&lt;br&gt;
К слову:&lt;br&gt;
&lt;code&gt;mousemove&lt;/code&gt; — это — &lt;code&gt;touchmove&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Есть ещё &lt;code&gt;mouseleave&lt;/code&gt;, когда курсор покидает элемент.&lt;br&gt;
Но на телефоне — нет курсора.&lt;br&gt;
Однако, на телефоне, мы можем нажать и вести, и тогда &lt;code&gt;mouseleave&lt;/code&gt; мог бы пригодиться.&lt;br&gt;
Но, это событие решили не реализовывать.&lt;br&gt;
Вместо этого, сделали так, что когда мы ведём пальцем за пределы экрана (не браузера) — выбрасывается &lt;code&gt;touchend&lt;/code&gt;.&lt;br&gt;
Но, если хочется выбрасывать событие, когда мы вышли за пределы элемента, то можно это сделать так:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height:100px;background:#f00;"&lt;/span&gt;
     &lt;span class="na"&gt;on:touchstart=&lt;/span&gt;&lt;span class="s"&gt;{(e)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; el = e.currentTarget}
     on:touchmove={(e) =&amp;gt; {
         const {pageX, pageY} = e.touches[0];
         const realElement = document.elementFromPoint(pageX, pageY)
         if (realElement !== el) {
             alert('touchleave')
         }
     }}&amp;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;Есть ещё &lt;code&gt;touchcancel&lt;/code&gt;, призванный обработать конфликты нажатия несколькими пальцами, но не работает в Safari, пэтому не используем.&lt;br&gt;
Есть ещё &lt;code&gt;dragleave&lt;/code&gt;, но это не ведение пальце, а именно перетаскивание элемента (картинки).&lt;/p&gt;

&lt;p&gt;К слову, чем отличается &lt;code&gt;mouseenter&lt;/code&gt;+&lt;code&gt;mouseleave&lt;/code&gt; от &lt;code&gt;mouseover&lt;/code&gt;+&lt;code&gt;mouseout&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;"Дом"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height:100px;background:#f00;"&lt;/span&gt;
     &lt;span class="na"&gt;on:mouseenter=&lt;/span&gt;&lt;span class="s"&gt;{(e)&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; {console.log('вОшли Дом')}}
     on:mouseleave={(e) =&amp;gt; {console.log('вЫшли Дома')}}
     on:mouseover={(e) =&amp;gt; {console.log('перешли В Дом или Комнату')}}
     on:mouseout={(e) =&amp;gt; {console.log('перешли ИЗ Дома или Комнаты')}}
&amp;gt;
    Каждый раз когда мы заходим в Дом — вызывается `mouseenter`.&lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
    Каждый раз когда мы выходим из Дома — вызывается `mouseleave`.
    &lt;span class="nt"&gt;&amp;lt;pre&lt;/span&gt; &lt;span class="na"&gt;data-name=&lt;/span&gt;&lt;span class="s"&gt;"Комната"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height:100px;width:50%;margin-left:50%;background:#000;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Каждый раз когда курсор пересекает границу этой Комнаты внутри Дома:&lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
            вызываются и mouseout и mouseover (именно в таком порядке).
    &lt;span class="nt"&gt;&amp;lt;/pre&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;h2&gt;
  
  
  Иии, внииимаааниииеее...
&lt;/h2&gt;

&lt;p&gt;Спасибо, за внимание.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Базовый ультимативный гайд по Node.js (на примере SvelteKit)</title>
      <dc:creator>Max Core</dc:creator>
      <pubDate>Sat, 11 Nov 2023 09:56:38 +0000</pubDate>
      <link>https://dev.to/maxcore/base-ultimate-guide-to-nodejs-3a4m</link>
      <guid>https://dev.to/maxcore/base-ultimate-guide-to-nodejs-3a4m</guid>
      <description>&lt;p&gt;&lt;em&gt;dependencies? devDependencies? peerDependencies?&lt;br&gt;
npm install? npm i? npm ci?&lt;br&gt;
--save? --save-dev? --save-prod? -g?&lt;br&gt;
package.json? package-lock.json? .npmrc?&lt;br&gt;
"module": "^1.0.0"?&lt;br&gt;
"module": "~1.0.0"?&lt;br&gt;
"module": "1.0.0"?&lt;br&gt;
Что из этого можно править руками?&lt;br&gt;
Что из этого в Гит?&lt;br&gt;
Какой командой в итоге билдить?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Актуально для: &lt;code&gt;node -v&lt;/code&gt; — v20.5.0 и &lt;code&gt;npm -v&lt;/code&gt; — 10.2.3&lt;/p&gt;
&lt;h2&gt;
  
  
  Что предлагает Svelte на старте?
&lt;/h2&gt;

&lt;p&gt;(После &lt;code&gt;npm create svelte@latest my-app&lt;/code&gt;)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;В &lt;code&gt;package-lock.json&lt;/code&gt; только &lt;code&gt;devDependencies&lt;/code&gt; (без prod-&lt;code&gt;dependencies&lt;/code&gt;):&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;И все эти зависимости «из коробки» НЕ строгие, т.е. с &lt;code&gt;^&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```
"devDependencies": {
    "@sveltejs/adapter-auto": "^2.0.0",
    "@sveltejs/kit": "^1.20.4",
    "svelte": "^4.0.5",
    "vite": "^4.4.2"
}, 
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;.npmrc&lt;/code&gt; (NPM Run Command) с единственной строкой &lt;code&gt;engine-strict=true&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;P.S. &lt;code&gt;package-lock.json&lt;/code&gt; нет вообще (и не надо).&lt;/p&gt;

&lt;h2&gt;
  
  
  Что рекомендуют разработчики Svelte?
&lt;/h2&gt;

&lt;p&gt;Определиться с адаптером, вместо &lt;code&gt;adapter-auto&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's recommended to install the appropriate adapter to your devDependencies once you've settled on a target environment, since this will add the adapter to your lockfile and slightly improve install times on CI.&lt;br&gt;
&lt;a href="https://kit.svelte.dev/docs/adapter-auto"&gt;https://kit.svelte.dev/docs/adapter-auto&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Мы люди простые, — возьмём универсальный &lt;code&gt;adapter-node&lt;/code&gt;.&lt;br&gt;
Итак,&lt;/p&gt;
&lt;h2&gt;
  
  
  Как установить новый модуль?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.npmjs.com/cli/v10/commands/npm-install"&gt;https://docs.npmjs.com/cli/v10/commands/npm-install&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;По умолчанию, &lt;code&gt;npm install @sveltejs/adapter-node&lt;/code&gt; — запишет в prod-&lt;code&gt;dependencies&lt;/code&gt;.&lt;br&gt;
Потом, можно перекинуть в &lt;code&gt;devDependencies&lt;/code&gt; путём:&lt;br&gt;
&lt;code&gt;npm install @sveltejs/adapter-auto --save-dev&lt;/code&gt;.&lt;br&gt;
Но, снова вернуть в «prod» той же командой:&lt;br&gt;
&lt;code&gt;npm install @sveltejs/adapter-auto&lt;/code&gt; уже не получится.&lt;br&gt;
Чтобы форсануть обратно в «prod»:&lt;br&gt;
&lt;code&gt;npm install @sveltejs/adapter-auto --save-prod&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm install @sveltejs/adapter-auto --save&lt;/code&gt; — такого просто нет (как минимум в npm v10)&lt;/li&gt;
&lt;li&gt;Но нода не ругается на несуществующие параметры.&lt;/li&gt;
&lt;li&gt;Более того, ей без разницы —
что так: &lt;code&gt;npm install module-name --param&lt;/code&gt;,
что так: &lt;code&gt;npm install --param module-name&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;А вообще можно и просто &lt;code&gt;npm i module-name&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Можно и &lt;code&gt;npm i module_name -g&lt;/code&gt;, если модуль нужен не для проекта, а как консольная утилита для чего-нибудь.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Но это не то, что нам нужно.&lt;br&gt;
Мы знаем, чем оборачивается «НЕ строгая версия».&lt;/p&gt;
&lt;h2&gt;
  
  
  Как установить строгую версию?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Есть 4 способа:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;npm config set save-exact true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Сомнительно, т.к. делает запись где-то глобально, и только на локальной машине.&lt;/p&gt;

&lt;p&gt;P.S.&lt;br&gt;
Создаётся на самом деле 2-е переменные в &lt;code&gt;npm config list&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;save-exact = true&lt;/code&gt;&lt;br&gt;
&lt;code&gt;save-prefix = ""&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Если вернуть обратно (&lt;code&gt;npm config set save-exact true&lt;/code&gt;), будет:&lt;br&gt;
&lt;code&gt;save-exact = false&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;save-prefix = "^"&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;npm install @sveltejs/adapter-auto --save-exact&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Делает свою работу, но нам нужна защита от дурака, на всю команду.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Добавить в &lt;code&gt;.npmrc&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;save-exact=true&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Т.е., теперь, когда мы делаем &lt;code&gt;npm i module-name&lt;/code&gt; он автоматически будет устанавливать строгую версию, без &lt;code&gt;^&lt;/code&gt;. &lt;br&gt;
   (Тут, никаких &lt;code&gt;save-prefix = ""&lt;/code&gt; не надо, это была внутренняя штука для глобального конфига.)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Можно руками постирать все &lt;code&gt;^&lt;/code&gt;, но — тогда у нас окажутся устаревшие пакеты :D.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;То, что было вначале пришло в &lt;code&gt;devDependencies&lt;/code&gt; — не совсем свежее.&lt;br&gt;
   Но, пока мы ещё ничего не установили, у нас нет ни &lt;code&gt;node_modules/&lt;/code&gt;, ни &lt;code&gt;package-lock.json&lt;/code&gt; — нам ничего не мешает действительно всё прописать руками.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Итого:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Идём по П.3. — добавляем в &lt;code&gt;.npmrc&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;save-exact=true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Для всего, что видим в &lt;code&gt;devDependencies&lt;/code&gt; — заного поочерёдно делаем &lt;code&gt;npm i module-name&lt;/code&gt;. (Они перелетят из &lt;code&gt;devDependencies&lt;/code&gt; в prod-&lt;code&gt;dependencies&lt;/code&gt;. Пока, тут это нам и нужно.)&lt;/li&gt;
&lt;li&gt;Ну и наконец-то устанавливаем наш &lt;code&gt;adapter-auto&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;npm i @sveltejs/adapter-auto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;P.S. Устанавливая один модуль — установятся все &lt;code&gt;dependencies&lt;/code&gt;, как если бы мы делали всё это одним &lt;code&gt;npm i&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;А &lt;code&gt;@sveltejs/adapter-auto&lt;/code&gt; можно удалить, чтоб не мешался.&lt;/p&gt;
&lt;h2&gt;
  
  
  Как удалить модуль?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.npmjs.com/cli/v10/commands/npm-uninstall"&gt;https://docs.npmjs.com/cli/v10/commands/npm-uninstall&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;npm uninstall @sveltejs/adapter-auto&lt;/code&gt; — удалит в каких бы &lt;code&gt;*Dependencies&lt;/code&gt; они не находились.&lt;/p&gt;

&lt;p&gt;Раньше нужно было дописывать &lt;code&gt;--save-dev&lt;/code&gt; и т.д., иначе удалится из &lt;code&gt;node_modules/&lt;/code&gt;, но не из &lt;code&gt;package.json&lt;/code&gt; и т.д.&lt;br&gt;
Сейчас этого нет. Только если прописать в &lt;code&gt;.npmrc&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;save=false&lt;/code&gt;, тогда нужно будет &lt;code&gt;--save&lt;/code&gt;.&lt;br&gt;
Но не вижу во всём этом смысла для общих случаев.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Можно удалить строку &lt;code&gt;"@sveltejs/adapter-auto": "^2.0.0",&lt;/code&gt; руками.&lt;/p&gt;

&lt;p&gt;При этом удалить &lt;code&gt;node_modules/&lt;/code&gt; и &lt;code&gt;package-lock.json&lt;/code&gt;.&lt;br&gt;
И сделать &lt;code&gt;npm i&lt;/code&gt; всего проекта заново.&lt;br&gt;
Но, так делать не стоит, когда всё уже в бою.&lt;br&gt;
Это может навредить и серверной сборке, и коллегам, но об этом позже.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Как не захламить prod-&lt;code&gt;dependencies&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Понятно, что в процессе разработки мы пробуем много разных модулей, которые чаще всего не пойдут на прод.&lt;br&gt;
И, не хотелось бы, чтобы всё ложилось в prod-&lt;code&gt;dependencies&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Тут выясняется, что возможен ещё какой-то &lt;code&gt;peerDependencies&lt;/code&gt;,&lt;br&gt;
где вообще — у каждого разработчика появляется свой личный блок с модулями:&lt;br&gt;
&lt;code&gt;npm i node_module --save-peer&lt;/code&gt; (&lt;code&gt;--save-peer&lt;/code&gt; не задокументирован, но работает. &lt;a href="https://stackoverflow.com/a/74549787/4117781"&gt;https://stackoverflow.com/a/74549787/4117781&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Пропустил я эту команду, и получил что-то новое — звёздочку! в &lt;code&gt;devDependencies&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"devDependencies": {
    "@sveltejs/adapter-auto": "*",
},
"peerDependencies": {
    "@sveltejs/adapter-auto": "2.1.1"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Испугался, и решил не использовать.&lt;br&gt;
Давайте лучше дружно хламить &lt;code&gt;devDependencies&lt;/code&gt;, но уж лучше без этого.&lt;br&gt;
Там ещё как-то должен был прописаться мой личный скоуп, на основе имени компа, но и этого автоматически не произошло.&lt;br&gt;
Валим из этой идеи короче :D&lt;br&gt;
Как минимум в этой статье.&lt;/p&gt;

&lt;p&gt;Не будем тянуть.&lt;br&gt;
Чтобы все модули по-умолчанию сваливались в &lt;code&gt;devDependencies&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;.npmrc&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;save-dev=true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Теперь, чтобы вогнать что-то в prod-&lt;code&gt;dependencies&lt;/code&gt; нужно будет &lt;code&gt;npm i module-name --save-prod&lt;/code&gt;.&lt;br&gt;
Такое делается не каждый день. Но — это ответственно.&lt;br&gt;
Потому, вероятно — это должен делать кто-то один из команды.&lt;/p&gt;

&lt;h2&gt;
  
  
  Зачем нужен &lt;code&gt;package-lock.json&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;У модулей, которые у нас в зависимостях, — есть свои зависимости.&lt;br&gt;
Каждая мажорная версия (&lt;code&gt;1.0.0&lt;/code&gt; —&amp;gt; &lt;code&gt;2.0.0&lt;/code&gt;) по конвенции допускает нарушение обратной совместимости.&lt;br&gt;
&lt;a href="https://docs.npmjs.com/about-semantic-versioning"&gt;https://docs.npmjs.com/about-semantic-versioning&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Зафиксируем:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;^1.0.0&lt;/code&gt; — тут разработчик модуля говорит, что версия зависимости сойдёт вплоть до &lt;code&gt;2.0.0&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;~1.0.0&lt;/code&gt; — тут разработчик модуля говорит, что версия зависимости сойдёт вплоть до &lt;code&gt;1.1.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;И — наши зависимости, зависимости модулей — могут между собой пересекаться.&lt;br&gt;
А сама конечная зависимость — может быть только одна.&lt;br&gt;
И, делая &lt;code&gt;npm i&lt;/code&gt; — каждый новый раз — нода может выкачивать из своих репозиториев чутка разные набор зависимостей, более оптимальные на текущий момент, удовлетворяя при этом всем настройкам выше — и в наших зависимостях, и в зависимостях зависимостей.&lt;br&gt;
Поэтому, несмотря на то, что &lt;code&gt;package-lock.json&lt;/code&gt; такой страшный — к сожалению, его лучше всё же класть в git.&lt;br&gt;
Чтобы не попасть в ситуацию, когда набор зависимостей на локале и на проде разный, а ты не можешь понять в чём ошибка.&lt;br&gt;
А ошибка может быть в любой даже минорной версии с баг-фиксом в любой из зависимостей. &lt;br&gt;
Хотя, это и бывает редко. Но бьёт больно. &lt;/p&gt;

&lt;p&gt;Чтобы &lt;code&gt;package-lock.json&lt;/code&gt; так не раздражал в git-e, парни предлагают:&lt;br&gt;
&lt;code&gt;.gitattributes&lt;/code&gt; —&amp;gt; &lt;code&gt;package-lock.json binary&lt;/code&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/a/50982431/4117781"&gt;https://stackoverflow.com/a/50982431/4117781&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Итого в &lt;code&gt;.npmrc&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.npmjs.com/cli/v10/configuring-npm/npmrc"&gt;https://docs.npmjs.com/cli/v10/configuring-npm/npmrc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;engine-strict=true  &amp;lt;— добрая рекомендация от Svelte&lt;br&gt;
save-exact=true&lt;br&gt;
save-dev=true&lt;/p&gt;

&lt;h2&gt;
  
  
  Что ещё интересного в &lt;code&gt;package.json&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;"private": true,&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Consider also setting "private": true to prevent accidental publication.&lt;br&gt;
&lt;a href="https://docs.npmjs.com/cli/v10/configuring-npm/package-json"&gt;https://docs.npmjs.com/cli/v10/configuring-npm/package-json&lt;/a&gt;&lt;br&gt;
Не знаю как это возможно, но, если «accidental», то убирать не будем.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. &lt;code&gt;"type": module,&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Это то, что позволяет нам делать модные &lt;code&gt;import a from '/b.js&lt;/code&gt;, вместо старых &lt;code&gt;a = require('b')&lt;/code&gt; и т.д.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Авторская рекомендация&lt;/strong&gt;&lt;br&gt;
Т.к. у нас кроме ноды есть строгое API со всякими проверками на всякие хосты, порты и заголовки,&lt;br&gt;
стоит гарантировать на каком хосте/порте будет открываться dev-версия.&lt;br&gt;
Заменить:&lt;br&gt;
&lt;code&gt;"dev": "vite dev",&lt;/code&gt;&lt;br&gt;
На:&lt;br&gt;
&lt;code&gt;"dev": "vite dev --host 127.0.0.1 --port 3000",&lt;/code&gt;&lt;br&gt;
А ещё добавить:&lt;br&gt;
&lt;code&gt;"host": "vite dev --host --port 3000",&lt;/code&gt;&lt;br&gt;
чтобы просто &lt;code&gt;npm run host&lt;/code&gt;, и проект можно посмотреть хоть на телефоне (если подключен к тому же wi-fi)&lt;/p&gt;

&lt;h2&gt;
  
  
  Во имя науки
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Можно руками закинуть модуль и в «prod» и в «dev». И даже ничего не сломается, но — не знаю зачем.
При попытке обновить/форсировать установку ещё раз — одна из записей сотрётся, в зависимости от куда &lt;code&gt;--save-x&lt;/code&gt; и т.д.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;optionalDependencies&lt;/code&gt; — когда допускаем, что модуль может не установиться, а он нам и не очень-то и нужен.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bundleDependencies&lt;/code&gt; — когда пилим свой модуль.&lt;/li&gt;
&lt;li&gt;Постоянно встречаются упоминания &lt;code&gt;npm-shrinkwrap.json&lt;/code&gt; —
Это «freeze» &lt;code&gt;package-lock.json&lt;/code&gt; для тех случаев когда это внезапно нужно:

&lt;ul&gt;
&lt;li&gt;Ноддерживает старые версии ноды (когда &lt;code&gt;package-lock.json&lt;/code&gt; только с v5),&lt;/li&gt;
&lt;li&gt;Необходим для публикации в качестве npm-модуля,&lt;/li&gt;
&lt;li&gt;А также, если встряли с версиями зависимостей. Тут &lt;code&gt;npm-shrinkwrap.json&lt;/code&gt; позволит управлять версиями вручную (&lt;a href="https://nodejs.org/en/blog/npm/managing-node-js-dependencies-with-shrinkwrap/"&gt;https://nodejs.org/en/blog/npm/managing-node-js-dependencies-with-shrinkwrap/&lt;/a&gt;).
В общем, не думая об этом — мы ничего не упускаем. Просто будем знать на всякий случай. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Как делать &lt;code&gt;install&lt;/code&gt; на проде?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Принято делать вот так:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm ci --[ТОЛЬКО PROD-DEPENDENCIES]&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;[ТОЛЬКО PROD-DEPENDENCIES]&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Можно встретить много рекомендаций, обещающих один и тот же результат:&lt;br&gt;
&lt;code&gt;--omit=dev&lt;/code&gt;, &lt;code&gt;--include=prod&lt;/code&gt;, &lt;code&gt;--only=prod&lt;/code&gt;, &lt;code&gt;--production&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;По всей видимости это из-за долгой эволюции ноды.&lt;br&gt;
Для последней 10-й версии в документации есть только &lt;code&gt;--include=prod&lt;/code&gt; (&lt;a href="https://docs.npmjs.com/cli/v10/commands/npm-ci"&gt;https://docs.npmjs.com/cli/v10/commands/npm-ci&lt;/a&gt;).&lt;br&gt;
Но, так — у меня устанавливаются всё — и «prod» и «dev».&lt;br&gt;
В итоге, делаю так:&lt;br&gt;
&lt;code&gt;npm ci --omit=dev&lt;/code&gt;&lt;br&gt;
Множественное «опущение» делается так:&lt;br&gt;
&lt;code&gt;npm ci --omit=dev --omit=peer&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Что за &lt;code&gt;ci&lt;/code&gt;?
&lt;a href="https://docs.npmjs.com/cli/v10/commands/npm-ci"&gt;https://docs.npmjs.com/cli/v10/commands/npm-ci&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Собственно, это то, что выкачивает &lt;code&gt;node_modules/&lt;/code&gt; на основе &lt;code&gt;package-lock.json&lt;/code&gt;, в обход &lt;code&gt;package.json&lt;/code&gt;, гарантируя то, что на проде будет так, как было на локале.&lt;/p&gt;

&lt;h2&gt;
  
  
  Иии, внииимаааниииеее...
&lt;/h2&gt;

&lt;p&gt;Спасибо, за внимание.&lt;/p&gt;

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