Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preferred method of using normalize.css? #364

Closed
drwpow opened this issue Dec 8, 2016 · 27 comments
Closed

Preferred method of using normalize.css? #364

drwpow opened this issue Dec 8, 2016 · 27 comments

Comments

@drwpow
Copy link

drwpow commented Dec 8, 2016

What is the ideal way to load normalize.css (ideally from NPM) in a performant way? I’d like to avoid loading it as a static asset and introduce a header request just for a tiny bit of CSS.

Glamor has a glamor/reset extra, but it’s a lot simpler than normalize, and not what I’m looking for (I’m not really sure how to load extras into Glamor from next anyway).

@nkzawa
Copy link
Contributor

nkzawa commented Dec 9, 2016

You can use next/head.

@drwpow
Copy link
Author

drwpow commented Dec 9, 2016

@nkzawa I’ve used next/head to load some global syles, but without css-loader on the project, how could I require a CSS file from node_modules? And is this cacheable on the user end or does this bloat out the payload every header request?

@nkzawa
Copy link
Contributor

nkzawa commented Dec 9, 2016

You'd like to define style as text in next/head like:

<Head>
  <style>{`
    body {
      margin: 0;
    }
  `}</style>
</Head>

You'd have to convert normalize.css to .json or a component to require, but this would be the best way for now IMO. If you require the file on all pages, then it bundles as a chunk and is loaded only once so it wouldn't bloat payload.

You'd be able to use css-loader too when #222 was released.

@drwpow
Copy link
Author

drwpow commented Dec 9, 2016 via email

@FrancosLab
Copy link

Would like to point out that glamor actually uses normalize.css albeit an outdated version v3.0.2
https://github.com/threepointone/glamor/blob/master/src/reset.js

Made a pull request
threepointone/glamor#154

Simply importing import 'glamor/reset' works fine.

Feel free to use my fork if you need 5.0 or wait for the pull request to be merged :)

@drwpow
Copy link
Author

drwpow commented Dec 13, 2016

@FrancosLab Thanks for the tip! I ran across glamor/reset but didn’t notice normalize was part of it—I don’t think it was mentioned on glamor’s README. Thanks for the PR!

@migueloller
Copy link
Contributor

migueloller commented Feb 23, 2017

So what is the best way to do this right now for next@2.0.0-beta.32? I've spent various hours trying to emulate what was done with the with-global-stylesheet example with no luck.

Because normalize.css is a package, simply copying the file isn't enough (Node's require resolution uses package.main). Moreover, emit-file-loader (and file-loader as well) seems to be behaving differently from the example repo. It seems that when passing the options name=dist/[path][name].[ext] to the loader, path always starts with -, resulting in the file being in .next/dist/-/node_modules/normalize.css/normalize.css, which is a problem.

