<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>TVLK5 Blog</title>
        <link>https://5.tvlk.dev/blog</link>
        <description>TVLK5 Blog</description>
        <lastBuildDate>Mon, 16 Mar 2020 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Dynamic route is now available]]></title>
            <link>https://5.tvlk.dev/blog/2020/03/16/dynamic-route</link>
            <guid>https://5.tvlk.dev/blog/2020/03/16/dynamic-route</guid>
            <pubDate>Mon, 16 Mar 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[When we first developed TVLK5, we include an express server to handle both route prefix (e.g: id-id) extraction from the URL and also to handle dynamic route requirement from product teams. The reason we use express for dynamic route was because we can't support next.js dynamic route feature since Next 9 originally launched.]]></description>
            <content:encoded><![CDATA[<p>When we first developed TVLK5, we include an express server to handle both route prefix (e.g: id-id) extraction from the URL and also to handle dynamic route requirement from product teams. The reason we use express for dynamic route was because we can't support <a href="https://nextjs.org/blog/next-9#dynamic-route-segments" target="_blank" rel="noopener noreferrer" class="">next.js dynamic route</a> feature since Next 9 originally launched.</p>
<p>When next.js is updated in 9.2.1, we finally able to integrate dynamic route into our framework.</p>
<p>If you're not interested in the detail you can skip to <a href="https://5.tvlk.dev/blog/2020/03/16/dynamic-route#migration-guide" class="">migration guide</a></p>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="brief-history">Brief History<a href="https://5.tvlk.dev/blog/2020/03/16/dynamic-route#brief-history" class="hash-link" aria-label="Direct link to Brief History" title="Direct link to Brief History" translate="no">​</a></h2>
<p>When we start working on the framework last year, we have next.js 9 as the base to build upon. The problem was our URLs for customer facing site have this locale prefix to determine which country and language that the user is in. We added custom middleware in the express server to remove the route prefix by matching it with the regex and forward the prefix (if any) via headers. This headers then get picked up by our next.js application. From there, it knows the current route prefix and can validate entirely inside <code>getInitialProps</code>.</p>
<p>Why express middleware? Because we have requirement where user can create dynamic route such as <code>/activities/:country/detail/:nameId</code> without having to bother with route prefix when matching the url so our middleware get applied to all URLs, and the next handler can simply match the URL without prefix.</p>
<p>We didn't use next dynamic route from the start because we want to have first-party support for client-side navigation. In practice, using dynamic route is not possible because next.js was expecting consistent <code>href</code> and <code>as</code> which is impossible as our <code>href</code> which maps to file path doesn't have route prefix while <code>as</code> that displayed in the address bar has a route prefix. It doesn't scale to create route prefix directory for all products. Imagine if everytime you create a page you'll need to create N files, each in different route prefix directory. It's a nightmare.</p>
<p>Shortly after, <a href="https://github.com/zeit/next.js/issues/9081" target="_blank" rel="noopener noreferrer" class="">Custom Route RFC</a> is opened and it seems like we can finally use this to replace our route prefix logic in express. Only after <a href="https://github.com/zeit/next.js/pull/9837" target="_blank" rel="noopener noreferrer" class="">this PR landed</a> that allows mismatching <code>href</code> and <code>as</code> we can finally integrate seamlessly with next.js dynamic routes.</p>
<p>Going forward, this is the recommended way to create dynamic route.</p>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="migration-guide">Migration Guide<a href="https://5.tvlk.dev/blog/2020/03/16/dynamic-route#migration-guide" class="hash-link" aria-label="Direct link to Migration Guide" title="Direct link to Migration Guide" translate="no">​</a></h2>
<p>If you have dynamic route in express, you've added both express middleware and 1 page handler prefixed by <code>_</code> in its filename. To migrate to next dynamic route, you'll need to migrate all your dynamic routes in one commit because it's not currently possible to handle both at the same time.</p>
<p>First, you'll need to remove <code>legacyRoutePrefixMiddleware</code> in your express server. This middleware is used to make sure that you can still add dynamic route in your express server.</p>
<p>Next, rename all your dynamic route file (prefixed with <code>_</code>) into next.js dynamic route file format. You can use this guide when renaming your route file:</p>
<ul>
<li class="">Express uses <code>:param</code> while next.js uses <code>[param]</code>. For example if you have <code>/activities/:country/detail/:nameId</code> you can rename your route file to <code>activities/[country]/detail/[nameId].tsx</code></li>
<li class="">Express uses <code>*</code> for wildcard match, while next uses <code>[...param]</code>. For example if you have <code>/explore/*</code> you can rename your route file to <code>explore/[...path].tsx</code></li>
</ul>
<p>Generally you can use any string to name your params, except 2 reserved words: <code>routePrefix</code> and <code>actualPath</code>. This is because we use this in our next rewrites to handle route prefix extraction.</p>
<p>If you've renamed all your dynamic route files, the next step is removing all your dynamic route definition in your server logic. And you're done!</p>
<p>Make sure you do these before May 1st because we'll start throwing error when you use custom express server that relies on route prefix removal logic. In the meantime, you'll get warning log when you still use express dynamic route method.</p>]]></content:encoded>
            <category>tvlk5</category>
            <category>intro</category>
        </item>
        <item>
            <title><![CDATA[TVLK5: The Late Intro]]></title>
            <link>https://5.tvlk.dev/blog/2019/08/15/hello-world</link>
            <guid>https://5.tvlk.dev/blog/2019/08/15/hello-world</guid>
            <pubDate>Thu, 15 Aug 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[By now you have to hear about this project called TVLK5. This post is an attempt to explain briefly what it is, how does it differ from how we used to develop products, what's changed since initial introduction and what's next.]]></description>
            <content:encoded><![CDATA[<p>By now you have to hear about this project called TVLK5. This post is an attempt to explain briefly what it is, how does it differ from how we used to develop products, what's changed since initial introduction and what's next.</p>
<p><img decoding="async" loading="lazy" src="https://cdn.dribbble.com/users/2873044/screenshots/9105402/media/9d4a119a39ca29a94650a06c49fafe7f.png" alt="Hand five: https://dribbble.com/shots/9105402-5" class="img_JDKa"></p>
<p>TVLK5 is an umbrella project to improve web development in Traveloka customer facing site, specifically how we author our code. It's technically our 2nd big change (but who's counting right), with the first one being Blocks and TvPage.</p>
<p>It's easy to call this a framework but we don't actually hide any backing implementation this time. It consists of express+nextjs boilerplate and few modules that you can integrate with. If you need to modify server middleware, you still working with an express app. The same can be said with nextjs, you follow their convention, with the entry inside pages directory. Want to do something fancy with nextjs? Just head to their documentation and it should work the same.</p>
<p>This is the main difference with our legacy system where you're kinda sucked in to how the framework was built, with routes being defined in specific file not even using express convention, middleware replaced with Filters and so on.</p>
<p>To understand how much is changed compared to our previous framework you can read some of these comparison below</p>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="hello-world">Hello World<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#hello-world" class="hash-link" aria-label="Direct link to Hello World" title="Direct link to Hello World" translate="no">​</a></h2>
<p>In TVLK5, to create new page you only need to touch single file (<code>pages/route.tsx</code> following next.js convention), compared to 5+ files you need to modify in previous framework (up to 2 routes, server module, client module, component, and webpack entry point).</p>
<p>If you need access to some properties, you might also need to configure your redux store. Ouch</p>
<p>Bonus point: you're not blocked by web-infra anymore for code review.</p>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="build-speed">Build speed<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#build-speed" class="hash-link" aria-label="Direct link to Build speed" title="Direct link to Build speed" translate="no">​</a></h2>
<p>In CI, entire TVLK5 workflow (JS build, docker+push, and performance tests) is faster than JS build of our monolith app. With faster feedback loop means you wait less time for your PR to be merged just because there's minor adjustment that you have to make.</p>
<p>Locally, you get the benefit of HMR where you can see your change in an instant. In our testing, adding log statements to the code will take &gt; 20 seconds in previous framework, while the new one only took ~2 seconds. That's 10x improvement for a single feedback loop.</p>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="content-resource--friends">Content Resource &amp; friends<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#content-resource--friends" class="hash-link" aria-label="Direct link to Content Resource &amp; friends" title="Direct link to Content Resource &amp; friends" translate="no">​</a></h2>
<p>In previous framework, fetching translation and any resource data are tied strongly to <code>react-diode</code> implementation which makes it difficult to optimize because CR/IR/IS have unique needs. In TVLK5 the syntax is simpler and still familiar, yet it have benefits like:</p>
<ul>
<li class=""><strong>Code split friendly</strong>. We leverage <code>React.Suspense</code> to make sure that you can place any resource query anywhere in the tree and it will be fetched only if your component renders it. You don't need to add <code>children</code> manually, it will automatically inferred based on request.</li>
</ul>
<div class="language-jsx codeBlockContainer_w3pX theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_lFxY"><pre tabindex="0" class="prism-code language-jsx codeBlock_sHpG thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_JLjW"><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token comment" style="color:hsl(220, 10%, 40%)">// Before:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Diode</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">createContainer</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Component</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">children</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Child</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">queries</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Diode</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">createQuery</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">ContentResourceQuery</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">GeneralLayout</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">logIn</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token keyword null nil" style="color:hsl(286, 60%, 67%)">null</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">// After:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token function" style="color:hsl(207, 82%, 66%)">useContentResource</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">GeneralLayout</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">logIn</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">''</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>Dead fields elimination</strong>. When you fetch image resource / image sliders, there's a lot of fields returned by backend API where most of them aren't even used. In TVLK5, those fields will be automatically removed if you don't use it, similar to how GraphQL works.</li>
</ul>
<div class="language-jsx codeBlockContainer_w3pX theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_lFxY"><pre tabindex="0" class="prism-code language-jsx codeBlock_sHpG thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_JLjW"><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token comment" style="color:hsl(220, 10%, 40%)">// Before:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Diode</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">createContainer</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Component</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">children</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Child</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">queries</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Diode</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">createQuery</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">ImageSliderQuery</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token comment" style="color:hsl(220, 10%, 40%)">// All fields will be hydrated in JSON even if it's not used</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">PaymentPartnersDark</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">// After:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token function" style="color:hsl(207, 82%, 66%)">useImageSlider</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">PaymentPartnersDark</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token comment" style="color:hsl(220, 10%, 40%)">// only link will be hydrated</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">link</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">''</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="mobile-redirection">Mobile redirection<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#mobile-redirection" class="hash-link" aria-label="Direct link to Mobile redirection" title="Direct link to Mobile redirection" translate="no">​</a></h2>
<p>This is common usage yet previously there's a few boilerplate when adding this functionality. In TVLK5, this can be as simple as single line change</p>
<div class="language-js codeBlockContainer_w3pX theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_lFxY"><pre tabindex="0" class="prism-code language-js codeBlock_sHpG thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_JLjW"><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token comment" style="color:hsl(220, 10%, 40%)">// Before:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:hsl(286, 60%, 67%)">function</span><span class="token plain"> </span><span class="token function" style="color:hsl(207, 82%, 66%)">pageRedirect</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token parameter">req</span><span class="token parameter punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token parameter"> res</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">const</span><span class="token plain"> url </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> req</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token property-access">router</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">url</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:hsl(95, 38%, 62%)">'PAGE_ROUTE_KEY'</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token keyword control-flow" style="color:hsl(286, 60%, 67%)">return</span><span class="token plain"> res</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">redirect</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">// After:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Page</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token property-access">mobileRedirection</span><span class="token plain"> </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(29, 54%, 61%)">true</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<p>There's an <a class="" href="https://5.tvlk.dev/docs/guides/page-behaviors/mobile-redirection#advanced-redirection">advanced redirection logic</a> that you can do, but most of the time you don't need that anyway. Why bother writing to much code?</p>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="confusing-lifecycle">Confusing Lifecycle<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#confusing-lifecycle" class="hash-link" aria-label="Direct link to Confusing Lifecycle" title="Direct link to Confusing Lifecycle" translate="no">​</a></h2>
<p>Previously we have <code>requestReceived</code>, <code>beforeFetch</code> and <code>afterFetch</code>. There's no clear way regarding what should be done inside those lifecycle, you only know what happen.</p>
<p>In TVLK5, by leveraging next.js we have <code>getInitialProps</code> that you can do to parse request data and fetch from backend API, or <code>routeProtection</code> that you can use to block access to specific route.</p>
<div class="language-jsx codeBlockContainer_w3pX theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_lFxY"><pre tabindex="0" class="prism-code language-jsx codeBlock_sHpG thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_JLjW"><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token comment" style="color:hsl(220, 10%, 40%)">// Before</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:hsl(286, 60%, 67%)">class</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">Page</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">extends</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">TvPage</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function" style="color:hsl(207, 82%, 66%)">requestReceived</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token parameter">req</span><span class="token parameter punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token parameter"> res</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token comment" style="color:hsl(220, 10%, 40%)">// wait is there req.user?</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword control-flow" style="color:hsl(286, 60%, 67%)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token property-access">user</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      res</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">status</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token number" style="color:hsl(29, 54%, 61%)">403</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token keyword control-flow" style="color:hsl(286, 60%, 67%)">return</span><span class="token plain"> </span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">ResponseHandler</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">endPageLifecycle</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function" style="color:hsl(207, 82%, 66%)">beforeFetch</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token parameter">req</span><span class="token parameter punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token parameter"> res</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">super</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">beforeFetch</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    req</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token property-access">props</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token property-access">key</span><span class="token plain"> </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">'value'</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token function" style="color:hsl(207, 82%, 66%)">afterFetch</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token parameter">req</span><span class="token parameter punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token parameter"> res</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token comment" style="color:hsl(220, 10%, 40%)">// ????</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">super</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">afterFetch</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">// After</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Page</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method-variable function-variable method function property-access" style="color:hsl(207, 82%, 66%)">getInitialProps</span><span class="token plain"> </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">async</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token parameter">ctx</span><span class="token parameter punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token parameter"> appCtx</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:hsl(207, 82%, 66%)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token keyword control-flow" style="color:hsl(286, 60%, 67%)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">key</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">'value'</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Page</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method-variable function-variable method function property-access" style="color:hsl(207, 82%, 66%)">routeProtection</span><span class="token plain"> </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> </span><span class="token parameter">ctx</span><span class="token plain"> </span><span class="token arrow operator" style="color:hsl(207, 82%, 66%)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token keyword control-flow" style="color:hsl(286, 60%, 67%)">if</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">ctx</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token property-access">user</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token property-access">loggedIn</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword control-flow" style="color:hsl(286, 60%, 67%)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">status</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(29, 54%, 61%)">200</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token keyword control-flow" style="color:hsl(286, 60%, 67%)">return</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"> </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">status</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(29, 54%, 61%)">403</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="parallel-server-side-api-call">Parallel server-side API call<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#parallel-server-side-api-call" class="hash-link" aria-label="Direct link to Parallel server-side API call" title="Direct link to Parallel server-side API call" translate="no">​</a></h2>
<p>Using <code>Filter</code> in previous framework means each filter is executed serially, this means that any API call happen inside different filter will be called sequentially.</p>
<p>In TVLK5, we optimize to fetch as much data as possible to reduce server latency. We even provide you with <a class="" href="https://5.tvlk.dev/docs/performance/perf-ttfb">Server Timing</a> to see how each server-side call performs.</p>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="production-debugging">Production debugging<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#production-debugging" class="hash-link" aria-label="Direct link to Production debugging" title="Direct link to Production debugging" translate="no">​</a></h2>
<p>Due to modular approach, it's now feasible to test production build locally without breaking your laptop. You can build and run production build using either staging or production API.</p>
<div class="language-bash codeBlockContainer_w3pX theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_lFxY"><pre tabindex="0" class="prism-code language-bash codeBlock_sHpG thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_JLjW"><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token comment" style="color:hsl(220, 10%, 40%)"># Before:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(29, 54%, 61%)">cd</span><span class="token plain"> packages/nodejs-web</span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token assign-left variable" style="color:hsl(207, 82%, 66%)">NODE_ENV</span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain">production </span><span class="token function" style="color:hsl(207, 82%, 66%)">pnpm</span><span class="token plain"> build</span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">## if it doesn't crash, then</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token assign-left variable" style="color:hsl(207, 82%, 66%)">NODE_ENV</span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain">production </span><span class="token function" style="color:hsl(207, 82%, 66%)">node</span><span class="token plain"> lib/index.js</span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)"># After:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token function" style="color:hsl(207, 82%, 66%)">pnpm</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(207, 82%, 66%)">--filter</span><span class="token plain"> @traveloka/webxpe-desktop build</span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token function" style="color:hsl(207, 82%, 66%)">pnpm</span><span class="token plain"> start</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="client-side-routing">Client-side routing<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#client-side-routing" class="hash-link" aria-label="Direct link to Client-side routing" title="Direct link to Client-side routing" translate="no">​</a></h2>
<p>Previously, to use client-side routing, you have to change a lot of things, starting from changing your base page, your route registration, your component render method, and more. This is assuming you don't want to code split because it's a different case altogether (thanks to <code>Diode</code>). It's not a pleasant experience.</p>
<p>In TVLK5, client-side routing get first class support, which means it works by default without you having to reconfigure anything. In next.js every page is different bundle so it's code-split by default.</p>
<div class="language-jsx codeBlockContainer_w3pX theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_lFxY"><pre tabindex="0" class="prism-code language-jsx codeBlock_sHpG thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_JLjW"><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token comment" style="color:hsl(220, 10%, 40%)">// Before:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">// duplicate path declaration with registration?</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token tag punctuation" style="color:hsl(220, 14%, 71%)">&lt;</span><span class="token tag class-name" style="color:hsl(29, 54%, 61%)">Link</span><span class="token tag" style="color:hsl(355, 65%, 65%)"> </span><span class="token tag attr-name" style="color:hsl(29, 54%, 61%)">to</span><span class="token tag attr-value punctuation attr-equals" style="color:hsl(220, 14%, 71%)">=</span><span class="token tag attr-value punctuation" style="color:hsl(220, 14%, 71%)">"</span><span class="token tag attr-value" style="color:hsl(95, 38%, 62%)">/path/:key/another</span><span class="token tag attr-value punctuation" style="color:hsl(220, 14%, 71%)">"</span><span class="token tag" style="color:hsl(355, 65%, 65%)"> </span><span class="token tag punctuation" style="color:hsl(220, 14%, 71%)">/&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">// or "server-side" navigation</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token dom variable" style="color:hsl(207, 82%, 66%)">window</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">assign</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token comment" style="color:hsl(220, 10%, 40%)">// Don't forget to add this in RouteResourceGroups</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  router</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">url</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:hsl(95, 38%, 62%)">'SOME_KEY_THAT_YOU_NEED_TO_FIND_IN_REGISTRATION_FILE'</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">// and another ceremonies</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">// After:</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token tag punctuation" style="color:hsl(220, 14%, 71%)">&lt;</span><span class="token tag class-name" style="color:hsl(29, 54%, 61%)">Link</span><span class="token tag" style="color:hsl(355, 65%, 65%)"> </span><span class="token tag attr-name" style="color:hsl(29, 54%, 61%)">route</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:hsl(220, 14%, 71%)">=</span><span class="token tag script language-javascript punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token tag script language-javascript constant" style="color:hsl(29, 54%, 61%)">ROUTE_PATH</span><span class="token tag script language-javascript punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token tag" style="color:hsl(355, 65%, 65%)"> </span><span class="token tag attr-name" style="color:hsl(29, 54%, 61%)">params</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:hsl(220, 14%, 71%)">=</span><span class="token tag script language-javascript punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token tag script language-javascript punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token tag script language-javascript" style="color:hsl(355, 65%, 65%)"> </span><span class="token tag script language-javascript literal-property property" style="color:hsl(355, 65%, 65%)">key</span><span class="token tag script language-javascript operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token tag script language-javascript" style="color:hsl(355, 65%, 65%)"> </span><span class="token tag script language-javascript string" style="color:hsl(95, 38%, 62%)">'value'</span><span class="token tag script language-javascript" style="color:hsl(355, 65%, 65%)"> </span><span class="token tag script language-javascript punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token tag script language-javascript punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token tag" style="color:hsl(355, 65%, 65%)"> </span><span class="token tag punctuation" style="color:hsl(220, 14%, 71%)">/&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)">// or programmatic client-side navigation</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:hsl(286, 60%, 67%)">const</span><span class="token plain"> route </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(207, 82%, 66%)">useLocalizedRouter</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:hsl(286, 60%, 67%)">const</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token plain">href</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token keyword module" style="color:hsl(286, 60%, 67%)">as</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"> </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(207, 82%, 66%)">route</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token constant" style="color:hsl(29, 54%, 61%)">ROUTE_PATH</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">params</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token literal-property property" style="color:hsl(355, 65%, 65%)">key</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">'value'</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token maybe-class-name" style="color:hsl(29, 54%, 61%)">Router</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token method function property-access" style="color:hsl(207, 82%, 66%)">push</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">href</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token keyword module" style="color:hsl(286, 60%, 67%)">as</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><br></div></code></pre></div></div>
<p>Those are non-exhaustive list of what's new in TVLK5. If you're curious, read our <a class="" href="https://5.tvlk.dev/docs/getting-started/local-setup">getting started</a> docs.</p>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="migration-requirement">Migration Requirement<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#migration-requirement" class="hash-link" aria-label="Direct link to Migration Requirement" title="Direct link to Migration Requirement" translate="no">​</a></h2>
<p>If you want to migrate your services to use TVLK5 these are few things you should know:</p>
<ul>
<li class="">TVLK5 only officially supports <code>@traveloka/web-components</code> as component primitive. This is probably one of the major blocker / where you'll need to spend most effort in. We'd suggest you refactor your component to use <code>web-components</code> before performing any migration.</li>
<li class="">There's no more dependency to <code>nodejs-web</code>. Each services can only depend to <code>@traveloka/core</code>, <code>@traveloka/app-desktop</code>, <code>@traveloka/app-mobile</code>, and other micro packages (such as <code>@traveloka/user</code> or <code>@traveloka/merchandising</code>). You can extract your utility modules to your own package, and make <code>nodejs-web</code> depend to that package, but not the other way around</li>
<li class="">The new services will only handle language-country routing, e.g: <code>/id-id</code> prefix. This means your service have to be compliant with URL standardization effort. In the future <code>nodejs-web</code> will only be used as redirection for naked locale and legacy <code>/en</code> prefix.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_R0VY" id="updates">Updates<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#updates" class="hash-link" aria-label="Direct link to Updates" title="Direct link to Updates" translate="no">​</a></h3>
<p>At this time of writing there's 3 product in production using TVLK5: Experience, DLP, and Explore. Thanks to experience team for becoming pilot for this adoption 🎉!</p>
<p>Since XPE team released their servies to production, we have made some improvement to the framework:</p>
<ul>
<li class="">There's now 3 experimental features that you can try to improve your page performance: <a class="" href="https://5.tvlk.dev/docs/performance/perf-server#caching-server-rendered-response">SSR cache</a>, <a class="" href="https://5.tvlk.dev/docs/performance/perf-client#is-this-component-visible-on-initial-render">progressive hydration</a>, and <a class="" href="https://5.tvlk.dev/docs/performance/perf-client#does-this-component-need-to-be-hydrated">static subtree</a></li>
<li class="">We have completed migration of shared desktop and mobile components (header, footer, sidebar) available in <code>@traveloka/app-desktop</code> and <code>@traveloka/app-mobile</code>. If your page uses this component and you already use <code>web-components</code> for all your components, you'll have easier time migrating your services.</li>
</ul>
<p>We also received contribution from various engineers in feature parity, bug fixes and other enhancements:</p>
<ul>
<li class="">Thanks to <a href="https://github.com/masbagal" target="_blank" rel="noopener noreferrer" class="">Agal</a>, we now have better OTP integration and external login capability</li>
<li class="">Thanks to <a href="https://github.com/iamn00b" target="_blank" rel="noopener noreferrer" class="">Yusei</a> we now have frictionless setup using Yeoman generator.</li>
<li class="">Thanks to <a href="https://github.com/ferzos" target="_blank" rel="noopener noreferrer" class="">Ferdinand</a>, <a href="https://github.com/raibima" target="_blank" rel="noopener noreferrer" class="">Raibima</a>, <a href="https://github.com/billydarmawan" target="_blank" rel="noopener noreferrer" class="">Billy</a>, <a href="https://github.com/pawlarius" target="_blank" rel="noopener noreferrer" class="">Paula</a> for bug fixes and DX improvements.</li>
<li class="">Thanks to <a href="https://github.com/ghautsulazham" target="_blank" rel="noopener noreferrer" class="">Dzulham</a> and <a href="https://github.com/FerdinandAnt" target="_blank" rel="noopener noreferrer" class="">Ferdinand</a> we have external tracking manager setup with automatic segment pageview tracking.</li>
<li class="">Thanks to <a href="https://github.com/drgx" target="_blank" rel="noopener noreferrer" class="">Ryan</a>, we have easy performance tracking with mock recorder. This means adding performance test is as easy as visiting your page in dev and modify 1 JSON file.</li>
<li class="">Thanks to <a href="https://github.com/abihf" target="_blank" rel="noopener noreferrer" class="">Abi</a> and <a href="https://github.com/asendia" target="_blank" rel="noopener noreferrer" class="">Asendia</a> we have migrated to Jenkins with the ability to do partial build. This means in average new TVLK5 services can finish building in under 10 minutes, including performance tests (the production build itself should finish in about a minute).</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_R0VY" id="whats-next">What’s Next?<a href="https://5.tvlk.dev/blog/2019/08/15/hello-world#whats-next" class="hash-link" aria-label="Direct link to What’s Next?" title="Direct link to What’s Next?" translate="no">​</a></h2>
<p>While most of the groundwork has already finished, there's more that we haven't got to it yet:</p>
<ul>
<li class="">Adoption of nextjs advanced features (dynamic route, module/nomodule, rewrites). Using dynamic route allow us to create route with params without touching express code, while module/nomodule will improve our page performance in newer browsers due to different transpilation method</li>
<li class="">Staging &amp; Release DX improvement. This is only slightly related to TVLK5 itself but it's an issue. Currently there's so many thing to touch when you want to create new services and release it to production. We're planning to simplify this process so you can migrate your screen 1 by 1.</li>
<li class="">Dev DX improvement (especially logging and hanging process). We noticed there's a strange bug where some process are not closed even after you stop the main proxy. This can cause issues in performarnce and battery life. If possible, we also like to remove <code>nohoist</code> limitation when you setup your packages. This could hopefully improve installation time</li>
<li class="">Docs completion, most of the docs are already completed, but the advanced topics sections (especially Architecture) are still missing. We plan to finish the remaining docs in H2.</li>
</ul>
<p>If you have any suggestion on what to improve in the framework, don't hesitate to contact us in frontend-club channel.</p>]]></content:encoded>
            <category>tvlk5</category>
            <category>intro</category>
        </item>
    </channel>
</rss>