<p dir="auto"><strong>Now-2</strong> and <strong><a class="issue-link js-issue-link notranslate" rel="noopener noreferrer nofollow" href="https://linear.app/vercel/issue/NEXT-8">Next-8</a></strong> require us to drop <code class="notranslate">server.js</code>-based approach to serve SSR in production, and replace it with lambdas and route configs. I fully understand the reasoning behind this and I don't question it. Hovewer, the <code class="notranslate">server.js</code> file was useful not only to apply routing but to inject middlewares! Middlewares were necessary, for example, to fix a bunch of annoying problems with React.</p>
<ol dir="auto">
<li>React title encodes HTML entities</li>
</ol>
<p dir="auto"><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="369521758" data-permission-text="Title is private" data-url="https://github.com/facebook/react/issues/13838" data-hovercard-type="issue" data-hovercard-url="/facebook/react/issues/13838/hovercard" href="https://github.com/facebook/react/issues/13838">facebook/react#13838</a><br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="76405731" data-permission-text="Title is private" data-url="https://github.com/facebook/react/issues/3879" data-hovercard-type="issue" data-hovercard-url="/facebook/react/issues/3879/hovercard" href="https://github.com/facebook/react/issues/3879">facebook/react#3879</a></p>
<p dir="auto">See fix-1 below.</p>
<ol start="2" dir="auto">
<li>Linebreaks in meta tags and stuff like that</li>
</ol>
<p dir="auto">See fix-2 below.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import Express from &quot;express&quot;
import Interceptor from &quot;express-interceptor&quot;
import {AllHtmlEntities} from &quot;html-entities&quot;

let ent = new AllHtmlEntities()
let metaContentFixer = Interceptor((req, res) =&gt; ({
  isInterceptable() {
    return /text\/html/.test(res.get(&quot;Content-Type&quot;))
  },
  intercept(body, send) {
    send(normalizeHTML(body.toString()))
  }
}))

app
  .prepare()
  .then(() =&gt; {
    let server = Express()
    server.use(metaContentFixer)
    ...
  })

function normalizeHTML(html) {
  return html
    // Fix SEO title
    .replace(/&lt;title[^&gt;]*&gt;([^&lt;]*)&lt;\/title&gt;/, (match, content) =&gt; {
      return match.replace(content, ent.decode(content))
    }) // fix-1
    // Remove linebreaks in meta contents
    .replace(/content=&quot;([^&quot;]+)&quot;/g, (match, content) =&gt; {
      return `content=&quot;${ent.decode(content).replace(/(\r\n|\n|\r)+/g, &quot; &quot;)}&quot;`
    }) // fix-2
}"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-v">Express</span> <span class="pl-k">from</span> <span class="pl-s">"express"</span>
<span class="pl-k">import</span> <span class="pl-v">Interceptor</span> <span class="pl-k">from</span> <span class="pl-s">"express-interceptor"</span>
<span class="pl-k">import</span> <span class="pl-kos">{</span><span class="pl-v">AllHtmlEntities</span><span class="pl-kos">}</span> <span class="pl-k">from</span> <span class="pl-s">"html-entities"</span>

