Next-plugins: SyntaxError on CSS file imported from node_modules.

Created on 18 Sep 2018  Β·  27Comments  Β·  Source: vercel/next-plugins

I've added @zeit/next-css and am using withCSS on my config, but the build complains about syntax errors when trying to import a CSS file (I presume the CSS file is being treated as a JS file).

How do we import CSS from node_modules?

Most helpful comment

If you are coming from Google search, especially if you still see the:

Module build failed: ModuleParseError: Module parse failed: Unexpected character '' (1:0) You may need an appropriate loader to handle this file type.

this might be the solution you are looking for.

3 simple steps:

  1. Install next-css plugin:
npm install --save @zeit/next-css
  1. Create in your root directory next.config.js with the following content:
// next.config.js 
const withCSS = require('@zeit/next-css')

module.exports = withCSS({
  cssLoaderOptions: {
    url: false
  }
})
  1. Now you should be able to import styleshets from node_modules like this:
import 'bootstrap-css-only/css/bootstrap.min.css';

_Note: Using Next v 8+_

Background:
I spent a few hours trying to simply import a CSS installed as a node_module and the various solutions are mostly hacky workarounds, but as shown above, there is a simple solution.
It was provided by one of the core team members: https://spectrum.chat/next-js/general/ignoring-folders-files-specifically-fonts~4f68cfd5-d576-46b8-adc8-86e9d7ea0b1f

All 27 comments

Hi @trusktr! Can you provide an example showing how and from where you refer to the css file?

Basically next.config.js is

const withCSS = require('@zeit/next-css')

module.exports = withCSS({
  cssModules: false,
})

and in my code I do

import "tiny-slider/dist/tiny-slider.css"

which yields the error

Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| .tns-outer{padding:0 !important}.tns-outer [hidden]{display:none !important} ... TRUNCATED ...

Do you have a Next.js CodeSandbox or StackBlitz I can fork to reproduce?

can you try require("tiny-slider/dist/tiny-slider.css")?

Here's an example project that uses next-css: https://github.com/zeit/next.js/tree/master/examples/with-next-css

Yep, looks like require instead of import works. That was unexpected though.

A problem with import 'something.css' would certainly be the case if your file is a typescript one and you are not using babel to load it. There may be other cases as well, I'm not sure.

Feel free to close this issue if you think that this problem is resolved πŸ˜‰

I'm using Next's default babel loader with @zeit/next-typescript. Should that work?

Here's my full config:

const path = require('path')
const withTypescript = require('@zeit/next-typescript')
const withCSS = require('@zeit/next-css')
const r = require('regexr')

const cssConfig = {
  cssModules: false,
}

const typescriptConfig = {}

const transpileModulesConfig = {
  transpileModules: [
    '@awaitbox/window-loaded',
    'tiny-slider',
  ],
}

const nextConfig = withTranspileModules(withTypescript(withCSS({
  ...cssConfig,
  ...typescriptConfig,
  ...transpileModulesConfig,

  // This is relative to src, because we run Next.js in the src folder (`next ./src`)
  distDir: '../.dist',

})))

// plugin to transpile specific node_modules packages
// See:
//  - https://github.com/zeit/next.js/pull/3732
function withTranspileModules(nextConfig) {

  const internalRegExps = nextConfig.transpileModules.map(m => {
    if (typeof m === 'string') return r`${r.escape(m)}(?!.*node_modules)`
    if (m instanceof RegExp) return m
    throw new TypeError('transpileModules should contain strings or RegExps only.')
  })

  const externalRegExps = nextConfig.transpileModules.map(m => {
    if (typeof m === 'string') return r`node_modules(?!\/${r.escape(m)}(?!.*node_modules))`
    return m
  })

  let jsRule

  function createJSRule(webpackConfig, nextOptions) {
    const {defaultLoaders} = nextOptions

    webpackConfig.module.rules.push(jsRule = {
      test: /\.+(js|jsx|ts|tsx)$/,
      loader: defaultLoaders.babel,
      include: []
    })
  }

  return {
    ...nextConfig,

    webpack(config, next) {
      config.resolve.symlinks = false

      // Next runs the dev config first, then the server config, so we reset rule
      // here when Next switches to the server config
      if (next.isServer) jsRule = null
      if (!jsRule) createJSRule(config, next)

      jsRule.include = internalRegExps

      config.externals = config.externals.map(external => {
        if (typeof external !== "function") return external
        return (ctx, req, cb) => internalRegExps.some(regex => regex.test(req)) ? cb() : external(ctx, req, cb)
      })

      if (typeof nextConfig.webpack === 'function')
        config = nextConfig.webpack(config, next)

      return config
    },

    webpackDevMiddleware(config) {
      const ignored = [...config.watchOptions.ignored, ...externalRegExps]
      config.watchOptions.ignored = ignored

      if (typeof nextConfig.webpackDevMiddleware === 'function')
        config = nextConfig.webpackDevMiddleware(config)

      return config
    },
  }
}

module.exports = nextConfig

