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

Global CSS cannot be imported from files other than your Custom <App>. #3803

Closed
danielquintero opened this issue Sep 24, 2020 · 30 comments · Fixed by #4047 or #5479
Closed

Global CSS cannot be imported from files other than your Custom <App>. #3803

danielquintero opened this issue Sep 24, 2020 · 30 comments · Fixed by #4047 or #5479
Assignees
Labels

Comments

@danielquintero
Copy link

danielquintero commented Sep 24, 2020

Screenshot 2020-09-24 at 15 14 39

## Current Behavior Given a generated NextJs app that imports a generated shared react lib with a default component that uses either css or cssModule imports fails throwing an error.

Expected Behavior

Given a default NextJs app that imports a shared react lib with a default component that uses either css or cssModule imports should just work, no need to adapt next.config.js as both imports are supported by default in NextJs.

Is this a regression? Not sure, I am able to reproduce with brand new workspace and latest version of every plugin.

Steps to Reproduce

  1. npx create-nx-workspace test-bug [choose empty setup]
  2. npm i -D @nrwl/next
  3. nx generate @nrwl/next:application --name=test-bug
  4. nx generate @nrwl/react:library --name=shared-library
  5. in the generated nextjs app add the shared component to the render function
  6. try run the app nx serve test-bug
  7. try renaming components css file to => xxx.module.css and it's corresponding import

Failure Logs

warn  - Detected next.config.js, no exported configuration found. https://err.sh/vercel/next.js/empty-configuration
info  - automatically enabled Fast Refresh for 1 custom loader
info  - Using external babel configuration from /Users/danielq/Projects/test-workspace/apps/test-bug/.babelrc
event - compiled successfully
[ ready ] on http://localhost:3000
event - build page: /next/dist/pages/_error
wait  - compiling...
event - compiled successfully
event - build page: /
wait  - compiling...
error - /Users/danielq/Projects/test-workspace/libs/shared-components/src/lib/shared-components.css
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to pages/_app.tsx. Or convert the import to Component-Level CSS (CSS Modules).
Read more: https://err.sh/next.js/css-global
Location: ../../libs/shared-components/src/lib/shared-components.tsx

Environment

nx : Not Found
@nrwl/angular : Not Found
@nrwl/cli : 10.2.1
@nrwl/cypress : 10.2.1
@nrwl/eslint-plugin-nx : 10.2.1
@nrwl/express : Not Found
@nrwl/jest : 10.2.1
@nrwl/linter : 10.2.1
@nrwl/nest : Not Found
@nrwl/next : 10.2.1
@nrwl/node : Not Found
@nrwl/react : 10.2.1
@nrwl/schematics : Not Found
@nrwl/tao : 10.2.1
@nrwl/web : 10.2.1
@nrwl/workspace : 10.2.1
typescript : 3.9.7

@vsavkin vsavkin added the scope: react Issues related to React support for Nx label Sep 24, 2020
@danielquintero
Copy link
Author

hey @vsavkin do you guys have any news on this?

@msreekm
Copy link

msreekm commented Oct 26, 2020

Got the similar error when selecting sass for styling while generating a component-
nx g component PartyPopper --project=demo --style=scss
i dont next.js let you do import './party-popper.scss'; inside components! it has to be css modules .module.css

this is what i had to do to get it working-

  1. rename party-popper.scss to party-popper.module.scss
  2. change import to import styles from './party-popper.module.scss';
  3. to apply the style -

code generator should be updated to updated the generate code.

I am happy to create a PR ,but I was not able to find the correct file to make the change inside packages/next folder. @jaysoo ?

@mandarini
Copy link
Member

Hi @danielquintero , thanks for filing an issue!

Hi @msreekm ! Would you like help creating a PR?

@msreekm
Copy link

msreekm commented Oct 29, 2020

@mandarini happy to create a PR , do you know which files have generate component template for next.js?

@msreekm
Copy link

msreekm commented Oct 30, 2020

I see the code ais already in the latest build ,not sure why it is no working? @jaysoo ?

<%= style !== 'styled-jsx' ? import styles from './${fileName}.module.${style}'; : '' %>

https://github.com/nrwl/nx/blob/10.3.1/packages/next/src/schematics/application/files/pages/__fileName__.tsx__tmpl__

@areknow
Copy link

areknow commented Nov 3, 2020