<span class="pl-k">let</span> <span class="pl-s1">ent</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">AllHtmlEntities</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
<span class="pl-k">let</span> <span class="pl-s1">metaContentFixer</span> <span class="pl-c1">=</span> <span class="pl-v">Interceptor</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-s1">req</span><span class="pl-kos">,</span> <span class="pl-s1">res</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-en">isInterceptable</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-pds"><span class="pl-c1">/</span>text<span class="pl-cce">\/</span>html<span class="pl-c1">/</span></span><span class="pl-kos">.</span><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s1">res</span><span class="pl-kos">.</span><span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-s">"Content-Type"</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-en">intercept</span><span class="pl-kos">(</span><span class="pl-s1">body</span><span class="pl-kos">,</span> <span class="pl-s1">send</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">send</span><span class="pl-kos">(</span><span class="pl-en">normalizeHTML</span><span class="pl-kos">(</span><span class="pl-s1">body</span><span class="pl-kos">.</span><span class="pl-en">toString</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span>

<span class="pl-s1">app</span>
  <span class="pl-kos">.</span><span class="pl-en">prepare</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
  <span class="pl-kos">.</span><span class="pl-en">then</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-s1">server</span> <span class="pl-c1">=</span> <span class="pl-v">Express</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
    <span class="pl-s1">server</span><span class="pl-kos">.</span><span class="pl-en">use</span><span class="pl-kos">(</span><span class="pl-s1">metaContentFixer</span><span class="pl-kos">)</span>
    <span class="pl-kos">.</span><span class="pl-kos">.</span><span class="pl-kos">.</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span>

<span class="pl-k">function</span> <span class="pl-en">normalizeHTML</span><span class="pl-kos">(</span><span class="pl-s1">html</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-s1">html</span>
    <span class="pl-c">// Fix SEO title</span>
    <span class="pl-kos">.</span><span class="pl-en">replace</span><span class="pl-kos">(</span><span class="pl-pds"><span class="pl-c1">/</span>&lt;title<span class="pl-kos">[</span>^&gt;<span class="pl-kos">]</span><span class="pl-c1">*</span>&gt;<span class="pl-kos">(</span><span class="pl-kos">[</span>^&lt;<span class="pl-kos">]</span><span class="pl-c1">*</span><span class="pl-kos">)</span>&lt;<span class="pl-cce">\/</span>title&gt;<span class="pl-c1">/</span></span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">match</span><span class="pl-kos">,</span> <span class="pl-s1">content</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-s1">match</span><span class="pl-kos">.</span><span class="pl-en">replace</span><span class="pl-kos">(</span><span class="pl-s1">content</span><span class="pl-kos">,</span> <span class="pl-s1">ent</span><span class="pl-kos">.</span><span class="pl-en">decode</span><span class="pl-kos">(</span><span class="pl-s1">content</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c">// fix-1</span>
    <span class="pl-c">// Remove linebreaks in meta contents</span>
    <span class="pl-kos">.</span><span class="pl-en">replace</span><span class="pl-kos">(</span><span class="pl-pds"><span class="pl-c1">/</span>content="<span class="pl-kos">(</span><span class="pl-kos">[</span>^"<span class="pl-kos">]</span><span class="pl-c1">+</span><span class="pl-kos">)</span>"<span class="pl-c1">/</span>g</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">match</span><span class="pl-kos">,</span> <span class="pl-s1">content</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-s">`content="<span class="pl-s1"><span class="pl-kos">${</span><span class="pl-s1">ent</span><span class="pl-kos">.</span><span class="pl-en">decode</span><span class="pl-kos">(</span><span class="pl-s1">content</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">replace</span><span class="pl-kos">(</span><span class="pl-pds"><span class="pl-c1">/</span><span class="pl-kos">(</span><span class="pl-cce">\r</span><span class="pl-cce">\n</span><span class="pl-c1">|</span><span class="pl-cce">\n</span><span class="pl-c1">|</span><span class="pl-cce">\r</span><span class="pl-kos">)</span><span class="pl-c1">+</span><span class="pl-c1">/</span>g</span><span class="pl-kos">,</span> <span class="pl-s">" "</span><span class="pl-kos">)</span><span class="pl-kos">}</span></span>"`</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c">// fix-2</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">You can say "meh, it's just React bugs". The problem is that such bugs can be very long-lasting and quite detremental to SEO (ruining og attributes for example).</p>
<p dir="auto">And the list of such issues can be expanded. Not necessary NextJS-related but I remember fixing HTML after ReactRouter + Helmet and so on. The bottom line is that similar issues and answers like "You can only fix it in HTML" are regular at StackOverflow.</p>
<p dir="auto"><code class="notranslate">server.js</code> allowed us to inject whatever middlewares we wanted. Unless I miss something, <strong>Now-2 + <a class="issue-link js-issue-link notranslate" rel="noopener noreferrer nofollow" href="https://linear.app/vercel/issue/NEXT-8">Next-8</a> do not leave any option to apply custom middlewares</strong>. It's quite a limitation, you know.</p>
<p dir="auto">I'm trying out next.js but for my specific needs I want to use external CSS file, e.g. from CDN. It's utility belt which provides a lot of useful classes in the app. I've tried adding it in <code class="notranslate">Head</code> component like:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import React from 'react';
import Head from 'next/head';

export default () =&gt; (
  &lt;div&gt;
    &lt;Head&gt;
      &lt;link href=&quot;//unpkg.com/contrabass.css@1.0.4/dist/contrabass.min.css&quot; rel=&quot;stylesheet&quot; /&gt;
    &lt;/Head&gt;
  &lt;/div&gt;
);"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-v">React</span> <span class="pl-k">from</span> <span class="pl-s">'react'</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-v">Head</span> <span class="pl-k">from</span> <span class="pl-s">'next/head'</span><span class="pl-kos">;</span>

<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">(</span>
  <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
    <span class="pl-c1">&lt;</span><span class="pl-ent">Head</span><span class="pl-c1">&gt;</span>
      <span class="pl-c1">&lt;</span><span class="pl-ent">link</span> <span class="pl-c1">href</span><span class="pl-c1">=</span><span class="pl-s">"//unpkg.com/contrabass.css@1.0.4/dist/contrabass.min.css"</span> <span class="pl-c1">rel</span><span class="pl-c1">=</span><span class="pl-s">"stylesheet"</span> <span class="pl-c1">/</span><span class="pl-c1">&gt;</span>
    <span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">Head</span><span class="pl-c1">&gt;</span>
  <span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">but everytime when switching between pages with <code class="notranslate">Link</code> element I see styles blinking - I assume due to loading this css file after the page rendered.</p>
<p dir="auto">I've also tried to load CSS once when returned from server like:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function addExternalCSS (href, id, media = 'all') {
  if (document.getElementById(id)) {
    return;
  }

  const head  = document.getElementsByTagName('head')[0];
  const link  = document.createElement('link');

  link.id   = id;
  link.rel  = 'stylesheet';
  link.type = 'text/css';
  link.href = href;
  link.media = media;

  head.appendChild(link);
}

(function () {
  if (typeof document === 'undefined') {
    return;
  }

  addExternalCSS('//unpkg.com/contrabass.css@1.0.4/dist/contrabass.min.css', 'contrabass');
})();"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">addExternalCSS</span> <span class="pl-kos">(</span><span class="pl-s1">href</span><span class="pl-kos">,</span> <span class="pl-s1">id</span><span class="pl-kos">,</span> <span class="pl-s1">media</span> <span class="pl-c1">=</span> <span class="pl-s">'all'</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementById</span><span class="pl-kos">(</span><span class="pl-s1">id</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-k">const</span> <span class="pl-s1">head</span>  <span class="pl-c1">=</span> <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">getElementsByTagName</span><span class="pl-kos">(</span><span class="pl-s">'head'</span><span class="pl-kos">)</span><span class="pl-kos">[</span><span class="pl-c1">0</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
  <span class="pl-k">const</span> <span class="pl-s1">link</span>  <span class="pl-c1">=</span> <span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'link'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

  <span class="pl-s1">link</span><span class="pl-kos">.</span><span class="pl-c1">id</span>   <span class="pl-c1">=</span> <span class="pl-s1">id</span><span class="pl-kos">;</span>
  <span class="pl-s1">link</span><span class="pl-kos">.</span><span class="pl-c1">rel</span>  <span class="pl-c1">=</span> <span class="pl-s">'stylesheet'</span><span class="pl-kos">;</span>
  <span class="pl-s1">link</span><span class="pl-kos">.</span><span class="pl-c1">type</span> <span class="pl-c1">=</span> <span class="pl-s">'text/css'</span><span class="pl-kos">;</span>
  <span class="pl-s1">link</span><span class="pl-kos">.</span><span class="pl-c1">href</span> <span class="pl-c1">=</span> <span class="pl-s1">href</span><span class="pl-kos">;</span>
  <span class="pl-s1">link</span><span class="pl-kos">.</span><span class="pl-c1">media</span> <span class="pl-c1">=</span> <span class="pl-s1">media</span><span class="pl-kos">;</span>

  <span class="pl-s1">head</span><span class="pl-kos">.</span><span class="pl-en">appendChild</span><span class="pl-kos">(</span><span class="pl-s1">link</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-kos">(</span><span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-k">typeof</span> <span class="pl-smi">document</span> <span class="pl-c1">===</span> <span class="pl-s">'undefined'</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>

  <span class="pl-en">addExternalCSS</span><span class="pl-kos">(</span><span class="pl-s">'//unpkg.com/contrabass.css@1.0.4/dist/contrabass.min.css'</span><span class="pl-kos">,</span> <span class="pl-s">'contrabass'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">But this approach has downside on big initial styles blink due to waiting while file is downloaded and parsed by browser.</p>
<p dir="auto">Do you have some pieces of advice how to work with external CSS files and do not have these weird style blinks?</p>