question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Extracted static stylesheet file into header

See original GitHub issue

Many issues are trying to solve extracting CSS file as separate link for production env. Eg: #1479 #1396 #1615

There is another solution what is works, and is quite elegant. (maybe isn’t 😄 ) This solution works for Next v3 beta and Docker. My source directory is src and build directory is one level up .next. We are using separated style files in /style directory with index.css where are all css files imported.

Required Webpack plugins and loaders

  • extract-text-webpack-plugin
  • css-loader
  • raw-loader
  • postcss-loader

next.config.js

const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  distDir: '../.next',
  webpack: (config, { dev }) => {
    config.module.rules.push({
      test: /\.css$/,
      loader: 'emit-file-loader',
      options: {
        name: 'dist/[path][name].[ext]'
      }
    });

    if (!dev) {
      config.module.rules.push({
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          use: [
            {
              loader: 'css-loader',
              options: {
                importLoaders: 2,
                modules: false,
                url: true,
                sourceMap: false,
                minimize: true,
                localIdentName: false
                  ? '[name]-[local]-[hash:base64:5]'
                  : '[hash:base64:5]'
              }
            },
            { loader: 'postcss-loader' }
          ]
        })
      });

      config.plugins.push(new ExtractTextPlugin('app.css'));
    } else {
      config.module.rules.push({
        test: /\.css$/,
        use: [{ loader: 'raw-loader' }, { loader: 'postcss-loader' }]
      });
    }

    return config;
  }
};

File is emitted in build directory and then is processed with css-loader and postcss-loader. After processing is extracted next to app.js file. Do not use babel-loader for global as in this example: https://github.com/zeit/next.js/tree/v3-beta/examples/with-global-stylesheet It is not neccessary and doesn’t work well with postcss-calc.

Docker

In dockerfile, copy generated app.css to static directory RUN mkdir src/static/styles && cp .next/app.css src/static/styles/app.css

Header link for production, style for development

pages/_document.js we also used React-Helmet, so this example is

import Document, { Head, Main, NextScript } from 'next/document';
import stylesheet from '../styles/index.css';

export default class extends Document {
  render() {
    return (
      <html>
        <Head>
          {process.env.NODE_ENV == 'production'
            ? <link
                rel="stylesheet"
                type="text/css" 
                href={`/static/styles/app.css?${this.props.__NEXT_DATA__
                  .buildStats['app.js'].hash}`}
              />
            : <style
                global
                dangerouslySetInnerHTML={{
                  __html: stylesheet
                }}
              />}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

Link to app.css is appended with querystring with same hash as is used in app.js path for disabling cache after redeploy.

What we can do better?

Next Server define route for production app.js file (https://github.com/zeit/next.js/blob/v3-beta/server/index.js#L151). This example should be more elegant if we can define route for app.css

Then this could be automated or at least we should have better links for app.css file. Ex:

<link
  rel="stylesheet"
  type="text/css"
  href={`/_next/${this.props.__NEXT_DATA__.buildStats['app.js'].hash}/app.css`}
/>

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:23
  • Comments:13 (6 by maintainers)

github_iconTop GitHub Comments

5reactions
trongthanhcommented, Aug 9, 2017

I’m also in need of this setup and this is the best solution so far. Below is my next.config.js in which:

  • Styles written in SASS / SCSS
  • Auto-prefixer with postcss (inlining the plugins settings)
  • In dev, I need source map, so I turn on the sourceMap: 'inline' at postcss-loader
  • I haven’t test the production outcome, but it’s just the idea.
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');

module.exports = {
    webpack: (config, { dev }) => {
        config.module.rules.push({
            test: /\.s?css$/,
            loader: 'emit-file-loader',
            options: {
                name: 'dist/[path][name].[ext]',
            },
        });

        if (!dev) {
            config.module.rules.push({
                test: /\.scss$/,
                use: ExtractTextPlugin.extract({
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                importLoaders: 2,
                                modules: false,
                                url: true,
                                sourceMap: false,
                                minimize: true,
                                localIdentName: false
                                    ? '[name]-[local]-[hash:base64:5]'
                                    : '[hash:base64:5]',
                            },
                        },
                        {
                            loader: 'postcss-loader',
                            options: {
                                sourceMap: true,
                                plugins: () => [
                                    autoprefixer(),
                                ],
                            },
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                sourceMap: true,
                                includePaths: [
                                    path.resolve(__dirname, 'scss'),
                                    path.resolve(__dirname, 'pages'),
                                ],
                            },
                        },
                    ],
                }),
            });

            config.plugins.push(new ExtractTextPlugin('app.css'));
        } else {
            config.module.rules.push({
                test: /\.scss$/,
                use: [
                    { loader: 'raw-loader' },
                    {
                        loader: 'postcss-loader',
                        options: {
                            sourceMap: 'inline',
                            plugins: () => [
                                autoprefixer(),
                            ],
                        },
                    },
                    {
                        loader: 'sass-loader',
                        options: { sourceMap: true },
                    },
                ],
            });
        }

        return config;
    },
};
3reactions
sheeruncommented, Dec 18, 2017

It is available only on custom document (in pages/_document.js), please see the README

Read more comments on GitHub >

github_iconTop Results From Across the Web

Extracted static stylesheet file into header · Issue #2534 - GitHub
We are using separated style files in /style directory with index.css where are all css files imported. Required Webpack plugins and loaders.
Read more >
Extracting only the css used in a specific page - Stack Overflow
UnCSS is a tool that removes unused CSS from your stylesheets. It works across multiple files and supports Javascript-injected CSS.
Read more >
Header and footer as templates in static html files - Reddit
Header and footer as templates in static html files. Hey guys, frequent reader here. I write mostly small static sites with HTML, CSS...
Read more >
How To Use Static Files in Gatsby | DigitalOcean
Tutorial Series: How To Create Static Web Sites with Gatsby.js ... First, you will extract the sample files to src/sample-assets , which you ......
Read more >
Static files in ASP.NET Core | Microsoft Learn
Static files, such as HTML, CSS, images, and JavaScript, are assets an ASP.NET Core app serves directly to clients by default.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found