The way to get around this is to basically copy the entire normalize.css file into the static folder or perhaps inline the entire thing into a style tag (I'm using styled components for styling, though).

I tried using webpack-copy-plugin but it looks like the static folder isn't served from .next but actually from the root folder itself <root-folder>/static (where pages lives) so that didn't work either.

Now that Next.js doesn't rely on Glamor, any tips on moving forward with this?

EDIT: Related: vercel/styled-jsx#83, vercel/styled-jsx#100, #544

@migueloller
Copy link
Contributor

The with-global-stylesheet example just got updated here: #1327!

@migueloller
Copy link
Contributor

#1327 still doesn't work for something as simple as import 'normalize.css'. The main issue seems to be that because Webpack doesn't run on the server, you can't import non-js files on any file that runs in the server.

@sedubois
Copy link
Contributor

sedubois commented Mar 2, 2017

@migueloller maybe could switch to universal Webpack after v2.0...: #1245

@migueloller
Copy link
Contributor

@sedubois, eagerly waiting for that! 😄

@sedubois
Copy link
Contributor

sedubois commented Mar 2, 2017

you can add your vote there 😉

@orlin
Copy link
Contributor

orlin commented Mar 2, 2017

Guys, I've been importing normalize just fine through sass-loader, even without the includePaths that just got merged. All you have to do is install normalize-scss (the Sass port of normalize.css) and add @import '~normalize-scss'; at your highest level (custom _document, layout, or page) where you would include an scss stylesheet the way with-global-stylesheet does.

Now if you rather import the original, I bet you could setup an alias to node_modulesusing babel-plugin-module-resolver the way I just did with styles in the example and then import it with js + <style dangerouslySetInnerHTML={{ __html: normalize }} />.

@migueloller
Copy link
Contributor

@orlin, you can't simply import it with JS because it will throw an error in the server since it doesn't go through Webpack.

@orlin
Copy link
Contributor

orlin commented Mar 2, 2017

@migueloller, it should work fine, the same way scss is imported from js in the with-global-stylesteet example. Both css and scss are handled by Webpack loaders in the next.config.js and converted to js. I just didn't provide the import normalize from '...' as I would need to install normalize.css and setup a babel-plugin-module-resolver alias to give you a ... path that works.

@migueloller
Copy link
Contributor

@orlin,

I've cloned the example, added normalize.css, and played with it a bit. You're right, it's possible to make it work!

I had to make a custom configuration for it though, where the output name of the emitted file was dist/[path]index.js due to the fact that if you don't copy the package.json then Node's require won't find it. Because you don't want this behavior for the other styles (living in your source code and not node_modules) then you have to setup a Webpack rule just for normalize.css (plus other packages you might be using).

This works as a short-term fix but it would definitely be nice to have something that works out of the box as is being discussed in #1245 and vercel/styled-jsx#100 (comment)

@rauchg, do you think it would be a good idea to make an example for packages that exist in node_modules? I wouldn't mind making a new example or extending the with-global-stylesheet one.

@rauchg
Copy link
Member

rauchg commented Mar 2, 2017

@migueloller adding it to the same example would probably be preferable

@orlin
Copy link
Contributor

orlin commented Mar 3, 2017

@migueloller I found a super-clean "best-practices" way to do this. Will do a PR on with-global-stylesheet... I hope you didn't spend too much time hacking it.

@jaydenseric
Copy link
Contributor

Global styles, including resets or normalize, are an anti-pattern anyway. Components should control their own styles. Normalize is the jQuery of CSS.

@btnwtn
Copy link

btnwtn commented Apr 9, 2017

@jaydenseric you're correct that Normalize.css is the jQuery of CSS. Browsers are still pretty inconsistent in their default styling of HTML elements, Normalize.css helps deal with that problem. Normalize.css is a necessity for legacy browser support for modern projects.

@vinzcelavi
Copy link

vinzcelavi commented Mar 1, 2018

Here is the approach I use : (https://github.com/zeit/next.js/#custom-document)

// ./pages/_document.js
import Document, { Head, Main, NextScript } from 'next/document'
import flush from 'styled-jsx/server'

export default class MyDocument extends Document {
  static getInitialProps({ renderPage }) {
    const { html, head, errorHtml, chunks } = renderPage()
    const styles = flush()
    return { html, head, errorHtml, chunks, styles }
  }

  render() {
    return (
      <html>
        <Head>
          <title>My page</title>
          <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css" />
        </Head>
        <body className="custom_class">
          {this.props.customValue}
          <Main />
          <NextScript />
        </body>
      </html>
    )
  }
}

@sospedra
Copy link
Contributor

@vinzcelavi Why do you flush the styles?

@vinzcelavi
Copy link

@sospedra I have no idea 😬 Maybe it could help : https://github.com/zeit/styled-jsx#styled-jsxserver

@timneutkens
Copy link
Member

You probably don't want to do that but instead call Document.getInitialProps as per the updated documentation: https://github.com/zeit/next.js/#custom-document

@janoist1
Copy link

janoist1 commented Dec 4, 2018

Why isn't it just fine placing a link tag with the CDN url inside the Head? It worked for me.

@IAmNatch
Copy link

IAmNatch commented Mar 8, 2019

@janoist1 I think the problem here is that we’d like to serve normalize ourselves from next, rather then relying on an external CDN. It’s fine in development, but I don’t want to rely on anything external in production.

@transitive-bullshit
Copy link

Here are two ways of solving this if using next-css isn't an option for you (perhaps you're using CSS modules so importing a CSS file from _app won't apply globally).

We first include a link inside the Head for normalize.css and then apply some custom global styles via <style type='text/css'>{globalStyles}</style>

import React from 'react'
import Document, { Head, Main, NextScript } from 'next/document'

const globalStyles = `
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
`

export default class MyDocument extends Document {
  render () {
    return (
      <html>
        <Head>
          <meta name='viewport' content='width=device-width, initial-scale=1' />
          <meta charSet='utf-8' />

          <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css' />

          <style type='text/css'>{globalStyles}</style>
        </Head>

        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    )
  }
}

ijjk pushed a commit to ijjk/next.js that referenced this issue Apr 13, 2019
* On hover prefetch

* Fix onHover prefetch

* Upgrade Next.js to latest canary
@lock lock bot locked as resolved and limited conversation to collaborators Mar 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests