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 · 100 comments

Comments

@matthewmueller
Copy link
Contributor

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Contributor Author

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

This comment has been minimized.

Copy link

commented Dec 28, 2016

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

This comment has been minimized.

Copy link

commented Dec 29, 2016

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

@kpuputti

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Jan 3, 2017

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

This comment has been minimized.

Copy link

commented Jan 6, 2017

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

This comment has been minimized.

Copy link

commented Jan 6, 2017

@viktorbezdek

This comment has been minimized.

Copy link

commented Jan 17, 2017

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

This comment has been minimized.

Copy link

commented Jan 19, 2017

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

@viktorbezdek

This comment has been minimized.

Copy link

commented Jan 20, 2017

@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

This comment has been minimized.

Copy link

commented Jan 21, 2017

@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

This comment has been minimized.

Copy link
Contributor

commented Jan 26, 2017

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

@matthewmueller

This comment has been minimized.

Copy link
Contributor Author

commented Jan 26, 2017

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

@viktorbezdek

This comment has been minimized.

Copy link

commented Jan 27, 2017

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

This comment has been minimized.

Copy link

commented Jan 27, 2017

@matthewmueller You are using CSS modules?

@abelovic

This comment has been minimized.

Copy link

commented Jan 27, 2017

@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

This comment has been minimized.

Copy link
Contributor

commented Jan 27, 2017

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link

commented Jan 27, 2017

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

@rauchg

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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.

@chibicode

This comment has been minimized.

Copy link
Contributor

commented Oct 23, 2017

I added an example using @stovmascript's solution:

#3157

@CHarnel

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Nov 16, 2017

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

@CHarnel

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Nov 16, 2017

@CHarnel try putting both in template string

@alanhr

This comment has been minimized.

Copy link

commented Nov 27, 2017

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

@comus

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link

commented Dec 11, 2017

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

@edmondnyaigoti

This comment has been minimized.

Copy link

commented Dec 12, 2017

@sheerun nice one ,thank you

@sheerun

This comment has been minimized.

Copy link
Contributor

commented Dec 13, 2017

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

@mihaiserban

This comment has been minimized.

Copy link

commented Jan 18, 2018

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Member

commented Feb 2, 2018

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

@nikolakanacki

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Member

commented Feb 2, 2018

@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

This comment has been minimized.

Copy link

commented Feb 2, 2018

@timneutkens Thank you!

@nikolakanacki

This comment has been minimized.

Copy link

commented Feb 5, 2018

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

@hopperhuang hopperhuang referenced this issue May 10, 2018
@rouxfeur

This comment has been minimized.

Copy link

commented Jun 9, 2018

Any news on this?

@timneutkens

This comment has been minimized.

Copy link
Member

commented Jun 9, 2018

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Dec 29, 2018

@comus

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.