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).
You can use next/head
.
@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?
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 https://github.com/zeit/next.js/pull/222 was released.
Thanks. This is what I figured, but didn’t know if there was a more automatic way of loading it currently. I guess I could run Webpack or Gulp locally to convert before next hits it.
And that’s good to know that next utilizes common chunking. I feel better about shoving stuff into the Head now. Thanks for answering my questions!
On Dec 9, 2016, at 01:11, Naoyuki Kanezawa notifications@github.com wrote:
You'd like to define style as text in next/head like:
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.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.
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
https://github.com/threepointone/glamor/pull/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 :)
@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!
So what is the best way to do this right now for [email protected]
? 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: https://github.com/zeit/styled-jsx/issues/83, https://github.com/zeit/styled-jsx/pull/100, https://github.com/zeit/next.js/issues/544
The with-global-stylesheet
example just got updated here: #1327!
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.@migueloller maybe could switch to universal Webpack after v2.0...: https://github.com/zeit/next.js/issues/1245
@sedubois, eagerly waiting for that! 😄
you can add your vote there 😉
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_modules
using babel-plugin-module-resolver
the way I just did with styles
in the example and then import it with js + <style dangerouslySetInnerHTML={{ __html: normalize }} />
.
@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.
@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.
@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 https://github.com/zeit/styled-jsx/pull/100#issuecomment-277133969
@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.
@migueloller adding it to the same example would probably be preferable
@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.
Global styles, including resets or normalize, are an anti-pattern anyway. Components should control their own styles. Normalize is the jQuery of CSS.
@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.
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>
)
}
}
@vinzcelavi Why do you flush the styles?
@sospedra I have no idea 😬 Maybe it could help : https://github.com/zeit/styled-jsx#styled-jsxserver
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
Why isn't it just fine placing a link
tag with the CDN url inside the Head
? It worked for me.
@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.
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>
)
}
}
Most helpful comment
@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.