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

Importing CSS files? #544

Closed
matthewmueller opened this issue Dec 27, 2016 · 102 comments
Closed

Importing CSS files? #544

matthewmueller opened this issue Dec 27, 2016 · 102 comments

Comments

@matthewmueller
Copy link
Contributor

matthewmueller commented Dec 27, 2016

Sometimes it's nice to break out your CSS into a separate .css file. I've tried to do the following:

pages/
└── index
    ├── index.css
    ├── index.js
    └── component.js

Then in the index.js, I've tried to do:

import css from './index.css'

And in next.config.js:

module.exports = {
  webpack: function (config) {
    config.module.loaders = (config.module.loaders || []).concat({
      test: /\.css$/, loader: 'raw'
    })
    return config
  }
}

But unfortunately, it keeps giving me:

 ERROR  Failed to compile with 1 errors

This dependency was not found in node_modules:

* ./index.css

Seems like it's not resolving to the right place for some reason, the local component.js works though via import component from './component.js', so I'm not sure what's going on here.

@nkzawa
Copy link
Contributor

nkzawa commented Dec 28, 2016

You mean this doesn't work on server ?
I think we don't have workaround for this yet. cc @arunoda

@matthewmueller
Copy link
Contributor Author

matthewmueller commented Dec 28, 2016

oh right, i guess there'd need to be a way for the webpack config in next.config.js to work on both sides in order for this to work.

@MikeDigitize
Copy link

I've got a kind of ballpark similar issue in that I just can't seem to get Next to play nicely with CSS or SASS. I have a components directory with standard React components in that I import into my pages but whenever I attempt to import in SASS (or CSS) files I get a ~"you need to use the appropriate loader for this file" type error message.

Generally in React I import SASS files and have Webpack compile using style, css and sass loaders. I've attempted to add these to the next.config.js file (and NPM installed them) but still get the same error message.

My next.config.js file:

module.exports = {
  webpack: (config, { dev }) => {
    config.module.rules.push({ test: /\.scss$/, loader: ['style-loader', 'css-loader', 'sass-loader'] });
    return config;
  }
}

Sorry if these questions sound dumb or I've missed something obvious in the docs that spell out the answers to them, but if anyone has a working example of importing / compiling SASS (or at the least CSS) into a component or a page with whatever's needed to add to the next.config.js to load / compile them, I'd massively appreciate it. Thanks!

@spacedragon
Copy link

I'm using css-modules-require-hook
to make css work.

@kpuputti
Copy link

kpuputti commented Jan 3, 2017

@spacedragon Do you have an example how to integrate css-modules-require-hook with Next.js? I'm having problems with getting it working.

@MikeDigitize
Copy link

I'm still having issues with getting SASS to compile if anyone could shed some light on how to do this or just import a CSS file within Next it would be appreciated (via a code example).

@MikeDigitize
Copy link

Interesting that the README file has been updated to remove the SVG loader example and changed to say adding loaders for file like SVG, CSS and SASS is discouraged. I'm not sure why inlined CSS is OK but imported CSS isn't but I'm sure there's a good reason why. I'm just currently uncertain about the best strategy to handle none JS defined / inlined CSS and SASS.

@kpuputti
Copy link

kpuputti commented Jan 6, 2017

@MikeDigitize See comment on #627 and #638 .

@viktorbezdek
Copy link

It's actually possible and pretty easy to process styles on server side.

directly in node:

require.extensions['.css'] = function(file) {
    console.log(file.id)
    return;
}

via babel register:

// from https://babeljs.io/docs/core-packages/babel-register/
require("babel-register")({
  // Optional ignore regex - if any filenames **do** match this regex then they
  // aren't compiled.
  ignore: /regex/,

  // Ignore can also be specified as a function.
  ignore: function(filename) {
    if (filename === '/path/to/es6-file.js') {
      return false;
    } else {
      return true;
    }
  },

  // Optional only regex - if any filenames **don't** match this regex then they
  // aren't compiled
  only: /my_es6_folder/,

  // Setting this will remove the currently hooked extensions of .es6, `.es`, `.jsx`
  // and .js so you'll have to add them back if you want them to be used again.
  extensions: [".es6", ".es", ".jsx", ".js"]
});

via webpack loaders:

I personally use isomorphic-style-loader as it allows me to inline critical CSS while rendering on server. Hot reloading and other DX related stuff works too. I'm not really fan of CSS in JS as it complicates using 3rd party components and and somehow takes away the C from CSS.

@noeljackson
Copy link

@viktorbezdek Have you successfully used isomorphic-style-loader with next.js?

@viktorbezdek
Copy link

@noeljackson Not really, but I intend to. Next.js looks promising and could save me lot of time if I make it work. Will look into it in next one or two weeks and submit pull request if I'm successful.

