<?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: Bojan Todorović</title>
    <description>The latest articles on DEV Community by Bojan Todorović (@bojant987).</description>
    <link>https://dev.to/bojant987</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%2F777081%2F76011b8e-0cf1-4d5c-a6e7-026e6672700e.jpeg</url>
      <title>DEV Community: Bojan Todorović</title>
      <link>https://dev.to/bojant987</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bojant987"/>
    <language>en</language>
    <item>
      <title>A day in life of a senior (UI) engineer</title>
      <dc:creator>Bojan Todorović</dc:creator>
      <pubDate>Sun, 19 Dec 2021 21:30:05 +0000</pubDate>
      <link>https://dev.to/bojant987/a-day-in-life-of-a-senior-ui-engineer-5bja</link>
      <guid>https://dev.to/bojant987/a-day-in-life-of-a-senior-ui-engineer-5bja</guid>
      <description>&lt;p&gt;I am a Lead Frontend Engineer in a team of 13 people at &lt;a href="https://en.wikipedia.org/wiki/Redbox" rel="noopener noreferrer"&gt;Redbox&lt;/a&gt;.&lt;br&gt;
Redbox is a streaming service, we offer a wide variety of movies and TV shows on demand. Those of you in US might recognize the name from the red kiosks all around for renting DVDs and Blurays.&lt;/p&gt;

&lt;p&gt;Being a streaming service we have apps covering many TV platforms, Samsung, Vizio, LG, VewD, PS4/5, Xbox, Roku, and more to come.&lt;br&gt;
Our main projects are native Roku app, and web app that supports every other platform besides Roku.&lt;/p&gt;

&lt;p&gt;But business occupies a whole spectrum, from customer facing, to internal tooling. My team has about 10 projects we maintain.&lt;/p&gt;

&lt;p&gt;I often encounter beginners that think seniors write thousands of lines of code daily, deploy it to millions of users, and somehow it is all stable all the time by itself.&lt;br&gt;
I even forget I was once a beginner that thought something similar.&lt;br&gt;
But, those of us in the "trenches" know better.&lt;/p&gt;

&lt;p&gt;So, how do engineers manage to create stable apps people use every day?&lt;br&gt;
How does a day of a senior frontend engineer look like?&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: check email
&lt;/h2&gt;

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

&lt;p&gt;So, my morning starts simple enough.&lt;br&gt;
I quickly check my email. It takes 5-10 minutes, I got stuff organized in folders so I can make easier and quicker sense of stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: check metrics
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewqvs11j0d44mrl6qwqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewqvs11j0d44mrl6qwqw.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhsnye8bytq84nn0xdh1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhsnye8bytq84nn0xdh1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I move onto taking a short look at Grafana charts for performance of our backend services that my (frontend) team maintains. These are small in terms of backend code, but important, as they deliver stuff like feature flags and various misc content from CMS(like Terms &amp;amp; Conditions texts).&lt;br&gt;
We do have alerts setup for critical scenarios, but that doesn't excuse not manually checking for trends.&lt;br&gt;
This is what some of these charts may look like, they're fed by &lt;a href="https://prometheus.io/" rel="noopener noreferrer"&gt;Prometheus&lt;/a&gt; into &lt;a href="https://grafana.com/" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt;.&lt;br&gt;
We got error percentage, Redis used memory, event loop lag, and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: check bug monitoring
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsoedvmg6bm13m137jnj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsoedvmg6bm13m137jnj.png" alt="Bugsnag dashboard"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe87bzrcvjmo3ksx95sqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe87bzrcvjmo3ksx95sqw.png" alt="Bugsnag dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, I move onto the bug monitoring.&lt;br&gt;
We use &lt;a href="https://www.bugsnag.com/" rel="noopener noreferrer"&gt;Bugsnag&lt;/a&gt;.&lt;br&gt;
Again, alerts for critical stuff are setup here too, but manual checks are desired.&lt;br&gt;
There's a timeline of bug trends and view of bug events themselves, with all the good stuff like stacktraces, breadcrumbs, custom event data an app might attach, etc.&lt;br&gt;
Unhandled errors are setup so they automatically open bugs in Jira, handled stuff usually not. But, just because an error is handled, does not mean it's okay for it to occur. It might, for example be a symptom of some issues at the backend, like on the data sync side.&lt;/p&gt;

&lt;p&gt;These 2 monitoring steps are not something that all team members are required to do every day, but we encourage everyone to be comfortable with them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: deployments
&lt;/h2&gt;

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

&lt;p&gt;Next, if there are any deployments to be done, I like to do it now.&lt;br&gt;
This is not something I alone do.&lt;br&gt;
We encourage everyone to be comfortable with the process of deploying to production. As in CI/CD, deployment is something to be seen as (daily) routine, not a big deal.&lt;br&gt;
After merge to master, &lt;a href="https://www.jenkins.io/" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt; builds our code, and when build is done &lt;a href="https://spinnaker.io/" rel="noopener noreferrer"&gt;Spinnaker&lt;/a&gt; automatically deploys it to staging.&lt;br&gt;
Test automation starts running right away on freshly built stage instance, and our manual QA folks are automatically alerted by a webhook in a chat about the new build in staging, so they can pick it up too.&lt;br&gt;
Once everything is greenlighted, production is just a click away in Spinnaker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: code reviews
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljb1lekw1lqfa1w22ilm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljb1lekw1lqfa1w22ilm.png" alt="Merge requests list"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After all these usually short endeavors, I move onto code reviews. Since we have many projects, that are in separate repos, we have a Gitlab CLI utility that lists open merge requests on all our projects.&lt;br&gt;
This is what that looks like, it's a simple script but quite helpful.&lt;br&gt;
We have a rule, code review takes priority if you're in between tasks, and having opened merge request more than a day old is considered a red alert for taking up code review.&lt;br&gt;
This is because we embrace the &lt;a href="https://trunkbaseddevelopment.com/" rel="noopener noreferrer"&gt;trunk based development&lt;/a&gt;, with short lived branches only.&lt;br&gt;
Merge request =&amp;gt; code review =&amp;gt; merge to master/main =&amp;gt; test =&amp;gt; deploy as soon as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: daily team meeting
&lt;/h2&gt;

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

&lt;p&gt;After this point, we usually have a short daily meeting.&lt;br&gt;
A short status update and getting rid of various misc doubts and blockers people might have.&lt;br&gt;
We encourage people to also do this by a chat at any time they have doubts about some approach and would like to get a consensus from team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: actual coding
&lt;/h2&gt;

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

&lt;p&gt;And finally, we got to the actual coding.&lt;br&gt;
I'm not going to get into the details of coding, but just an overview of the process.&lt;br&gt;
Every one of our projects has it's own &lt;a href="https://www.atlassian.com/software/jira" rel="noopener noreferrer"&gt;Jira&lt;/a&gt; board, but as a rule we don't venture there for picking up a task, as that would be too chaotic.&lt;br&gt;
We have a team Jira board, that pulls tickets from all Jira boards of projects our team maintains.&lt;br&gt;
A master board, if you will.&lt;br&gt;
As a developer, this is your taking off point.&lt;br&gt;
In this board, priority is by sorted top to bottom, so developer doesn't have to go "window shopping" for a ticket. First ticket in TO DO column is yours for the taking.&lt;br&gt;
We are doing &lt;a href="https://en.wikipedia.org/wiki/Kanban_(development)" rel="noopener noreferrer"&gt;Kanban&lt;/a&gt; with a backlog, also called &lt;a href="https://www.wrike.com/kanban-guide/faq/what-is-kanplan/" rel="noopener noreferrer"&gt;Kanplan&lt;/a&gt;. &lt;br&gt;
The spin is we embrace what is called &lt;a href="https://hilton.org.uk/blog/zero-bug-policy#:~:text=Fixing%20bugs%20before%20you%20write,bugs%20unfixed%20for%20'later'." rel="noopener noreferrer"&gt;zero bug policy&lt;/a&gt;. Meaning, bugs can't be in backlog, and they take priority over stories/features.&lt;br&gt;
This does not mean our UIs have literally 0 bugs at all times, or at any one time for that matter, only that bugs don't get to live happily ever after in the backlog. We either fix the bug ASAP, or declare it as not relevant and close it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: afternoon meetings
&lt;/h2&gt;

&lt;p&gt;In the afternoon, as a lead I usually attend some meetings. &lt;br&gt;
This is usually for various planning/grooming purposes with product people.&lt;br&gt;
We all know how fun this is, so we try to spare other team members from it as much as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9: misc
&lt;/h2&gt;

&lt;p&gt;Some other things that can pop up here and there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Triage&lt;/strong&gt;, which I sometimes do by myself, but also bring in other team members when needed. We have no strong rules here, we do it when and if it is needed when bringing tickets from backlog into TO DO world. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retrospective&lt;/strong&gt; once a month to review our team practices and processes, and try to improve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feature flags&lt;/strong&gt; are setup for most of major features, with optional A/B testing. As soon as work on a major feature is started, feature flag for it is set up. In this way, doing parts of a new feature and opening small merge requests is doable, because unless feature flag is turned on, partially done feature won't be visible to users. It goes hand in hand with trunk based development, since everything is on master/main and in production all the time, but we have control over what users see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 10: And that's pretty much it. Now you know (almost) everything
&lt;/h2&gt;

&lt;p&gt;Thank you for your attention and take this inspirational quote to go.&lt;br&gt;
”What one programmer can do in one month, two programmers can do in two months.”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frederick P. Brooks&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>ReacTV</title>
      <dc:creator>Bojan Todorović</dc:creator>
      <pubDate>Sun, 19 Dec 2021 12:02:58 +0000</pubDate>
      <link>https://dev.to/bojant987/reactv-52a4</link>
      <guid>https://dev.to/bojant987/reactv-52a4</guid>
      <description>&lt;p&gt;Vizio, LG, Samsung, PS4, PS5, Xbox, VewD.&lt;br&gt;
What do all these platforms have in common?&lt;br&gt;
Yup, that's right, React!&lt;br&gt;
All of these devices support web apps, and React is the web king.&lt;br&gt;
At &lt;a href="https://en.wikipedia.org/wiki/Redbox"&gt;Redbox&lt;/a&gt;, a streaming service you might not have heard of, we run React on all of these platforms, from a single codebase.&lt;/p&gt;

&lt;p&gt;Now you might think "oh, so it's just a regular web app, okay".&lt;br&gt;
And you would be correct, up to a point.&lt;br&gt;
But let's go beyond that point.&lt;/p&gt;
&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;p&gt;There are a couple of challenges when developing TV web app that you don't generally encounter doing "normal" web apps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Ancient browsers&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spatial navigation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;So many platforms&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some of these are TV specific, but some can be applied to improve any web app.&lt;br&gt;
So, don't worry if you're not starting a TV web app project tomorrow, might still find something for you below.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ancient ones
&lt;/h3&gt;

&lt;p&gt;Browsers on TVs can be old.&lt;br&gt;
Old like Chrome v38(latest is v94), Opera v36(latest is v80), old non-Chromium Edge, Safari 6, etc.&lt;br&gt;
And most of them are not vanilla browsers, but platforms built on top of these browsers.&lt;br&gt;
Meaning there's always some custom code in there too, potentially making compatibility even more painful.&lt;br&gt;
We come well prepared in the web world to deal with this, however. Most of the time &lt;code&gt;browserslist&lt;/code&gt; will take care of it.&lt;/p&gt;

&lt;p&gt;Still, two main issues can arise here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;CSS&lt;/strong&gt; - it can be a pain anywhere, but we all know old browsers are especially volatile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transpilation&lt;/strong&gt; - it is generally the practice to exclude &lt;code&gt;node_modules&lt;/code&gt; from transpilation, as it decreases build time significantly.
However, you may find for TVs that many modules over time drop support for browsers you simply have to continue supporting.
You can include the whole &lt;code&gt;node_modules&lt;/code&gt; in transpilation, but we've found including only a handful of modules with the issues works well.
Ie:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&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;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;or&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/wonka/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/vtt-to-json/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/serialize-error/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/joi-browser/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/whatwg-fetch/&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;Alternatively, there are tools like &lt;a href="https://www.npmjs.com/package/are-you-es5"&gt;are-you-es5&lt;/a&gt; that you can try out.&lt;/p&gt;
&lt;h3&gt;
  
  
  Spatial navigation
&lt;/h3&gt;

&lt;p&gt;Besides your regular mouse and keyboard, TVs work with remotes.&lt;br&gt;
There are modern "magic remotes" that function almost the same as the mouse.&lt;br&gt;
But the classic remote requires navigating by arrow keys around your UX, or as commonly referred to, "spatial navigation".&lt;/p&gt;

&lt;p&gt;There is nowadays this library for React &lt;a href="https://github.com/NoriginMedia/react-spatial-navigation"&gt;react-spatial-navigation&lt;/a&gt;&lt;br&gt;
However, one safe and secure way is to build your own React wrapper around the tried and tested Mozilla's open source &lt;a href="https://github.com/luke-chang/js-spatial-navigation"&gt;spatial navigation&lt;/a&gt;.&lt;br&gt;
And we have done just that.&lt;/p&gt;
&lt;h3&gt;
  
  
  So many platforms
&lt;/h3&gt;

&lt;p&gt;Supporting all the browsers on the web from a single codebase is a pain, but much less pain then doing it with all of TVs.&lt;br&gt;
For regular web apps, besides a &lt;code&gt;browserslist&lt;/code&gt;, you might need an &lt;code&gt;if&lt;/code&gt; to apply different styling or similar here and there, but that's about it.&lt;br&gt;
TVs, on the other hand, are platforms built on top of browsers, and this is where the difficulty lies.&lt;br&gt;
All of these platforms will have different ways to handle remote keys, TV specific events, to get device info, playback, etc.&lt;/p&gt;

&lt;p&gt;There are a lot of ways to elegantly handle this platform specificity in a codebase and make it less painful.&lt;br&gt;
Here's one:&lt;br&gt;
Let's say you want to exit the application when exit button is pressed on the remote.&lt;br&gt;
So you do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;exitApplication&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;../../utils/device/device&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// .... call exitApplication in some event handler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, the trick is, every platform has it's own way of handling application exiting.&lt;br&gt;
So, we make a device folder with the structure:&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="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;
    &lt;span class="o"&gt;|-&lt;/span&gt; &lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
    &lt;span class="o"&gt;|-&lt;/span&gt; &lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tizen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
    &lt;span class="o"&gt;|-&lt;/span&gt; &lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;xbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
    &lt;span class="o"&gt;|-&lt;/span&gt; &lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vizio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we make a little webpack magic.&lt;br&gt;
Note that we have separate build script for every platform, so application is aware where it's being run by build script passing &lt;code&gt;env.platform&lt;/code&gt; variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;platformizeExtensions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extensions&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="nx"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extension&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;platform&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;extension&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="nx"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in your &lt;code&gt;webpack.config.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;platformizeExtensions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;platform&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;.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.scss&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;For LG, this will make extensions look like this:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.lg.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.lg.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.lg.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.lg.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.mjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, doing &lt;code&gt;import { exitApplication } from '../../Utils/device/device';&lt;/code&gt; will import from device file for the platform, ie on LG it will import from &lt;code&gt;device.lg.js&lt;/code&gt;.&lt;br&gt;
Problem solved.&lt;br&gt;
Naturally, one caveat of this is that every &lt;code&gt;device.*.js&lt;/code&gt; will have to export methods with the same name, otherwise you might encounter an error trying to import something that doesn't exist on some platforms.&lt;br&gt;
Ie all of our device files have the same signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getDeviceId&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;const&lt;/span&gt; &lt;span class="nx"&gt;getOSVersion&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;const&lt;/span&gt; &lt;span class="nx"&gt;exitApplication&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;const&lt;/span&gt; &lt;span class="nx"&gt;isTTSEnabled&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;const&lt;/span&gt; &lt;span class="nx"&gt;isLowEndDevice&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we do the same with eg. &lt;code&gt;keyCodes&lt;/code&gt;, since most platforms have keys on the remote dispatch &lt;code&gt;onKeyDown&lt;/code&gt; event with their own custom set of &lt;code&gt;keyCodes&lt;/code&gt;.&lt;br&gt;
But, this little trick can have more use cases than just TV web app development.&lt;br&gt;
One advantage of this approach over classical &lt;code&gt;if&lt;/code&gt; or &lt;code&gt;switch&lt;/code&gt; is that code in modules for other platforms is never imported, and therefore shaken off by webpack at bundling time, reducing bundle size.&lt;/p&gt;
&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;You might have heard of "you need to watch for performance, mobile devices are low powered".&lt;br&gt;
That is certainly true, until you encounter a new beast, a TV device.&lt;br&gt;
Premium TV devices will probably be on par with mid range phones, which is great.&lt;br&gt;
But budget TVs are more on par with a calculator.&lt;br&gt;
I'm talking couple of hundred MHz processing power and 1GB or less RAM, shared with the operating system too.&lt;br&gt;
Even a powerful platform like PlayStation, only allocates a small amount of resources to a web app, so in practice is also very low powered.&lt;/p&gt;

&lt;p&gt;So, it's clear, you need to watch for performance, and not just like an afterthought.&lt;br&gt;
That, however, involves multiple layers, not just React.&lt;br&gt;
Let's go over some of the stuff you can do to preserve optimal experience on low end devices.&lt;/p&gt;
&lt;h4&gt;
  
  
  Measuring
&lt;/h4&gt;

&lt;p&gt;A good starting point is always to continually run your app through well established performance measuring tools.&lt;br&gt;
No single tool that I know of has everything regarding exposing performance flaws in your code, but a combination should do.&lt;br&gt;
These tools are great for pointing out weak spots in terms of performance, and even suggesting improvements.&lt;/p&gt;

&lt;p&gt;I'd mention:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://developers.google.com/web/tools/lighthouse"&gt;Lighthouse&lt;/a&gt;, &lt;a href="https://www.webpagetest.org/"&gt;Webpagetest&lt;/a&gt;, etc&lt;/strong&gt;
These ones do it from a simulated user perspective, what might be called "end to end", on a web app level.
This is what you always want to have. But, they don't precisely point out flaws in your React code, so there's still a gap for another tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React profiler&lt;/strong&gt;
Great for measuring and pointing out where you have performance bottlenecks in your React code.
An absolute must.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ideally, you'd want one of these tool in CI/CD pipeline.&lt;br&gt;
But, we found that manual checks will always be required.&lt;/p&gt;
&lt;h4&gt;
  
  
  Assets
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fonts&lt;/strong&gt; - trying not to load huge file sizes for fonts is always sensible. For optimization, try preloading fonts with &lt;code&gt;&amp;lt;link rel="preload" as="font"&amp;gt;&lt;/code&gt; and avoiding flash of invisible text while fonts are loading by using &lt;a href="https://developers.google.com/web/updates/2016/02/font-display"&gt;font-display API&lt;/a&gt;, ie &lt;code&gt;font-display: swap;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Images&lt;/strong&gt; - ideally use &lt;code&gt;webp&lt;/code&gt; format, and keep images as small as possible by loading in only what you need in terms of resolution. Ie, if user is on mobile, and image is displayed in ie 320x160, don't load huge image for desktop and resize it in-browser. This can be achieved by tools like &lt;a href="http://thumbor.org/"&gt;Thumbor&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compression&lt;/strong&gt; - gzip your data sent over network, that goes for API data and for JS/CSS files(which should be minimized too)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Preconnecting to relevant domains
&lt;/h4&gt;

&lt;p&gt;Any app nowadays is bound to fetch a lot of stuff from other domains.&lt;br&gt;
Things like data from your APIs, images from image server, etc.&lt;br&gt;
Preconnecting to these domains or doing DNS prefetch might improve load time somewhat.&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/dns-prefetch"&gt;Learn&lt;/a&gt; the differences between these two and have them in mind as tools at your disposal&lt;br&gt;
&lt;code&gt;&amp;lt;link rel="preconnect" href="https://example.com"&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&amp;lt;link rel="dns-prefetch" href="https://example.com"&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Prefetch/preload, async/defer
&lt;/h4&gt;

&lt;p&gt;Another set of tools that might come in handy is preload and prefetch.&lt;br&gt;
Also, script async and defer.&lt;br&gt;
Again, learn the differencies between these, so you're aware if and when to use them.&lt;br&gt;
&lt;code&gt;&amp;lt;link rel="prefetch" href="/bundle.js"&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&amp;lt;link rel="preload" href="/something.chunk.js"&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&amp;lt;script defer src="./script.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&amp;lt;script async src="./script.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Reflow vs Repaint
&lt;/h4&gt;

&lt;p&gt;While this is somewhat advanced and you might not need it on a daily basis, learning the concept of browser repaint and reflow cycles might further expand your horizons when pondering performance.&lt;br&gt;
And for general web performance overview, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance"&gt;MDN&lt;/a&gt; is always a good starting point.&lt;/p&gt;
&lt;h4&gt;
  
  
  Code splitting
&lt;/h4&gt;

&lt;p&gt;Code splitting with React and bundlers like webpack is extremely easy to setup, and you should almost always use it.&lt;br&gt;
The most sensible way to start with is usually splitting your routes and maybe some parts of the application that are not accessed very frequently by users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Library&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="cm"&gt;/* webpackChunkName: "library" */&lt;/span&gt; &lt;span class="cm"&gt;/* webpackPrefetch: true */&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Components/Library/Library&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;h4&gt;
  
  
  Watch out for async/await
&lt;/h4&gt;

&lt;p&gt;We all know async/await is great, right?&lt;br&gt;
But one thing I noticed it has lead to, is the pitfall of sequential code where none is needed.&lt;br&gt;
It's not once that I've seen in the wild code that awaits something, while there's code below hanging in there, even though it does not have to.&lt;br&gt;
Ie&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;componentDidMount&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;genres&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetchGenres&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;genres&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;isPlatformReady&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;platformReady&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPlatformReady&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;isPlatformReady&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case above, there's no reason for anything below line 3 to wait for genres to fetch.&lt;br&gt;
Beware of sequential code, folks.&lt;/p&gt;

&lt;h4&gt;
  
  
  React components
&lt;/h4&gt;

&lt;p&gt;Performance wise, React is great.&lt;br&gt;
But, there are still stuff to watch out for.&lt;br&gt;
Here's some:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;React.memo&lt;/code&gt; There are two "schools of thought" here. First is use it all the time, second one is use it sparingly. If you decide to use it all the time, you might end up slightly improving performance for some components, having little to no impact on others, and having negative impact on edge cases. If you decide to evaluate and use it sparingly only where it makes sense, you'll be safer, but it does consume more time(which is one of the main arguments for "use it all the time" I've seen).
It sounds great in theory, but in practice it can easily prove "more trouble than it's worth". Eg. if a component has large number of props, might be the same or even faster to just let it re-render instead of making a costly check against all those props.
Personally, I'm leaning towards checking in the profiler whether you're getting something out of it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Context&lt;/code&gt; is always somewhat costly to use.
Make sure it's not overused. Prop drilldown isn't ideal, but it might save you some performance hits of having every component ever connected to global state management.
One problem we encountered was with &lt;code&gt;styled-components&lt;/code&gt; a couple of years ago, when we started the project.
Not sure about now, but back then it used context for every single styled component.
Needless to say, we noticed performance hits, and quickly switched to good old sass.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt; are generally worth it, with some exceptions.
&lt;code&gt;useMemo&lt;/code&gt; is great for your stuff that is derived from props/state and &lt;code&gt;useCallback&lt;/code&gt; for your functions in components.
Main thing to watch out for here is using these if their dependencies change too often.
Ie, if you're memoizing function reference with &lt;code&gt;useCallback&lt;/code&gt;, but it's dependency is ie &lt;code&gt;inputValue&lt;/code&gt; which changes on every key press.
In that case, &lt;code&gt;useCallback&lt;/code&gt; just slows you down, as function reference will change anyway because of constantly changing dependency, you're just introducing memoization on top of recreating the function.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Virtualization
&lt;/h4&gt;

&lt;p&gt;There are many great open source libraries for React which handle virtualization and lazy loading of components in lists.&lt;br&gt;
Most notable being &lt;a href="https://www.npmjs.com/package/react-virtualized"&gt;react-virtualized&lt;/a&gt;.&lt;br&gt;
These are generally easy to setup and use, and solve almost all your problems of slow rendering in long lists of components.&lt;/p&gt;

&lt;p&gt;However, because of spatial navigation, none of them satisfy our needs on TVs.&lt;br&gt;
So, we built our own virtualization that works well for us, although we can't say we're too happy about having to allocate time for that.&lt;br&gt;
Fortunately, if you're not running your web app on a TV, this is a problem you won't encounter.   &lt;/p&gt;

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

&lt;p&gt;And that about covers the main stuff.&lt;br&gt;
Sure, there's also stuff like video playback, which is an epic narrative on it's own.&lt;br&gt;
The accessibility, TV vendors usually have mandatory requirement for TTS accessibility in apps.&lt;br&gt;
That's where we learned the hard way that WAI-ARIA standard is not much of a standard and that imperative TTS is much more maintainable.&lt;br&gt;
And don't get me started on development experience TV vendors provide, or we might be here all day.&lt;br&gt;
But, these are stories for another time.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>tv</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
