Nx: Global CSS cannot be imported from files other than your Custom <App>.

Created on 24 Sep 2020  路  17Comments  路  Source: nrwl/nx


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

react bug

Most helpful comment

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

All 17 comments

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

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 ?

Hi @danielquintero , thanks for filing an issue!

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

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

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__

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!

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?

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.

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

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!

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;
  },
};

thank you @jaysoo for working on this!

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!

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.

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?

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

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

Was this page helpful?
0 / 5 - 0 ratings