nx: Global CSS cannot be imported from files other than your Custom .

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

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 11
  • Comments: 30 (10 by maintainers)

Most upvoted comments

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

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 - <div className={**styles**.container}>

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 ?

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

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

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.

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 @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.

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?

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__