I want to expect styles from my modules to be compiled into the same stylesheet as my global styles. Please see demo setup below to understand where styles are being pulled from.
βββ pages
β βββ index.js
βββ components
β βββ Button
β β βββ index.js
β β βββ index.sass
βββ styles
β βββ index.sass (Global stylesheet with @imports)
Can't get both modules and global styles to work together in parallel. Only one of them can be used while the other cannot. Please see my comments in this demo repo in the files, _document.js and styles/index.sass
yarn && yarn dev_document.js and styles/index.sass to turn on and off behaviors._document.js, save, and you'll notice that module styles will be applied but not the global styles.
As stated in the above, I want the ability to use SASS modules within my components folder AND global styles in my styles folder together. As of right now I can either have styles from modules and NOT from my global stylesheet OR have styles from global stylesheet and not my modules.
The only work around I've found is including the path of a component's style inside my styles/index.sass file, like so:
@import '../components/Button/index'
The only issue with this is that the global stylesheet is imported into the _document.js and therefore reloads the page on save for those styles intstead of injecting those changes. That's not the biggest deal in the world, but not ideal.
I'm not sure if the issue is due to the way modules and _document.js work together, or if there needs to be a specific way to allow this within the next.config.js setup.
| Tech | Version |
|---------|---------|
| next | 6.0.0-canary.4 |
Issue is persistant for stable releases too.
+1 I'm having the exact same issue. As soon as you import a CSS Module from _document.js, all other scoped modules stop being bundled.
I'm seeing the same thing in _app.js as well.
This is the case for the stylus plugin as well.
Wanted to add an update to this. @claus's solution found here works for my case. I was able to add a reference to the global stylesheet in my _document.js file while also having SASS modules enabled. It's a solid workaroundπ
@eugeneross solved it for me as well! Thank you for sharing.
but his solution will add all available CSS files into the head , right? For example I have pages A,B,C,D and each has its own SCSS file. Does it only load A and global style when I go to page A? otherwise it will be super heavy bundle.
Hey,
This is not specifically for Sass but I think it's probably the same issue, so I created a Gist of a workaround for this based on @eugeneross solution: https://gist.github.com/Grsmto/8e7ade37862f1c8b4d019da8dd423450
It provides the same behaviour as CRA (Create React App) by allowing css-modules files (file.module.css) and normal css files (file.css) to work together and be extracted in the same stylesheet.
Did this get any better with the release of Next 7? I'm really interested in applying a framework stylesheet globally but scoping my own stylesheets.
Doesn't work with next 8.0.0-canary.2
TypeError: Cannot read property 'css' of undefined
I ended up tweaking the "getLocalIdent" of the css loader options:
const path = require('path')
const loaderUtils = require('loader-utils')
cssLoaderOptions: {
localIdentName: '[local]--[hash:base64:5]',
getLocalIdent: (loaderContext, localIdentName, localName, options) => {
const { resourcePath, rootContext } = loaderContext
if (resourcePath.indexOf('.module.') < 0) return localName
if (!options.context) {
// eslint-disable-next-line no-param-reassign
options.context = rootContext
}
const request = path
.relative(rootContext, loaderContext.resourcePath)
.replace(/\\/g, '/')
// eslint-disable-next-line no-param-reassign
options.content = `${request}+${localName}`
// eslint-disable-next-line no-param-reassign
localIdentName = localIdentName.replace(/\[local\]/gi, localName)
const hash = loaderUtils.interpolateName(
loaderContext,
localIdentName,
options
)
return hash
.replace(new RegExp('[^a-zA-Z0-9\\-_\u00A0-\uFFFF]', 'g'), '-')
.replace(/^((-?[0-9])|--)/, '_$1')
}
}
I'm having this issue when i have global variables that i want to access in modules, i get variable undefined. Anyone managed to fix this?
i have a global scss that i add in _app.js
@import "settings/all";
@import "bootstrap/bootstrap-grid";
@import "tools/all";
@import "generic/generic.reset";
@import "elements/elements.headingspara";
@import "elements/elements.images";
@import "elements/elements.links";
@import "elements/elements.page";
The in index.js i'm adding the following style sheet and $color-brand-primary is coming up as undefined. Do i need to add a loader?
div {
background-color: $color-brand-primary;
}
I ended up using the solution described here: https://spectrum.chat/next-js/general/import-bootstrap-scss-and-enable-cssmodules-both~eb9113e1-f1f7-4427-bcd0-fe72c1a4d259
This is my _app.js:
import App, { Container } from 'next/app';
import React from 'react';
import { Provider } from 'react-redux';
import withReduxStore from '../lib/with-redux-store';
import './App.global.scss'; // Used to import bootstrap or any other global stylesheet.
import styles from './styles.scss'; // CSS modules can be imported as usual.
class MyApp extends App {
render() {
const { Component, pageProps, reduxStore } = this.props;
return (
<Container>
<Provider store={reduxStore}>
<Component {...pageProps} />
</Provider>
</Container>
);
}
}
export default withReduxStore(MyApp);
This is my next.config.js:
const withSass = require('@zeit/next-sass');
module.exports = withSass({
cssModules: true,
cssLoaderOptions: {
importLoaders: 2,
localIdentName: '[local]___[hash:base64:5]',
},
webpack: config => {
config.module.rules.forEach(rule => {
if (rule.test.toString().includes('.scss')) {
rule.rules = rule.use.map(useRule => {
if (typeof useRule === 'string') {
return { loader: useRule };
}
if (useRule.loader.startsWith('css-loader')) {
return {
oneOf: [
{
test: new RegExp('.global.scss$'),
loader: useRule.loader,
options: { ...useRule.options, modules: false },
},
{
loader: useRule.loader,
options: useRule.options,
},
],
};
}
return useRule;
});
delete rule.use;
}
});
return config;
},
});
This workaround of using *.global.scss files should be set as a convention into this package for next major release.
can use *.module.less instand ? @wedneyyuri
@ckken I don't know for sure, but using @zeit/next-less instead of @zeit/next-sass should work.
no work for me !~ sad
Here is my solution based on @wedneyyuri answer.
By default css-modules is off. If you want to enable it you just need to add '.module'
at the end of file name.
using global styles:
import './your/file/path/name.sass'
using scoped styles:
import styles from './your/file/path/name.module.sass'
here's my next.config.js :
```
const withSass = require('@zeit/next-sass');
module.exports = withSass({
cssModules: true,
cssLoaderOptions: {
importLoaders: 2,
localIdentName: '[local]___[hash:base64:5]',
},
webpack: config => {
config.module.rules.forEach(rule => {
if (rule.test.toString().includes('.sass')) {
rule.rules = rule.use.map(useRule => {
if (typeof useRule === 'string') {
return { loader: useRule };
}
if (useRule.loader.startsWith('css-loader')) {
return {
oneOf: [
{
test: new RegExp('.module.sass$'),
loader: useRule.loader,
options: useRule.options
},
{
loader: useRule.loader,
options: {},
},
],
};
}
return useRule;
});
delete rule.use;
}
});
return config;
},
});
```
If you using .scss just change '.sass' => '.scss' in code.
A better way to use oneOf is with resourceQuery - it won't limit the rule by single filename only
// next.config.js
// ...
oneOf: [
{
resourceQuery: /plain/,
//.... no modules config
},
{
// ... default config
},
],
//...
And then import with ?plain query
// some_component.js
import 'assets/styles/style.scss?plain';
import { class1, class2 } 'assets/styles/my-modules.scss';
import 'assets/styles/another-global-style.scss?plain';
@strunoder24 works great for scss but appears to have a bug related to use of :global in a module file. We use this in a few rare instances like layout components because they need to apply CSS to the base <html>, <body>, and base __next div. It appears these global styles are not flushed if you leave the page where a component uses them.
I've had the same issues, so I created a small package to deal with it. (css + sass + modules + globals)
https://github.com/webdeb/next-styles
I've found global SCSS + modules still don't work by default even after updating to Next.js 9.2, where built-in CSS modules/global was introduced.
When you add any of the css plugins it'll disable built-in support.
This is fixed for me in 9.2, however, I'm not using SASS so that might be why others are still having issues.
For me, I import my global styles from _app.js (like this) without using CSS modules.
And then import all other CSS files as modules via the *.module.css syntax. π
@webdeb
I've had the same issues, so I created a small package to deal with it. (css + sass + modules + globals)
https://github.com/webdeb/next-styles
Thank you so much! It works!
@pixelkritzel thank you, its good to know, that it works well for you!
So, there's no way to use both SASS global and module stylesheets?
Does anyone have any workaround and solution?
@jamius19 this workaround worked well for me - https://github.com/zeit/next-plugins/issues/403#issuecomment-504650416 (change css to scss/sass)
@SZharkov Thank you very much. Working for me.
I've had the same issues, so I created a small package to deal with it. (css + sass + modules + globals)
https://github.com/webdeb/next-styles
YOU ARE MY SAVIOUR π€
The latest version of Next.js supports Global CSS and CSS Modules simultaneously (and Sass on next@canary), zero configuration required.
meh, I still have the issue even with canary
This is fixed in Next.js 9.3 if you use the built-in Sass support and not @zeit/next-sass.
Instead of global css by default why not do module css by default? Use style.global.scss when we want a global style.
Hello Team
I have facing issues regarding the next-CSS . I have using next-CSS but they are giving me a warning and when I removed the next-CSS from next.config file. my style CSS has not loaded chunks in the production. and my CSS is out of order in a production build.
Can you plz help me.
Most helpful comment
Here is my solution based on @wedneyyuri answer.
By default css-modules is off. If you want to enable it you just need to add '.module'
at the end of file name.
using global styles:
import './your/file/path/name.sass'using scoped styles:
import styles from './your/file/path/name.module.sass'here's my
next.config.js:```
const withSass = require('@zeit/next-sass');
module.exports = withSass({
cssModules: true,
cssLoaderOptions: {
importLoaders: 2,
localIdentName: '[local]___[hash:base64:5]',
},
});
```
If you using .scss just change '.sass' => '.scss' in code.