Same happening to me. NX with NextJS app, importing component from a lib. Lib schematics generate the following:
nx g @nrwl/react:lib test
Screen Shot 2020-11-03 at 5 18 31 PM

Screen Shot 2020-11-03 at 5 18 56 PM

Changing to test.module.scss and import './test.module.scss'; has no effect.

Checking the default webpack config I can see that there are rules in place for css modules.

Thanks!

@jlcampbell
Copy link
Contributor

Screen Shot 2020-11-05 at 4 02 44 PM
Screen Shot 2020-11-05 at 4 02 50 PM
Screen Shot 2020-11-05 at 4 04 05 PM
Screen Shot 2020-11-05 at 4 04 20 PM
@vsavkin I'm also experiencing this issue. I follow the instructions from the first error message and switch my css file to end in ".module.css", but modules cannot be used in libs. Is there a work around?

@jaysoo
Copy link
Member

jaysoo commented Nov 6, 2020

Hey folks, after a quick chat with @mandarini we've decided to do the following:

  1. Provide a withNx function for next.config.js to use, which will allow workspace libs to use css modules. This config enhancer will also help with future modifications based on Nx's needs.
  2. Add a --cssModules option for React component schematic (this is used by Next.js schematics underneath the hood). This will allow app components/pages, as well as libs, to generate with *.module.css or *.module.scss by default.

@jlcampbell
Copy link
Contributor

@jaysoo @mandarini Thank you for the quick response, that sounds great!

@areknow
Copy link

areknow commented Nov 6, 2020

Hey folks, after a quick chat with @mandarini we've decided to do the following:

  1. Provide a withNx function for next.config.js to use, which will allow workspace libs to use css modules. This config enhancer will also help with future modifications based on Nx's needs.
  2. Add a --cssModules option for React component schematic (this is used by Next.js schematics underneath the hood). This will allow app components/pages, as well as libs, to generate with *.module.css or *.module.scss by default.

That would be great! Thanks!

@jaysoo
Copy link
Member

jaysoo commented Nov 6, 2020

PR for the first part is ready -- the second change for schematics isn't required but more of a quality of life change.

For those that want a workaround before the next release, you can use this in your app's next.config.js.

const { join } = require('path');
const { appRootPath } = require('@nrwl/workspace/src/utils/app-root');
const { workspaceLayout } = require('@nrwl/workspace/src/core/file-utils');
function regexEqual(x, y) {
  return (
    x instanceof RegExp &&
    y instanceof RegExp &&
    x.source === y.source &&
    x.global === y.global &&
    x.ignoreCase === y.ignoreCase &&
    x.multiline === y.multiline
  );
}
module.exports = {
  webpack: (config) => {
    // Include workspace libs in css/sass loaders
    const includes = [join(appRootPath, workspaceLayout().libsDir)];
    const nextCssLoaders = config.module.rules.find(
      (rule) => typeof rule.oneOf === 'object'
    );
    // webpack config is not as expected
    if (!nextCssLoaders) return config;
    /*
     *  1. Modify css loader to enable module support for workspace libs
     */
    const nextCssLoader = nextCssLoaders.oneOf.find(
      (rule) =>
        rule.sideEffects === false && regexEqual(rule.test, /\.module\.css$/)
    );
    // Might not be found if Next.js webpack config changes in the future
    if (nextCssLoader) {
      nextCssLoader.issuer.or = nextCssLoader.issuer.and
        ? nextCssLoader.issuer.and.concat(includes)
        : includes;
      delete nextCssLoader.issuer.and;
    }
    /*
     *  2. Modify sass loader to enable module support for workspace libs
     */
    const nextSassLoader = nextCssLoaders.oneOf.find(
      (rule) =>
        rule.sideEffects === false &&
        regexEqual(rule.test, /\.module\.(scss|sass)$/)
    );
    // Might not be found if Next.js webpack config changes in the future
    if (nextSassLoader) {
      nextSassLoader.issuer.or = nextSassLoader.issuer.and
        ? nextSassLoader.issuer.and.concat(includes)
        : includes;
      delete nextSassLoader.issuer.and;
    }
    /*
     *  3. Modify error loader to ignore css modules used by workspace libs
     */
    const nextErrorCssModuleLoader = nextCssLoaders.oneOf.find(
      (rule) =>
        rule.use &&
        rule.use.loader === 'error-loader' &&
        rule.use.options &&
        (rule.use.options.reason ===
          'CSS Modules \u001b[1mcannot\u001b[22m be imported from within \u001b[1mnode_modules\u001b[22m.\n' +
            'Read more: https://err.sh/next.js/css-modules-npm' ||
          rule.use.options.reason ===
            'CSS Modules cannot be imported from within node_modules.\nRead more: https://err.sh/next.js/css-modules-npm')
    );
    // Might not be found if Next.js webpack config changes in the future
    if (nextErrorCssModuleLoader) {
      nextErrorCssModuleLoader.exclude = includes;
    }
    return config;
  },
};

@danielquintero
Copy link
Author

thank you @jaysoo for working on this!

@areknow
Copy link

areknow commented Nov 9, 2020

PR for the first part is ready -- the second change for schematics isn't required but more of a quality of life change.

For those that want a workaround before the next release, you can use this in your app's next.config.js.

...

This works, but please keep in mind that the schematics for generating the react:lib still need some tweaks:

  1. the component scss file needs to be renamed: test.module.scss
  2. the corresponding import needs to be modified in the component jsx: import './test.module.scss';

Thanks!

@jaysoo jaysoo reopened this Nov 9, 2020
@jaysoo
Copy link
Member

jaysoo commented Nov 9, 2020

Accidentally closed the issue from the PR merge. Keeping this open until we get the schematics change in as well.

@areknow We are changing the schematics as well, so by default they will generate with css modules (which are better IMO), and you can pass --cssModule=false to use plain/global css.

@areknow
Copy link

areknow commented Nov 9, 2020

Accidentally closed the issue from the PR merge. Keeping this open until we get the schematics change in as well.

@areknow We are changing the schematics as well, so by default they will generate with css modules (which are better IMO), and you can pass --cssModule=false to use plain/global css.

Love that! Thanks @jaysoo

What version can we expect the changes in?

@jaysoo
Copy link
Member

jaysoo commented Nov 10, 2020

This will come in 10.4, which will land before American Thanksgiving. We'll cut a beta release before stable.

@guojianlan
Copy link

guojianlan commented Nov 16, 2020

PR for the first part is ready -- the second change for schematics isn't required but more of a quality of life change.

For those that want a workaround before the next release, you can use this in your app's next.config.js.

const { join } = require('path');
const { appRootPath } = require('@nrwl/workspace/src/utils/app-root');
const { workspaceLayout } = require('@nrwl/workspace/src/core/file-utils');
function regexEqual(x, y) {
  return (
    x instanceof RegExp &&
    y instanceof RegExp &&
    x.source === y.source &&
    x.global === y.global &&
    x.ignoreCase === y.ignoreCase &&
    x.multiline === y.multiline
  );
}
module.exports = {
  webpack: (config) => {
    // Include workspace libs in css/sass loaders
    const includes = [join(appRootPath, workspaceLayout().libsDir)];
    const nextCssLoaders = config.module.rules.find(
      (rule) => typeof rule.oneOf === 'object'
    );
    // webpack config is not as expected
    if (!nextCssLoaders) return config;
    /*
     *  1. Modify css loader to enable module support for workspace libs
     */
    const nextCssLoader = nextCssLoaders.oneOf.find(
      (rule) =>
        rule.sideEffects === false && regexEqual(rule.test, /\.module\.css$/)
    );
    // Might not be found if Next.js webpack config changes in the future
    if (nextCssLoader) {
      nextCssLoader.issuer.or = nextCssLoader.issuer.and
        ? nextCssLoader.issuer.and.concat(includes)
        : includes;
      delete nextCssLoader.issuer.and;
    }
    /*
     *  2. Modify sass loader to enable module support for workspace libs
     */
    const nextSassLoader = nextCssLoaders.oneOf.find(
      (rule) =>
        rule.sideEffects === false &&
        regexEqual(rule.test, /\.module\.(scss|sass)$/)
    );
    // Might not be found if Next.js webpack config changes in the future
    if (nextSassLoader) {
      nextSassLoader.issuer.or = nextSassLoader.issuer.and
        ? nextSassLoader.issuer.and.concat(includes)
        : includes;
      delete nextSassLoader.issuer.and;
    }
    /*
     *  3. Modify error loader to ignore css modules used by workspace libs
     */
    const nextErrorCssModuleLoader = nextCssLoaders.oneOf.find(
      (rule) =>
        rule.use &&
        rule.use.loader === 'error-loader' &&
        rule.use.options &&
        (rule.use.options.reason ===
          'CSS Modules \u001b[1mcannot\u001b[22m be imported from within \u001b[1mnode_modules\u001b[22m.\n' +
            'Read more: https://err.sh/next.js/css-modules-npm' ||
          rule.use.options.reason ===
            'CSS Modules cannot be imported from within node_modules.\nRead more: https://err.sh/next.js/css-modules-npm')
    );
    // Might not be found if Next.js webpack config changes in the future
    if (nextErrorCssModuleLoader) {
      nextErrorCssModuleLoader.exclude = includes;
    }
    return config;
  },
};

workspace lib use importing CSS required by a third party component, you can do so in your component. For example:

// components/ExampleDialog.js
import { useState } from 'react'
import { Dialog } from '@reach/dialog'
import '@reach/dialog/styles.css'

function ExampleDialog(props) {
  const [showDialog, setShowDialog] = useState(false)
  const open = () => setShowDialog(true)
  const close = () => setShowDialog(false)

  return (
    <div>
      <button onClick={open}>Open Dialog</button>
      <Dialog isOpen={showDialog} onDismiss={close}>
        <button className="close-button" onClick={close}>
          <VisuallyHidden>Close</VisuallyHidden>
          <span aria-hidden>×</span>
        </button>
        <p>Hello there. I am a dialog</p>
      </Dialog>
    </div>
  )
}

But there is a bug, error log:

image

I moved import '@reach/dialog/styles.css' to file pages/_app.tsx and there was no error, but I think this is not good

@github-actions
Copy link

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏

@github-actions github-actions bot added the stale label Mar 29, 2021
@jsking216
Copy link

this is still an issue for my team, especially with next-sass breaking in new 10.1.X builds

@github-actions github-actions bot removed the stale label Apr 1, 2021
@jaysoo jaysoo added scope: nextjs Issues related to NextJS support for Nx and removed scope: react Issues related to React support for Nx labels Apr 8, 2021
@kirjai
Copy link
Contributor

kirjai commented Apr 27, 2021

seems like there are a few different issues floating around in this thread 👀

firstly, using a react lib with css modules inside a next.js app. From what I understand, that's what the original issue is about.
That has been fixed, and works as expected, based on what I'm seeing locally and following the steps to reproduce in the original issue. If someone is still seeing this issue, please create a repro repo that we can pull down to debug it.


secondly, using sass modules. Same thing here, really. In my attempts locally, sass modules work in the same way as css modules. So once again, if someone have specific steps that reproduce the issue - please let us know!
@jsking216 are you able to provide a repro repo that demonstrates the issue you're talking about?


thirdly, importing "global" css from node_modules in a react lib that's used in a next.js app. (this comment).
this is a use case that's supported by next.js natively, and i can reproduce it. i'll look into it further and report back!

@vukers
Copy link

vukers commented Jul 13, 2021

thirdly, importing "global" css from node_modules in a react lib that's used in a next.js app. (this comment).
this is a use case that's supported by next.js natively, and i can reproduce it. i'll look into it further and report back!

I see that this issue is closed, but there is a pending item to review the use of React component libraries which are not using CSS modules. Where can the status of that be tracked?

@Armer7
Copy link

Armer7 commented Aug 24, 2021

This error happens again

  1. create app
    изображение
  2. Try run app nx run dev:serve
  3. Get error
    изображение
    изображение

package.json

{
  "name": "nx-test",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "nx": "nx",
    "start": "nx serve",
    "build": "nx build",
    "test": "nx test",
    "lint": "nx workspace-lint && nx lint",
    "e2e": "nx e2e",
    "affected:apps": "nx affected:apps",
    "affected:libs": "nx affected:libs",
    "affected:build": "nx affected:build",
    "affected:e2e": "nx affected:e2e",
    "affected:test": "nx affected:test",
    "affected:lint": "nx affected:lint",
    "affected:dep-graph": "nx affected:dep-graph",
    "affected": "nx affected",
    "format": "nx format:write",
    "format:write": "nx format:write",
    "format:check": "nx format:check",
    "update": "nx migrate latest",
    "workspace-generator": "nx workspace-generator",
    "dep-graph": "nx dep-graph",
    "help": "nx help"
  },
  "private": true,
  "dependencies": {
    "@nrwl/next": "12.7.2",
    "core-js": "^3.6.5",
    "next": "11.1.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "regenerator-runtime": "0.13.7",
    "tslib": "^2.0.0"
  },
  "devDependencies": {
    "@nrwl/cli": "12.7.2",
    "@nrwl/cypress": "12.7.2",
    "@nrwl/eslint-plugin-nx": "12.7.2",
    "@nrwl/jest": "12.7.2",
    "@nrwl/linter": "12.7.2",
    "@nrwl/react": "12.7.2",
    "@nrwl/tao": "12.7.2",
    "@nrwl/web": "12.7.2",
    "@nrwl/workspace": "12.7.2",
    "@testing-library/react": "11.2.6",
    "@types/jest": "26.0.24",
    "@types/node": "14.14.33",
    "@types/react": "17.0.3",
    "@types/react-dom": "17.0.3",
    "@typescript-eslint/eslint-plugin": "~4.28.3",
    "@typescript-eslint/parser": "~4.28.3",
    "babel-jest": "27.0.6",
    "cypress": "^7.3.0",
    "dotenv": "~10.0.0",
    "eslint": "7.22.0",
    "eslint-config-next": "11.1.0",
    "eslint-config-prettier": "8.1.0",
    "eslint-plugin-cypress": "^2.10.3",
    "eslint-plugin-import": "2.22.1",
    "eslint-plugin-jsx-a11y": "6.4.1",
    "eslint-plugin-react": "7.23.1",
    "eslint-plugin-react-hooks": "4.2.0",
    "jest": "27.0.3",
    "prettier": "^2.3.1",
    "ts-jest": "27.0.3",
    "ts-node": "~9.1.1",
    "typescript": "~4.3.5"
  }
}

Node version v14.16.1
Repo

@kirjai kirjai reopened this Aug 24, 2021
@kirjai
Copy link
Contributor

kirjai commented Aug 27, 2021

hey @Armer7 , thanks for reporting this!

i pulled down the repo from your message, but running nx run dev:serve works fine for me. could you double check that repo please?

@Armer7
Copy link

Armer7 commented Aug 27, 2021

hey @Armer7 , thanks for reporting this!

i pulled down the repo from your message, but running nx run dev:serve works fine for me. could you double check that repo please?

It's strange, but after I pulled down my repo and run npm install now it works. I will look when I will create new nx project again and if I will have mistake I will remove folder node_module and I will reinstall packages.

@Armer7
Copy link

Armer7 commented Aug 27, 2021

Hi @kirjai. I checked. Now all good. Maybe It was failure when creating. Although not. When creating other versions were used than in the repository
изображение

@kirjai
Copy link
Contributor

kirjai commented Aug 27, 2021

@Armer7 great, so if everything's good, then i'll close the issue

@kirjai kirjai closed this as completed Aug 27, 2021
@omnitube
Copy link

Got the similar error when selecting sass for styling while generating a component-
nx g component PartyPopper --project=demo --style=scss
i dont next.js let you do import './party-popper.scss'; inside components! it has to be css modules .module.css

this is what i had to do to get it working-

  1. rename party-popper.scss to party-popper.module.scss
  2. change import to import styles from './party-popper.module.scss';
  3. to apply the style -

code generator should be updated to updated the generate code.

I am happy to create a PR ,but I was not able to find the correct file to make the change inside packages/next folder. @jaysoo ?

This issue still exists in part, so I don't think it should be closed.

I am using a fresh install of the latest nx, and when I generate a page with nx g @nrwl/next:page blabla --style=scss the created page contains import './blabla.module.scss'; instead of import styles from './blabla.module.scss';

@Murkantilism
Copy link

Murkantilism commented Dec 1, 2021

This was re-introduced in NextJS v11.1.1 (seemingly only for Windows devs) and fixed in 11.1.2; see here for details: vercel/next.js#28579

@gideoncatz
Copy link

gideoncatz commented May 24, 2022

Hey guys (@kirjai ?),
So If I can't import the global.scss from any other place except for my _app.js, how can I use a globally defined sass variable (say, for a purpose of an application-wide color palette), inside a component-level xxx.module.scss?
The fact that the global.scss is imported in _app.js doesn't make its contents automatically available to all the scss modules in the app. So if I say:

// MyComponent.module.scss
.testclass {
    background-color: $color-from-global-scss;
}

I'm getting: SassError: Undefined variable.

@github-actions
Copy link

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet