<?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: Arnaud Denoyelle</title>
    <description>The latest articles on DEV Community by Arnaud Denoyelle (@arnauddenoyelle).</description>
    <link>https://dev.to/arnauddenoyelle</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%2F281743%2Fdc270cca-1e23-463f-ad9a-f435c5793d48.jpg</url>
      <title>DEV Community: Arnaud Denoyelle</title>
      <link>https://dev.to/arnauddenoyelle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arnauddenoyelle"/>
    <language>en</language>
    <item>
      <title>From Wow to Oops: The Vibe Coding Reality Check</title>
      <dc:creator>Arnaud Denoyelle</dc:creator>
      <pubDate>Tue, 12 Aug 2025 09:50:55 +0000</pubDate>
      <link>https://dev.to/arnauddenoyelle/from-wow-to-oops-the-vibe-coding-reality-check-1alc</link>
      <guid>https://dev.to/arnauddenoyelle/from-wow-to-oops-the-vibe-coding-reality-check-1alc</guid>
      <description>&lt;p&gt;AI is having its “gold rush” moment.&lt;/p&gt;

&lt;p&gt;Every week, there’s a new tool promising you can “build an app in minutes” — just type a prompt and watch the magic happen.&lt;/p&gt;

&lt;p&gt;Non-technical folks see it and think: “Wow, developers must be 100x faster now.”&lt;br&gt;
But here’s the thing: the magic trick only works from the right angle.&lt;/p&gt;

&lt;p&gt;In this article, I’ll unpack why the reality is messier and how to use AI productively without falling for the hype.&lt;/p&gt;

&lt;p&gt;Note : What I call &lt;strong&gt;vibe-coding&lt;/strong&gt; is creating an application almost without writing any code, relying solely on prompts. This is in contrast to &lt;strong&gt;LLM-assisted coding&lt;/strong&gt;, where the developer creates the project and occasionally uses prompts to complete it.&lt;/p&gt;
&lt;h2&gt;
  
  
  The illusion of application generators
&lt;/h2&gt;

&lt;p&gt;I fully agree with the description given here: &lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="https://brianjenney.medium.com/my-trip-to-vibe-coding-hell-17eb806824a1" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A64%3A64%2F1%2AHYcJ_z0ti23gZRVoLG3IpA.jpeg" alt="Brian Jenney"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://brianjenney.medium.com/my-trip-to-vibe-coding-hell-17eb806824a1" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;My Trip to Vibe Coding Hell. Let me start by saying that I use AI to… | by Brian Jenney | Medium&lt;/h2&gt;
      &lt;h3&gt;Brian Jenney ・ &lt;time&gt;May 15, 2025&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        brianjenney.Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Your manager reads a few LinkedIn posts about AI, tries an application generator, and suddenly expects you to work 100 times faster.&lt;/p&gt;

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

&lt;p&gt;But that’s not how it works.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A developer often spends more time reading code than writing it&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;especially when the code was generated by AI.&lt;/p&gt;

&lt;p&gt;So, no—you won’t code 100 times faster with AI. At least, not today.&lt;/p&gt;

&lt;p&gt;Many have tried this: go to an application generator (&lt;a href="https://replit.com/" rel="noopener noreferrer"&gt;Replit&lt;/a&gt;, &lt;a href="https://lovable.dev/" rel="noopener noreferrer"&gt;Lovable&lt;/a&gt;, &lt;a href="https://bolt.new/" rel="noopener noreferrer"&gt;Bolt&lt;/a&gt;, &lt;a href="https://v0.app/" rel="noopener noreferrer"&gt;V0&lt;/a&gt;), enter a prompt, and receive a “working” app.&lt;/p&gt;

&lt;p&gt;It feels like “&lt;em&gt;AI &lt;strong&gt;built&lt;/strong&gt; it&lt;/em&gt;”. In reality, it’s closer to “&lt;em&gt;AI &lt;strong&gt;finished&lt;/strong&gt; it&lt;/em&gt;”.&lt;/p&gt;

&lt;p&gt;Most generated apps are 80% boilerplate, 20% actual features — and that boilerplate is almost always pre-written by humans&lt;/p&gt;

&lt;p&gt;Think of the boilerplate as the foundation of a house—the technical groundwork before construction begins. In software, that means setting up tools, a database, a server, basic page structures, etc.&lt;/p&gt;

&lt;p&gt;When developers code manually, this boilerplate is what takes the most time at the beginning. Generators just clone a boilerplate and sprinkle AI-generated features on top.&lt;/p&gt;

&lt;p&gt;That’s why the first prompt often delivers impressive results, but subsequent prompts fail to produce the same value.&lt;/p&gt;

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

&lt;p&gt;Right now, you can’t realistically expect AI tools to generate large, production-ready applications from scratch. &lt;/p&gt;

&lt;p&gt;They’re still best suited for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ideation&lt;/li&gt;
&lt;li&gt;Design team support&lt;/li&gt;
&lt;li&gt;Small personal tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typically, the design team can test prompts with style constraints, color palettes, fonts, etc., and see the results live while generating multiple mockup proposals.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Complexity
&lt;/h2&gt;

&lt;p&gt;You ask the AI to make a login/password form.&lt;/p&gt;

&lt;p&gt;It gives you a form with two fields and a button. You think that’s it? That’s the “happy path,” the nominal case.&lt;/p&gt;

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

&lt;p&gt;But alongside that, you also have to handle all the other cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data validation (show the field in red if it’s empty, etc.)&lt;/li&gt;
&lt;li&gt;Extra features (auto-fill, global styling, etc.)&lt;/li&gt;
&lt;li&gt;Is it responsive?&lt;/li&gt;
&lt;li&gt;Handle error messages&lt;/li&gt;
&lt;li&gt;If the password is wrong, allow another attempt (or not)&lt;/li&gt;
&lt;li&gt;If the address doesn’t exist, suggest signing up&lt;/li&gt;
&lt;li&gt;If an unexpected error occurs? “Please try again later”&lt;/li&gt;
&lt;li&gt;Handle abuse&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What about someone trying to brute-force a password? Just for that, you have to go through a whole process of setting up a captcha, with Google API calls, etc.&lt;/p&gt;

&lt;p&gt;And what about someone attempting an SQL injection?&lt;/p&gt;

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

&lt;p&gt;Extra features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What if I forgot my password? You need a separate form, with an email being sent. That’s another whole process in itself.&lt;/li&gt;
&lt;li&gt;And what if I want to log in with a Google account instead? That’s another separate process to set up OAuth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need to think about handling all these cases (and actually know they exist in the first place), and it takes time to deal with them, even with AI — if only to simulate/test that you’re handling them correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Story Behind Productivity Curves
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Junior&lt;/strong&gt; – Starts quickly but maintains a slow overall pace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Senior&lt;/strong&gt; – Invests time upfront to build a solid boilerplate, then accelerates and eventually outpaces everyone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vibe coding&lt;/strong&gt; – Bursts out of the gate with impressive speed, but soon crashes into the vibe coding wall — where lack of structure and growing complexity drain momentum.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s a zone where the developer has to explain to their manager that, no, vibe coding won’t actually make us faster. This is tricky, because from the manager’s perspective, things currently look very different. Navigating this moment requires clear communication and strong teaching skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dangers of Vibe Coding
&lt;/h2&gt;

&lt;p&gt;Sometimes, managers just want to ship code quickly, regardless of quality.&lt;/p&gt;

&lt;p&gt;There are two major risks with AI-generated code: &lt;strong&gt;security&lt;/strong&gt; and &lt;strong&gt;skyrocketing costs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Application generators often allow users to write code without understanding it—creating high security risks. &lt;strong&gt;I expect many generated apps will leak user data&lt;/strong&gt; simply because their creator doesn’t truly understand how they work.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you can’t explain your code, you can’t secure it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There’s also the financial risk: AI can produce inefficient code that consumes vastly more resources than necessary — sometimes even getting stuck in infinite loops — leading to bills in the hundreds of thousands.&lt;/p&gt;

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

&lt;p&gt;Rule of thumb: &lt;strong&gt;never run code you don’t fully understand&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Moore’s Law
&lt;/h2&gt;

&lt;p&gt;Source : &lt;a href="https://theaidigest.org/time-horizons" rel="noopener noreferrer"&gt;https://theaidigest.org/time-horizons&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s a so-called &lt;em&gt;AI Moore’s Law&lt;/em&gt;, suggesting that AI’s “time horizon” doubles every 7 months:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initially, AI could do in 30 seconds what a coder could do—success rate 50%.&lt;/li&gt;
&lt;li&gt;Seven months later, it could handle 1-minute tasks.&lt;/li&gt;
&lt;li&gt;Today, it can handle 1-hour tasks (still with a 50% success rate).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But remember—a typical software project can represent decades of development (5–10 developers over 2–3 years).&lt;/p&gt;

&lt;p&gt;If the trend continues, AI could match one month of coding by 2030. Even then, that won’t be enough for fully automated software creation for non-developers.&lt;/p&gt;

&lt;p&gt;For developers, though, this is still a huge advantage—AI will be able to take on increasingly large chunks of work.&lt;/p&gt;

&lt;h2&gt;
  
  
  LLM-Assisted Development
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1953531950137815374-297" src="https://platform.twitter.com/embed/Tweet.html?id=1953531950137815374"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1953531950137815374-297');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1953531950137815374&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;We don’t need to wait for fully autonomous AI.&lt;br&gt;
If AI can do an hour’s worth of coding with a 50% success rate, it can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do 30 minutes with ~70% success (70%² ≈ 50%)&lt;/li&gt;
&lt;li&gt;Do 15 minutes with ~84% success (84%⁴ ≈ 50%)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s already a massive time saver.&lt;/p&gt;

&lt;p&gt;Developers are also learning to distinguish between tasks AI can and cannot handle.&lt;/p&gt;

&lt;p&gt;Right now, AI is especially effective for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spotting bugs&lt;/li&gt;
&lt;li&gt;Writing and updating documentation&lt;/li&gt;
&lt;li&gt;Creating automated tests&lt;/li&gt;
&lt;li&gt;Developing small features&lt;/li&gt;
&lt;li&gt;Drafting development plans&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These use cases will only expand.&lt;/p&gt;

&lt;p&gt;It’s also becoming easy to “train” AI to code in a specific style.&lt;/p&gt;

&lt;p&gt;You can give it a file describing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How you build forms (with examples)&lt;/li&gt;
&lt;li&gt;How you handle database requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it will follow your style for repetitive tasks, leaving you to connect everything together.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Work with AI Today
&lt;/h2&gt;

&lt;p&gt;AI offers both opportunities and risks. The key is understanding its current limits to avoid unrealistic expectations.&lt;/p&gt;

