Giter VIP home page Giter VIP logo

Comments (7)

kachkaev avatar kachkaev commented on July 22, 2024 9

Here's one more discovery that might help those who have little CSS in style.css. That's the case when most of the styles come from styled-components or a similar framework. Turns out you can improve your website's performance by including the contents of .next/static/style.css directly into document, e.g. like this:

let style = null;
if (process.env.NODE_ENV === "production") {
  style = fs.readFileSync(`${process.cwd()}/.next/static/style.css`, "utf8");
}

// inside _document's Head:
{typeof style === "string" ? (
<style dangerouslySetInnerHTML={{ __html: style }} />
) : (
<link rel="stylesheet" href="/_next/static/style.css" />
)}

This helped me change the lighthouse performance score in production from 89 to 96 because First meaningful paint time decreased from 2.06 to 1.10 seconds. This is an advice in the original report that I followed:

screen shot 2018-03-26 at 11 31 08

When a stylesheet is heavy, it's cheaper to load it as a separate file and cache that request in the browser – this keeps the size of the server-rendered HTMLs small while avoiding extra round trips in consequent page requests. However, when style.css contains just normalize.css and a couple of simple global selectors, always keeping the entire stylesheet within the document's <head> and avoiding extra round trips appears to be a better thing. Obviously, caching is no longer a problem, because <style>{style}</style> is read from .next/static/style.css when your Next.js server starts.

Don't forget to import styles in a higher order component that works as a page wrapper:

# e.g. in hocs/page.js
import "./path/to/your/root/stylesheet.css"

Can this issue be considered as resolved?


If you want to check your website's performance, simply run

npm install --global lighthouse

lighthouse http://example.com/ --view

if ...style.css` screws up syntax highlighting in your editor, here's a trick:

let style = null;
if (process.env.NODE_ENV === "production") {
  // ${"css"} prevents editors from incorrectly highlighting code after css`
  style = readFileSync(`${process.cwd()}/.next/static/style.${"css"}`, "utf8");
}

from next-plugins.

Ehesp avatar Ehesp commented on July 22, 2024 6

I ended up doing the following in _document.js - this works for the time being, however we need to make sure the BUILD_ID is the same on a multi-deployment basis!

Note this builds from a src directory!

import Document, { Head, Main, NextScript } from 'next/document';
import { readFileSync } from 'fs';

let version = '';

if (process.env.NODE_ENV === 'production') {
  version = `?v=${readFileSync(`${process.cwd()}/src/.next/BUILD_ID`)}`;
}

export default class extends Document {
  render() {
    return (
      <html>
        <Head>
          <link rel="stylesheet" href={`/_next/static/style.css${version}`} />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    )
  }
}

from next-plugins.

kachkaev avatar kachkaev commented on July 22, 2024 5

It's also possible to use file's hash instead of BUILD_ID as version:

import { createHash } from "crypto";
import { readFileSync } from "fs";

// ...

let version = "";
if (process.env.NODE_ENV === "production") {
  const hash = createHash("sha256");
  hash.update(readFileSync(`${process.cwd()}/.next/static/style.css`));
  version = `?v=${hash.digest("hex").substr(0, 8)}`;
}

// ...

If the styles don't change between the builds, there's no need to download them and so everyone is better off.

In general, it's more efficient to calculate file cache using streams, but this should be unnecessary in our case. if .next/static/style.css is big enough to cause a hiccup during server setup, something is probably wrong 😃

crypto.createHash has been a part of Node's core nearly since the beginning of times, so there is no need to install a new module.


What are the caveats of this trick? If anyone sees them, could you please share?

from next-plugins.

kachkaev avatar kachkaev commented on July 22, 2024 2

Even though the workarounds in two previous comments solve the issue with style.css caching, all other static assets like images remain under the over-caching thread.

It'd be truly great to bring some webpack magic here! This would not only allow correct caching by turning paths into something like image.eld7hd4p.png, but would also make it possible to store images in folders with components. It's a bit of a shame that the images have to go to static in next.js, which separates them from a place where they really belong.

from next-plugins.

bryandowning avatar bryandowning commented on July 22, 2024 2

If you're going with the inlining approach, you may need to use:

<style dangerouslySetInnerHTML={{ __html: style }} />

Otherwise, things like quotes get converted to HTML entities.

from next-plugins.

kachkaev avatar kachkaev commented on July 22, 2024 2

Thank you @bryandowning, you are right! I updated the comment and removed <style>{{ style }}</style>.

from next-plugins.

timneutkens avatar timneutkens commented on July 22, 2024

Will be possible when vercel/next.js#4119 lands for Next 6

from next-plugins.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.