@noeljackson
Copy link

@viktorbezdek I will put a bounty on this one, as it's really crucial to a project I'm working on. I know I'm not inept, but I do not understand how to debug the babel transformations enough to figure this out. I've tried permutation of these ideas and nothing works 100%. I have been able to get raw-loader to pull in a data-encoded stylesheet using babel-plugin-webpack-loaders, but none of the style loaders work. Thanks for chiming in! :) Much appreciated.

@pencilcheck
Copy link
Contributor

Is there a solution to this? I would like to see a solution so I don't have to include css globally.

@matthewmueller
Copy link
Contributor Author

FWIW, I've just been putting my CSS files in the /static folder. Not great colocation, but not a huge deal either.

@viktorbezdek
Copy link

There will be a solution. I just didn't manage to finish it. I've locally very first prototype which seems to work, however it needs few hours to be finished. I'm pretty sure I'll be done after weekend. Stay tuned.

@viktorbezdek
Copy link

@matthewmueller You are using CSS modules?

@abelovic
Copy link

@viktorbezdek Thanks for working on this! CSS Modules support (or similar) is important for this project IMO. Styled jsx, is ok for simple situations but is hard to read for heavily styled components.

Would a babel plugin like this be an option (server side as well)? https://github.com/gajus/babel-plugin-react-css-modules

I tried to get this to work but but no luck :/

@stephenmathieson
Copy link
Contributor

I got CSS modules sort of working with babel-plugin-css-modules-transform. See my hacky example in my fork.

The downside is you have to kill the server & restart it every time you make a change to the CSS.

@mquandalle
Copy link

mquandalle commented Jan 27, 2017

Some React components expose default styling though a importable static resource. For instance to import the default style of https://github.com/react-component/slider one would use:

import 'rc-slider/assets/index.css';

It sure is possible to copy paste this stylesheet in the static/ directory but it won't stay in sync with the upstream style on a future component update, and it doesn't match what this component documentation recommend.

@rauchg
Copy link
Member

rauchg commented Jan 27, 2017

The problem is that those CSS files introduce global effects. We need to be able to capture the CSS and put it inside the React lifecycle, so that it gets unmounted, server-rendered, etc.

Many libraries do that, but I don't think it's a good pattern.

@mquandalle
Copy link

I'm not familiar with Zeit Next internals, but could some static analysis of the import be used to register/capture the CSS?

@rauchg
Copy link
Member

rauchg commented Jan 27, 2017

We could, but it would be really strange. Similar to something that's outside of render() magically inserting itself inside your component lifecycle.

@auser
Copy link

auser commented Jan 28, 2017

// Figured I'd share this for anyone else

Well... I just spent a bit too much time trying to hack CSS in here, BUT I landed on a solution that works (for me). Admittedly, it's a hack, but hot reloading works and so does server-side building.