&lt;p&gt;There won’t be an “AI big bang” but rather a steady, continuous adoption.&lt;/p&gt;

&lt;p&gt;AI won’t replace developers tomorrow. But developers who know how to work with AI — and know its limits — will replace those who don’t.&lt;/p&gt;

&lt;p&gt;So my advice is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Experiment daily&lt;/li&gt;
&lt;li&gt;Learn what AI can and can’t do&lt;/li&gt;
&lt;li&gt;Never ship code you don’t understand&lt;/li&gt;
&lt;li&gt;Regularly test whether past limitations have improved&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invest in communication&lt;/strong&gt; — Learn to clearly explain AI’s limits and trade-offs to non-technical stakeholders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vibe-coding can be a great creative tool — just don’t confuse the demo for the delivery.&lt;/p&gt;

&lt;p&gt;Have you tried vibe-coding yet? What worked for you, and what blew up in your face?&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>ai</category>
    </item>
    <item>
      <title>Double bind the foreign key to avoid unnecessary JOIN in TypeORM</title>
      <dc:creator>Arnaud Denoyelle</dc:creator>
      <pubDate>Sat, 23 Mar 2024 18:38:02 +0000</pubDate>
      <link>https://dev.to/arnauddenoyelle/double-bind-the-foreign-key-to-avoid-unnecessary-join-in-typeorm-29bf</link>
      <guid>https://dev.to/arnauddenoyelle/double-bind-the-foreign-key-to-avoid-unnecessary-join-in-typeorm-29bf</guid>
      <description>&lt;p&gt;ORM tools are cool but they generate SQL "automagically". The generated code tends to be unnecessarily complex and causes a performance overhead.&lt;/p&gt;

&lt;p&gt;In a database, performance depends on the time to compute the information + the time to bring this information back to the server.&lt;/p&gt;

&lt;p&gt;In this article, I will show how to reduce the computation time by removing some unnecessary JOINs and how to load only the information you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model
&lt;/h2&gt;

&lt;p&gt;In this article, we will use the simplest possible model :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A table called &lt;code&gt;company&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A table called &lt;code&gt;employee&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;mapped like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;company&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompanyEntity&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;PrimaryGeneratedColumn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;creation_date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;creationDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;employee&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmployeeEntity&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;PrimaryGeneratedColumn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;creation_date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;creationDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;JoinColumn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;company_id&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="nd"&gt;ManyToOne&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;CompanyEntity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;company&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CompanyEntity&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;h3&gt;
  
  
  Preparation : Activate logging on the local environment
&lt;/h3&gt;

&lt;p&gt;To spot optimization problems early, you should always log the generated SQL at least in your local environment. You can do so using the &lt;code&gt;logging&lt;/code&gt; option from the TypeORM configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;createTypeOrmOptions():&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;TypeOrmModuleOptions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;host:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;port:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;database:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;username:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;password:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;schema:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;logging:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Here&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;entities:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;CompanyEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;EmployeeEntity&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;synchronize:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way, TypeORM will output the generated SQL in logs, which is a huge help for debugging. Here is an example of output :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;query: SELECT &lt;span class="s2"&gt;"EmployeeEntity"&lt;/span&gt;.&lt;span class="s2"&gt;"id"&lt;/span&gt; AS &lt;span class="s2"&gt;"EmployeeEntity_id"&lt;/span&gt;, &lt;span class="s2"&gt;"EmployeeEntity"&lt;/span&gt;.&lt;span class="s2"&gt;"creation_date"&lt;/span&gt; AS &lt;span class="s2"&gt;"EmployeeEntity_creation_date"&lt;/span&gt;, &lt;span class="s2"&gt;"EmployeeEntity"&lt;/span&gt;.&lt;span class="s2"&gt;"first_name"&lt;/span&gt; AS &lt;span class="s2"&gt;"EmployeeEntity_first_name"&lt;/span&gt;, &lt;span class="s2"&gt;"EmployeeEntity"&lt;/span&gt;.&lt;span class="s2"&gt;"last_name"&lt;/span&gt; AS &lt;span class="s2"&gt;"EmployeeEntity_last_name"&lt;/span&gt;, &lt;span class="s2"&gt;"EmployeeEntity"&lt;/span&gt;.&lt;span class="s2"&gt;"company_id"&lt;/span&gt; AS &lt;span class="s2"&gt;"EmployeeEntity_company_id"&lt;/span&gt; FROM &lt;span class="s2"&gt;"acme"&lt;/span&gt;.&lt;span class="s2"&gt;"employee"&lt;/span&gt; &lt;span class="s2"&gt;"EmployeeEntity"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this article, we will rely on that to show the code generated by TypeORM&lt;/p&gt;




&lt;h3&gt;
  
  
  Double bind the foreign key
&lt;/h3&gt;