You can see there I'm using the default loader:

    webpackConfig.module.rules.push(jsRule = {
      test: /\.+(js|jsx|ts|tsx)$/,
      loader: defaultLoaders.babel,
      include: []
    })

Did I mess it up?

What’s the version of your loader and next?

I've got

❯ npm list next @zeit/next-css @zeit/next-typescript
[email protected] /Users/trusktr/public-website
β”œβ”€β”€ @babel/[email protected]
β”œβ”€β”€ @zeit/[email protected]
β”œβ”€β”€ @zeit/[email protected]
└── [email protected]

and my babelrc looks like

{
  "presets": [
    "next/babel",
    "@zeit/next-typescript/babel"
  ],
  "plugins": [
    ["@babel/plugin-proposal-decorators", {
      "legacy": true
    }]
  ]
}

The rest are dependencies of those packages (including Babel, which is on beta.42)

Might be worth upgrading to canary - there’s stable babel 7 there

@kachkaev i'm using canary and I have almost same problem #267

New plugin versions have just been released. Next.js itself is 7.0.0 now. Does upgrading help?

With [email protected] and @zeit/[email protected] it makes no difference for me :(

Same here. I also tried to ignore plugin/loader /\.css$/. No matter what, it always fails with SyntaxError inside one of node_modules CSS files.

Try this in next.config.js:

const withTM = require('next-plugin-transpile-modules');

module.exports = withTM({
  transpileModules: ['tiny-slider'],
...

(swap out tiny-slider for whichever node module contains your css files)

There's a bunch of issues related to this problem (if not pure duplicates) - some of them have already had posted a working (temporary?) solution: https://github.com/zeit/next-plugins/issues/267#issuecomment-436454048

Worked great for me :)

Same here. I also tried to ignore plugin/loader /\.css$/. No matter what, it always fails with SyntaxError inside one of node_modules CSS files.

Did you managed to get it work?

If you are coming from Google search, especially if you still see the:

Module build failed: ModuleParseError: Module parse failed: Unexpected character '' (1:0) You may need an appropriate loader to handle this file type.

this might be the solution you are looking for.

3 simple steps:

  1. Install next-css plugin:
npm install --save @zeit/next-css
  1. Create in your root directory next.config.js with the following content:
// next.config.js 
const withCSS = require('@zeit/next-css')

module.exports = withCSS({
  cssLoaderOptions: {
    url: false
  }
})
  1. Now you should be able to import styleshets from node_modules like this:
import 'bootstrap-css-only/css/bootstrap.min.css';

_Note: Using Next v 8+_

Background:
I spent a few hours trying to simply import a CSS installed as a node_module and the various solutions are mostly hacky workarounds, but as shown above, there is a simple solution.
It was provided by one of the core team members: https://spectrum.chat/next-js/general/ignoring-folders-files-specifically-fonts~4f68cfd5-d576-46b8-adc8-86e9d7ea0b1f

Thanks @Vrq. Since NextCSS has a non-resolved issue "very hard to resolve": https://github.com/zeit/next-plugins/issues/282#issuecomment-462743580 about Router and CSS, I think it's not a viable solution. I just rewrote my whole app with styled component because of this issue, and I think there should be a workaround for people who don't rely on next/css.

I still face this :
image

Here's my next.config.js

/**
 * Next config for Next.js app
 *
 */


const withCSS = require('@zeit/next-css');
require('dotenv').config({ silent: true });
const path = require('path');
const Dotenv = require('dotenv-webpack');

module.export = withCSS({
  cssLoaderOptions: {
    url: false,
  },
  webpack: (config) => {
    // const config = {};

    config.plugins = config.plugins || [];

    config.plugins = [
      ...config.plugins,
      // Read the .env file
      new Dotenv({
        path: path.join(__dirname, '.env'),
        systemvars: true,
      }),
    ];

    return config;
  },
});

Here's how I'm importing.

...

// Top level import
import React, { Component } from 'react';
// Import Major components
import Head from 'next/head';
import 'bootstrap/dist/css/bootstrap.min.css';

...

import your css file in _app.js,
Don't Import it in _document.js.

@Vrq Your config could solve the problem. But it won't work if the css depends on local fonts (like font-awesome). As the font asset are not imported and expose by nextjs.

This hasn't worked for me or I am doing it wrong. I want to import a component from npm which internally imports from "typeface-montserrat"
Next.js coplaints about @font-face on typeface-montserrat/invdex.css

i have the same problem on next 9

Sorry to see this issue lasts for over 1y

This is still an issue if you use @zeit/next-css then next/css default css is disabled.

Hi, thanks for creating an issue. We currently recommend using https://nextjs.org/docs/basic-features/built-in-css-support as zeit/next-css and zeit/next-sass have been deprecated in favor of the built-in support.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lucasfeliciano picture lucasfeliciano  Β·  19Comments

Jauny picture Jauny  Β·  20Comments

paulrberg picture paulrberg  Β·  36Comments

morgs32 picture morgs32  Β·  15Comments

claus picture claus  Β·  14Comments