Issue 1:
Now-2 and Next-8 require us to drop server.js-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 server.js 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.

React title encodes HTML entities

facebook/react#13838

facebook/react#3879

See fix-1 below.

Linebreaks in meta tags and stuff like that

See fix-2 below.

import Express from "express"
import Interceptor from "express-interceptor"
import {AllHtmlEntities} from "html-entities"

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

app
.prepare()
.then(() => {
let server = Express()
server.use(metaContentFixer)
...
})

function normalizeHTML(html) {
return html
// Fix SEO title
.replace(/<title[^>]*>([^<]*)<\/title>/, (match, content) => {
return match.replace(content, ent.decode(content))
}) // fix-1
// Remove linebreaks in meta contents
.replace(/content="([^"]+)"/g, (match, content) => {
return `content="${ent.decode(content).replace(/(\r\n|\n|\r)+/g, " ")}"`
}) // fix-2
}

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).

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.

server.js allowed us to inject whatever middlewares we wanted. Unless I miss something, Now-2 + Next-8 do not leave any option to apply custom middlewares. It's quite a limitation, you know.

Issue 2:
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 Head component like:

import React from 'react';
import Head from 'next/head';

export default () => (
<div>
<Head>
<link href="//unpkg.com/contrabass.css@1.0.4/dist/contrabass.min.css" rel="stylesheet" />
</Head>
</div>
);

but everytime when switching between pages with Link element I see styles blinking - I assume due to loading this css file after the page rendered.

I've also tried to load CSS once when returned from server like:

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');
})();

But this approach has downside on big initial styles blink due to waiting while file is downloaded and parsed by browser.

Do you have some pieces of advice how to work with external CSS files and do not have these weird style blinks?