&lt;p&gt;Suppose that your application has already loaded the list of companies and you want to get the list of employees for one specific company, knowing it's &lt;code&gt;companyId&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The naive implementation would be this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;findByCompanyId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;companyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;employeeRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findBy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;company&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;companyId&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;But let's have a look at the generated SQL :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;            &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"creation_date"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_creation_date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_name"&lt;/span&gt;    &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_name"&lt;/span&gt;     &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"company_id"&lt;/span&gt;    &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_company_id"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"employee"&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;
  &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"company"&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity__EmployeeEntity_company"&lt;/span&gt;
    &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity__EmployeeEntity_company"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"company_id"&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;((((&lt;/span&gt;&lt;span class="nv"&gt;"EmployeeEntity__EmployeeEntity_company"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a &lt;code&gt;JOIN&lt;/code&gt; between the &lt;code&gt;employee&lt;/code&gt; and &lt;code&gt;company&lt;/code&gt; tables! This join is not necessary as the "company id" information is already present in the &lt;code&gt;employee&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;And here comes the double binding on the foreign key to solve that :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;employee&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmployeeEntity&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseEntity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;PrimaryGeneratedColumn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// [...]&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;JoinColumn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;company_id&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="nd"&gt;ManyToOne&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;CompanyEntity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;company&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CompanyEntity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Here is where the magic happens&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;company_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;companyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;We let the &lt;code&gt;company&lt;/code&gt; relationship but add a &lt;code&gt;companyId&lt;/code&gt; field, which points to the same column.&lt;/p&gt;

&lt;p&gt;Now we can rewrite the &lt;code&gt;findByCompany&lt;/code&gt; implementation like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;findByCompanyId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;companyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;employeeRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findBy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// Use the companyId "column" instead of the relationship&lt;/span&gt;
    &lt;span class="na"&gt;companyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;companyId&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the generated SQL looks like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;            &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"creation_date"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_creation_date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_name"&lt;/span&gt;    &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_name"&lt;/span&gt;     &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"company_id"&lt;/span&gt;    &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_company_id"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"employee"&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"company_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more unnecessary JOIN !&lt;/p&gt;




&lt;h3&gt;
  
  
  Bonus: "SELECT" only the information you need
&lt;/h3&gt;

&lt;p&gt;In this example, the table &lt;code&gt;employee&lt;/code&gt; contains few columns but, in a real-world example, it could contain dozens of columns that you don't need every time. Especially columns that could contain sensible information&lt;/p&gt;

&lt;p&gt;Suppose that I just fetch all employees like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;employeeRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the generated sql :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;            &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"creation_date"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_creation_date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_name"&lt;/span&gt;    &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_name"&lt;/span&gt;     &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"company_id"&lt;/span&gt;    &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_company_id"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"employee"&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we might not need all the columns. TypeORM lets you decide which columns you want to fetch, like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;employeeRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : we don't call &lt;code&gt;findBy&lt;/code&gt; anymore but &lt;code&gt;find&lt;/code&gt; which allows us to pass other useful parameters such as &lt;code&gt;take&lt;/code&gt;, &lt;code&gt;skip&lt;/code&gt; and &lt;code&gt;relations&lt;/code&gt; (this one is for lazy/eager loading), and of course, the &lt;code&gt;where&lt;/code&gt; clause.&lt;/p&gt;

&lt;p&gt;And here is the corresponding SQL :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"first_name"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_name"&lt;/span&gt;  &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;         &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity_id"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"employee"&lt;/span&gt; &lt;span class="nv"&gt;"EmployeeEntity"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; : the return type will still be a &lt;code&gt;EmployeeEntity[]&lt;/code&gt; but the non-required fields are left &lt;code&gt;undefined&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Double binding on the foreign key is so useful that I now use it on nearly every foreign key. &lt;/p&gt;

&lt;p&gt;Also, &lt;code&gt;select&lt;/code&gt; can be useful on main tables, especially the &lt;code&gt;user&lt;/code&gt; table, which often contains sensible information that you don't want to expose outside of the database if not necessary.&lt;/p&gt;

&lt;p&gt;I hope that those tips will help you reduce the performance overhead on your database!&lt;/p&gt;

</description>
      <category>typeorm</category>
      <category>typescript</category>
      <category>database</category>
    </item>
    <item>
      <title>Stupid form generator</title>
      <dc:creator>Arnaud Denoyelle</dc:creator>
      <pubDate>Sun, 02 Oct 2022 15:25:13 +0000</pubDate>
      <link>https://dev.to/arnauddenoyelle/stupid-form-generator-2434</link>
      <guid>https://dev.to/arnauddenoyelle/stupid-form-generator-2434</guid>
      <description>&lt;p&gt;Or why full automatic forms generators are often a fake good idea, and what to use instead.&lt;/p&gt;

&lt;p&gt;But first things first, why do we use form generators in the first place ?&lt;/p&gt;

&lt;h2&gt;
  
  
  Forms take more time to develop than expected
&lt;/h2&gt;

&lt;p&gt;Let's say you want to build a login/password form. 2 input fields + a submit button. Seems easy and looks like it will take 5 min.&lt;/p&gt;

&lt;p&gt;But experienced developers learned the hard way that forms hide some complexity :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Field validation&lt;/li&gt;
&lt;li&gt;Error messages&lt;/li&gt;
&lt;li&gt;Layout problems&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;If you need a lot of forms in your application, they can be tedious to build. To tackle this problem, some developer's immediate reaction is to use a form generator. There are plenty of them, in every existing language.&lt;/p&gt;




&lt;h2&gt;
  
  
  Automatic form generators : the fake good idea
&lt;/h2&gt;

&lt;p&gt;Form generators come with a handful of promises :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just configuration, no HTML/CSS/JS/Java to write&lt;/li&gt;
&lt;li&gt;The code base will become "cleaner"&lt;/li&gt;
&lt;li&gt;Compatible with any tool/framework/library&lt;/li&gt;
&lt;li&gt;Fully configurable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the beginning, everything seems easy to use, and the demo works well.&lt;/p&gt;