Using (shudder) gulp, with this gulpfile (https://gist.github.com/auser/25e88e39d83413773c01f4c000ec2806) all **/*.scss files get concatenated together and shoved into a Styles component which I mount on the page as a "normal" element.

Hope this helps someone else until we can get true postcss support in next.

@brycejacobs
Copy link

brycejacobs commented Jan 30, 2017

Thanks for the hack @auser, I've been looking at the webpack config all day with no luck!

Edit:
Btw, you need to add a sass parser to the gulpfile!

@auser
Copy link

auser commented Jan 30, 2017

Yes and no... I just use the .scss extension as a way to differentiate pure css files from pre-compiled ones. Since postcss (with precss) mimics sass well enough, I don't have one. Feel free to edit for yourself with a sass parser.

@ghost
Copy link

ghost commented Jan 31, 2017

Seems like that is currently the best solution, using gulp to compile css file and build it inline or just even in /static if you don't mind not having hot reloading.

@CHarnel
Copy link

CHarnel commented Nov 16, 2017

How do you include more than one external css?
I use 2 libs that require it in the same component, each one works separately, but I don't know how to combine them.

import rtStyle from 'react-table/react-table.css';
import dpStyle from 'react-datepicker/dist/react-datepicker.css';
...
render() {
    return (
      <div>
        {/* <style jsx global>{ rtStyle }</style> */}
        <style jsx global>{ dpStyle }</style>
...

@almeynman
Copy link

almeynman commented Nov 16, 2017

@CHarnel try <style jsx global>{ rtStyle }{dpStyle}</style>

@CHarnel
Copy link

CHarnel commented Nov 16, 2017

@almeynman getting this:

Module build failed: SyntaxError: C:/.../components/activeUsersTable.js: 
Expected one child under JSX Style tag, but got 2 (eg: <style jsx>{`hi`}</style>)

@almeynman
Copy link

@CHarnel try putting both in template string

@alanhr
Copy link

alanhr commented Nov 27, 2017

@CHarnel try this approach
<style jsx global>{ ${rtStyle} ${dpStyle}}</style>

@comus
Copy link

comus commented Nov 30, 2017

@alanhr

i try to put those css in one js file and export it

import bootstrap from 'bootstrap/dist/css/bootstrap.min.css'
import styles from './index.css'

export default bootstrap + styles

and then just

import styles from '../styles'
...
<style jsx global>{styles}</style>

@sheerun
Copy link
Contributor

sheerun commented Dec 9, 2017

With https://github.com/sheerun/extracted-loader I've created you can use ExtractTextPlugin for both development and production, no need for different html in development or injecting css into js.

@CHarnel
Copy link

CHarnel commented Dec 11, 2017

@comus I used your approach, works good, thank you.

@edmondnyaigoti
Copy link

edmondnyaigoti commented Dec 12, 2017

@sheerun nice one ,thank you

@sheerun
Copy link
Contributor

sheerun commented Dec 13, 2017

I've submitted even more comprehensive example to next.js:
#3451

@mihaiserban
Copy link

This used to work before nextjs v4

<style jsx global>{style}</style> <style jsx global>{colors}</style> <style jsx global>{layout}</style>

What's the reason for using this aproach to load jsx global styles? <style jsx global>{ rtStyle }{dpStyle}</style>

@nikolakanacki
Copy link

nikolakanacki commented Feb 2, 2018

I've made myself a solution based on emit-files-loader. If anyone is interested I can post it here, but it relies on a custom server setup - basically you need to be able to statically serve single directory within .next build dir. It could probably be configured without a server by relying on the /_next/... path structure of the server.

Other than that you can write import stylesheet from './styles/style.[scss|less|stylus|w/e]'; and it will be the public path to your stylesheet file, so you can put it in a <link>. It includes ?[hash] for permanent caching and it does hot-reload.

@timneutkens
Copy link
Member

@nikolakanacki official support will be introduced very soon 🙏 #3578

@nikolakanacki
Copy link

nikolakanacki commented Feb 2, 2018

@timneutkens I've seen this one, is there an estimation on "very soon"? I see it's in canary already.
I just needed a solution right away, spent 2-3 days looking for one, and managed to write up my own which is basically an "easy fix". I'm even thinking about combining it with extract-text-webpack-plugin so one could statically join all the separate .[css|stylus|less|scss] files and have them all available as a single static resource like it normally would without next.

The main problem behind these issues I think is that there is a lot of "magic" going on in the background behind production and dev builds, with hot reloading and stuff... One could probably read the source and see how things are assembled together, but it would be awesome if someone who built it wrote some docs on that, I think more people could contribute.

@timneutkens
Copy link
Member

@nikolakanacki very soon 🙏 🤐

'm even thinking about combining it with extract-text-webpack-plugin so one could statically join all the separate .[css|stylus|less|scss] files and have them all available as a single static resource like it normally would without next.

The plugins that I wrote for next v5 already do this, they'll be open sourced soon 👍

Regarding writing docs on the internals, we're planning to document how everything works after v5 is out 🙏

@jameskennethrobinson
Copy link

@timneutkens Thank you!

@nikolakanacki
Copy link

@timneutkens thank you for the update, please post an update here when this thing lands!

@dhnm
Copy link

dhnm commented Jun 9, 2018

Any news on this?

@timneutkens
Copy link
Member

I'm not sure what other news you're expecting 🤔

This was released in Next.js v5.
It's even in the readme https://github.com/zeit/next.js#importing-css--sass--less--stylus-files

Also, the mentioned PR was merged and this issue is closed.

@nguyenvanphuc2203
Copy link

nguyenvanphuc2203 commented Oct 9, 2018

just create /static folder in root project, and put your file.css inside /static, then to Header html structure hock.

import Head from 'next/head';
<Head>
          <meta charset="utf-8" />
          <link rel="stylesheet" href="/static/css/custom.css" />
</Head>

and then use className anywhere!

@pavinduLakshan
Copy link

pavinduLakshan commented Dec 29, 2018

@comus

Much comprehensive and smart..thank you for this..I have been searching this kind of solution all day..

@mrpeski
Copy link

mrpeski commented Dec 1, 2019

just create /static folder in root project, and put your file.css inside /static, then to Header html structure hock.

import Head from 'next/head';
<Head>
          <meta charset="utf-8" />
          <link rel="stylesheet" href="/static/css/custom.css" />
</Head>

and then use className anywhere!

Create a 'public' folder in the root of your application(where package.json file is located).

@Timer
Copy link
Member

Timer commented Dec 1, 2019

Support is being added via #8626!

@vercel vercel locked as resolved and limited conversation to collaborators Dec 1, 2019
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