&lt;p&gt;Then you decide to use it in your project, on real use cases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fije858qhbm813kogljqd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fije858qhbm813kogljqd.png" alt="This is where the fun begins" width="605" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, you discover problems : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A text field is nice, but I need a text area instead&lt;/li&gt;
&lt;li&gt;But I need a very special component for this field, like a color picker&lt;/li&gt;
&lt;li&gt;But here, I want to place components differently&lt;/li&gt;
&lt;li&gt;But here, I want to add a "special offer" tag&lt;/li&gt;
&lt;li&gt;But I need to react to a value change in this component &lt;/li&gt;
&lt;li&gt;But I need to show a different component if this field has that value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And their usual solutions :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have an option for that&lt;/li&gt;
&lt;li&gt;You can use a design pattern provide your own component&lt;/li&gt;
&lt;li&gt;You can override the layout with CSS&lt;/li&gt;
&lt;li&gt;You can use a factory/builder/adapter in order to handle this very special use case&lt;/li&gt;
&lt;li&gt;You can provide a callback&lt;/li&gt;
&lt;li&gt;We developed a custom dynamic expression language to handle this use case&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, you realize that, for complex use cases, it would have been easier to just use the native API&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A form generator that aims at handling every use case is bound to become more complex than the problem it was supposed to solve.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You did not want to write code, but your configuration became the code&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6yx1b98pkjtv0njdaz3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6yx1b98pkjtv0njdaz3.png" alt="You've become the very thing you swore to destroy" width="755" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do you remember when you just wrote the form by hand, and were able to do exactly what you wanted without dealing with tons of options ?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With a full automatic form generator, you still end up coding the form manually&lt;/strong&gt;. You just code with the generator options instead of the native API, but you actually finish the code manually.&lt;/p&gt;

&lt;p&gt;Configuring form generators takes time, and if you have less than &amp;lt; 10 forms in your app... just write them by hand.&lt;/p&gt;

&lt;p&gt;Or...&lt;/p&gt;




&lt;h2&gt;
  
  
  Code generators to the rescue
&lt;/h2&gt;

&lt;p&gt;Use a &lt;strong&gt;code generator&lt;/strong&gt; instead. What is the difference ? You generate some code then copy-paste this code in the project. The project does not contain the form generator anymore, only the generated code.&lt;/p&gt;

&lt;p&gt;Then, you can finish the code manually, adapt the structure as you wish and use the native API for complex use cases.&lt;/p&gt;

&lt;p&gt;Also, as the complexity comes from the intention to handle every case... what if you just generated some code that is only 90% right ?&lt;/p&gt;

&lt;p&gt;A code that is only 90% accurate ? Really ?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ov9ix9c5pr93pijwilw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ov9ix9c5pr93pijwilw.png" alt="You underestimate my power" width="400" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you don't need to handle every use case anymore, the complexity falls dramatically. With a rule like "1 field = 1 component", &lt;strong&gt;you can build yourself a code generator&lt;/strong&gt; that will handle 90% of the use cases &lt;strong&gt;in only ~100 lines of code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And as you code the generator yourself, you can decide what you want to automatize or not and fully customize the generated code to your good taste.&lt;/p&gt;

&lt;p&gt;I show you how to do that, and I provide a boilerplate&lt;/p&gt;




&lt;h2&gt;
  
  
  Build your own code generator
&lt;/h2&gt;

&lt;p&gt;This part shows one possible way to build a custom code generator. I provide a working example &lt;a href="https://github.com/ArnaudDenoyelle/stupid-form-generator"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;It generates a basic Angular form with 2 templates :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One template for the HTML code&lt;/li&gt;
&lt;li&gt;One template for the TypeScript code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not much, but enough to understand the concept.&lt;/p&gt;

&lt;p&gt;The code generator consists in 3 steps :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Describe the form fields&lt;/li&gt;
&lt;li&gt;Enrich the model with variables that will be useful in the templates&lt;/li&gt;
&lt;li&gt;Apply the enriched model on various templates&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1) Describe the fields
&lt;/h3&gt;

&lt;p&gt;The first thing you need is a place to describe the fields. As it will be &lt;strong&gt;your&lt;/strong&gt; code generator and &lt;strong&gt;your&lt;/strong&gt; templates, just think about the info that you will need when writing the templates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firstName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TEXTFIELD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lastName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TEXTFIELD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;[...]&lt;/span&gt;
     &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2) Enrich the model
&lt;/h3&gt;

&lt;p&gt;From this point, the variable name &lt;code&gt;firstName&lt;/code&gt; is useful, but you will probably need to have it in different cases : &lt;code&gt;FIRST_NAME&lt;/code&gt;, &lt;code&gt;first-name&lt;/code&gt;, &lt;code&gt;First Name&lt;/code&gt; etc. This can be automatized with a simple for loop in order to obtain that :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"component"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TEXTFIELD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"placeholder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameCamelCase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameUpperCase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FIRST_NAME"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameSnakeCase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameCapitalized"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FirstName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameKebabCase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"first-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameLabel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First Name"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"component"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TEXTFIELD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"placeholder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameCamelCase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameUpperCase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LAST_NAME"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameSnakeCase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameCapitalized"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LastName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameKebabCase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"last-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nameLabel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Last Name"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3) Apply it to templates
&lt;/h3&gt;

&lt;p&gt;For this part, you have to choose a template engine. I chose &lt;a href="https://ejs.co/"&gt;ejs&lt;/a&gt; because it has the required features : conditions and loops. Also, it is quite standard and well documented&lt;/p&gt;

&lt;p&gt;The code is as simple as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Loading template &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;templatePath&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;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templatePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Compiling template&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;compiledTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ejs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Applying template&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compiledTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;enrichedInput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is what the template looks like :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;[formGroup]=&lt;/span&gt;&lt;span class="s"&gt;"formGroup"&lt;/span&gt; &lt;span class="na"&gt;(ngSubmit)=&lt;/span&gt;&lt;span class="s"&gt;"onSubmit()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;fields.forEach&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="err"&gt;){&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="na"&gt;_&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;(field.component =&lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;TEXTFIELD&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="na"&gt;-&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mat-form-field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;mat-label&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;field.nameLabel&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/mat-label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;matInput&lt;/span&gt; &lt;span class="na"&gt;[formControl]=&lt;/span&gt;&lt;span class="s"&gt;"formControl&amp;lt;%= field.nameCapitalized%&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;(field.required =&lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt; &lt;span class="na"&gt;true&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; placeholder="&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;field.placeholder&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;"&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&amp;gt;
    &lt;span class="nt"&gt;&amp;lt;/mat-form-field&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="na"&gt;_&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="na"&gt;-&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="na"&gt;_&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;(field.component =&lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;TEXTAREA&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="na"&gt;-&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mat-form-field&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;mat-label&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;field.nameLabel&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/mat-label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;matInput&lt;/span&gt; &lt;span class="na"&gt;[formControl]=&lt;/span&gt;&lt;span class="s"&gt;"formControl&amp;lt;%= field.nameCapitalized%&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;(field.required =&lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt; &lt;span class="na"&gt;true&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; placeholder="&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;field.placeholder&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;"&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&amp;gt;&lt;span class="nt"&gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/mat-form-field&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="na"&gt;_&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="na"&gt;-&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Put everything together
&lt;/h3&gt;

&lt;p&gt;The complete program works like that :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the list of form fields from the input file&lt;/li&gt;
&lt;li&gt;Enrich the model with various string cases&lt;/li&gt;
&lt;li&gt;For each template of the &lt;code&gt;templates&lt;/code&gt; directory : 

&lt;ul&gt;
&lt;li&gt;Apply the enriched model on the template&lt;/li&gt;
&lt;li&gt;Open the template in your favorite text editor&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For me, it opens the generated files in gedit, ready to be copy-pasted to the project !&lt;/p&gt;

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




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

&lt;p&gt;By taking back the control on the generated code, you can have 90% of the code automatically generated while still being able to fully customize the output.&lt;/p&gt;

&lt;p&gt;Bonus : using the same strategy, it is possible, from a given class to generate most of the files for the frontend &lt;strong&gt;AND the backend&lt;/strong&gt; part of the app that are more or less always the sames:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DAO&lt;/li&gt;
&lt;li&gt;Service&lt;/li&gt;
&lt;li&gt;Controller&lt;/li&gt;
&lt;li&gt;Model&lt;/li&gt;
&lt;li&gt;View&lt;/li&gt;
&lt;li&gt;Presenter&lt;/li&gt;
&lt;li&gt;various pieces of configuration to add in those files that you systematically forget.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I applied this strategy with success in an app that contained hundreds of forms. The code generator (written in Java at the time) would generate 25 different files for every part of the application : frontend, backend, database, configuration.&lt;/p&gt;

&lt;p&gt;Code generators are nothing new and they are incredibly efficient. Their power should not be forgotten&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yzwlwwzurv6juobtail.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yzwlwwzurv6juobtail.png" alt="I know him, it's me" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>html</category>
    </item>
    <item>
      <title>9 things Chrome DevTools can do for you</title>
      <dc:creator>Arnaud Denoyelle</dc:creator>
      <pubDate>Tue, 06 Jul 2021 09:10:07 +0000</pubDate>
      <link>https://dev.to/arnauddenoyelle/9-things-chrome-devtools-can-do-for-you-1oij</link>
      <guid>https://dev.to/arnauddenoyelle/9-things-chrome-devtools-can-do-for-you-1oij</guid>
      <description>&lt;p&gt;This is my first article here. In this article, I share some tips that I wish I had known sooner. Those tips help you to debug faster and/or code better.&lt;/p&gt;

&lt;p&gt;Most of the features I show here are available in all browsers.&lt;/p&gt;

&lt;p&gt;The most important feature to me is 7 - Lighthouse and if you work with a dedicated test team, 8 - Export the Network tab is vital !&lt;/p&gt;

&lt;h2&gt;
  
  
  1 - Put any DOM element in a variable
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;Elements&lt;/em&gt; tab allows you to edit the DOM and CSS properties. &lt;/p&gt;

&lt;p&gt;But did you know that clicking on an element of the DOM will also put this element in the variable &lt;code&gt;$0&lt;/code&gt; ? Chrome actually gives an hint about that by adding &lt;code&gt;== $0&lt;/code&gt; beside the selected element :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7zj9tvio9e9ax0jyyf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7zj9tvio9e9ax0jyyf7.png" alt="Select DOM element" width="312" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then manipulate it in JavaScript from the &lt;em&gt;Console&lt;/em&gt; tab : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fso3ho9vpv8r4hnx6x6u7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fso3ho9vpv8r4hnx6x6u7.png" alt="DOM element in console" width="257" height="35"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, if you select other elements, &lt;code&gt;$1&lt;/code&gt; will contain the previously selected element. &lt;code&gt;$2&lt;/code&gt;, &lt;code&gt;$3&lt;/code&gt; and &lt;code&gt;$4&lt;/code&gt; work in the same way.&lt;/p&gt;

&lt;h2&gt;
  
  
  2 - Pretty print minified source files
&lt;/h2&gt;

&lt;p&gt;In the &lt;em&gt;Sources&lt;/em&gt; tab now, suppose that you are working with minified code and need to put a breakpoint somewhere in this file : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4m0zryvof4a1p5jua0xw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4m0zryvof4a1p5jua0xw.png" alt="Before pretty print" width="665" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This script is minified so the whole script lies in a unique line. How to put a breakpoint if there is only one line ? This is where the &lt;em&gt;Pretty print&lt;/em&gt; tool comes in. It is located in the lower left corner :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsq4oyey59v2kcqxt8tt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsq4oyey59v2kcqxt8tt.png" alt="Pretty print tool" width="387" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click it and... tadaaa !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6fbw3algyvuhzhzv9mp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6fbw3algyvuhzhzv9mp.png" alt="After pretty print" width="657" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3 - Conditional breakpoints
&lt;/h2&gt;

&lt;p&gt;Speaking about breakpoints : what if there is a function that is called very often and throws an error only when a particular value is given ? How do you debug it without clicking 100 times on "Step over" ?&lt;/p&gt;

&lt;p&gt;You can &lt;del&gt;add a condition or a bunch of &lt;code&gt;console.log&lt;/code&gt;&lt;/del&gt; use &lt;em&gt;Conditional breakpoints&lt;/em&gt; !&lt;/p&gt;

&lt;p&gt;First, you need... a breakpoint !&lt;/p&gt;

&lt;p&gt;Click in the left column on the line of your choice to add a breakpoint then right click on the blue arrow then &lt;em&gt;Edit breakpoint&lt;/em&gt; :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnf9ia9co1sfup5x0m00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnf9ia9co1sfup5x0m00.png" alt="Edit breakpoint" width="348" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now write  any condition you want. The code execution will stop only when the condition returns &lt;code&gt;true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sf1ncn674w89zhacgvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sf1ncn674w89zhacgvq.png" alt="Breakpoint condition" width="605" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4 - Preserve logs upon navigation
&lt;/h2&gt;

&lt;p&gt;Tired of losing logs each time you navigate ? You can just tell Chrome to keep them. The cog icon located in the upper right corner offers a ton of useful options.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fask8m3rfi1rv1bdkd6qp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fask8m3rfi1rv1bdkd6qp.png" alt="Devtools preferences" width="701" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;Network&lt;/em&gt; section, you can tick &lt;em&gt;Preserve logs&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;Console&lt;/em&gt; section, you can tick &lt;em&gt;Preserve log upon navigation&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlg07nud3uzaszsldymy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlg07nud3uzaszsldymy.png" alt="Devtools preferences options" width="700" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a lot of other useful options, such as &lt;em&gt;Show timestamps&lt;/em&gt; in the &lt;em&gt;Console&lt;/em&gt; section. Feel free to explore them !&lt;/p&gt;

&lt;h2&gt;
  
  
  5 - Simulate a slow connection
&lt;/h2&gt;

&lt;p&gt;Not everyone has a good internet connection. Do you know how long does it take to display your site on a slow connection ?&lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;Network&lt;/em&gt; tab, there is an option to simulate a slow connection : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e838e0ksfiwdni4ugg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e838e0ksfiwdni4ugg7.png" alt="Slow 3G" width="456" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do not forget to tick the &lt;em&gt;Disable cache&lt;/em&gt; checkbox if you want to simulate a first connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  6 - Replay a request
&lt;/h2&gt;

&lt;p&gt;Suppose that there is a request that ends in error in your application. In order to understand why, you would like to be able to replay this request and/or modify its content.&lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;Network&lt;/em&gt; tab, you can right-click on a request and there are several options :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3c7ol31ssaxlq4z1j7vg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3c7ol31ssaxlq4z1j7vg.png" alt="Copy as fetch" width="765" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the error came form the server, you will appreciate the &lt;em&gt;Replay XHR&lt;/em&gt; for a quick retry after fixing the problem.&lt;/p&gt;

&lt;p&gt;You can also copy it to any format and modify it before replaying it. The easiest one is &lt;em&gt;Copy as Fetch&lt;/em&gt; : it will generate the code to reproduce the request and copy it to the clipboard, you can then paste it in the &lt;em&gt;Console&lt;/em&gt; tab : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8x7x6mx19jyndutus41o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8x7x6mx19jyndutus41o.png" alt="Copy fetch" width="663" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can modify any parameters you want and see if the problem still occurs.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;7 - Lighthouse
&lt;/h2&gt;

&lt;p&gt;The most important one in my humble opinion ! The &lt;em&gt;Lighthouse&lt;/em&gt; tab offers a free audit of your website.&lt;/p&gt;

&lt;p&gt;As simple as can be, just click on the &lt;em&gt;Generate report&lt;/em&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6ul26dik5ygevp95vn7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6ul26dik5ygevp95vn7.png" alt="Lighthouse generate report" width="700" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lighthouse will run a battery of tests concerning performance, accessibility, best practices, SEO and progressive webapps.&lt;/p&gt;

&lt;p&gt;First, it will give you some marks for each category :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmwooujv9s1ujkfr1a3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmwooujv9s1ujkfr1a3s.png" alt="Lighthouse marks" width="499" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is neat because it will make you want to get a 100%.&lt;/p&gt;

&lt;p&gt;But more important, it gives detailed advices on every detected problem : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo53i3hz8hmac5e6esrvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo53i3hz8hmac5e6esrvq.png" alt="Lighthouse image size" width="642" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, it is advised to set explicit &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes on images. The &lt;em&gt;Learn more&lt;/em&gt; link gives a detailed explanation on why it is important and how to fix it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt; : if you have problems with your images' weight, take a look at &lt;a href="https://squoosh.app/"&gt;Squoosh&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;8 - Export the Network tab
&lt;/h2&gt;

&lt;p&gt;This one is essential if you are working with a dedicated test team. Suppose that a tester filed a bug report but you do not understand what the tester actually did.&lt;/p&gt;

&lt;p&gt;You probably already know that the &lt;em&gt;Network&lt;/em&gt; tab allows you to see the executed requests with all the details concerning : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requested URL&lt;/li&gt;
&lt;li&gt;The request method (&lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt; etc)&lt;/li&gt;
&lt;li&gt;Request headers&lt;/li&gt;
&lt;li&gt;Request body&lt;/li&gt;
&lt;li&gt;Response headers&lt;/li&gt;
&lt;li&gt;Status code
And so on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But did you know that you could export/import the content of this tab ?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5j6morkxx4ytzdlthvsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5j6morkxx4ytzdlthvsj.png" alt="HAR export" width="712" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the export button and you will get an &lt;a href="https://fr.wikipedia.org/wiki/Format_HTTP_Archive"&gt;HAR&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;You can then later reimport this file using the &lt;em&gt;Import&lt;/em&gt; icon located just next to the &lt;em&gt;Export&lt;/em&gt; icon (or drag the HAR file in the &lt;em&gt;Request&lt;/em&gt; tab directly, which is even cooler). You then have a complete trace of what the tester did along with all the request details.&lt;/p&gt;

&lt;h2&gt;
  
  
  9 - New : the Flexbox debugging tool !
&lt;/h2&gt;

&lt;p&gt;Note : this feature is recent and things are still changing. Even the &lt;a href="https://developer.chrome.com/blog/new-in-devtools-90/#flexbox"&gt;Official documentation&lt;/a&gt; might not be up to date&lt;/p&gt;

&lt;p&gt;As it is a quite recent feature, you might have to activate it in the &lt;em&gt;Experiments&lt;/em&gt; sections of Chrome settings.&lt;/p&gt;

&lt;p&gt;Open Chrome settings :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyujlraednfwcwrpyihe2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyujlraednfwcwrpyihe2.png" alt="Devtools preferences" width="701" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, in the &lt;em&gt;Experiments&lt;/em&gt; section, check &lt;em&gt;Enable new CSS Flexbox debugging features&lt;/em&gt; (you might need to scroll down to find it) :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftec86azou6b7cy9qi8fk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftec86azou6b7cy9qi8fk.png" alt="Flexbox - activate experiment" width="578" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might get a warning message with a button to reload DevTools&lt;/p&gt;

&lt;p&gt;Now, in the &lt;em&gt;Elements&lt;/em&gt; tab, every DOM element that has &lt;code&gt;display&lt;/code&gt; value of &lt;code&gt;flex&lt;/code&gt;, &lt;code&gt;inline-flex&lt;/code&gt; or &lt;code&gt;grid&lt;/code&gt;, you can see a &lt;code&gt;flex&lt;/code&gt; or &lt;code&gt;grid&lt;/code&gt; badge. Click on it to toggle the display of an overlay on the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdwssv23okf4dfnh2uhl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdwssv23okf4dfnh2uhl.png" alt="Flexbox - badge" width="476" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can try it on Google !&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1qyacvpcu4t440d1kh3c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1qyacvpcu4t440d1kh3c.png" alt="Flexbox Google" width="360" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An overlay appears, showing the position of the elements. Also, in the &lt;em&gt;Elements&lt;/em&gt; tab, there is a &lt;em&gt;Layout&lt;/em&gt; tab that has now a &lt;em&gt;Flexbox&lt;/em&gt; section where you can activate/deactivate the overlay each element :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ewv9gtbjkt2sa2oa67c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ewv9gtbjkt2sa2oa67c.png" alt="Flexbox checkboxes" width="635" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, a panel appears in the Style tab. This panel allows you to quickly try different display options :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lfn0799wc1gk7r5enfm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lfn0799wc1gk7r5enfm.png" alt="Display flex" width="317" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Chrome DevTools contains dozens of useful features but I decided to show only the ones I use the most.&lt;/p&gt;

&lt;p&gt;I hope those tips will make your debugging sessions easier and help you becoming a better developer.&lt;/p&gt;

&lt;p&gt;You can follow me on &lt;a href="https://twitter.com/ArnaudDenoyelle"&gt;Twitter&lt;/a&gt; in order to know when future articles come. Also, tell me which feature helped you the most !&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>devtools</category>
      <category>javascript</category>
      <category>html</category>
    </item>
  </channel>
</rss>
