Configuring next.config file

18,395

Solution 1

So it looks like I had to do the following to get this to work:

Changing my next.config.js file to:

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

module.exports = withCSS({
  webpack: function (config) {
    config.module.rules.push({
      test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
      use: {
        loader: 'url-loader',
        options: {
          limit: 100000,
          name: '[name].[ext]'
        }
      }
    })
    return config
  }
})

And doing an npm i css-loader file-loader url-loader -D did the trick.

However I'm baffled as to why css-loader file-loader are needed? I'm used to webpack configs where you are explicitly adding the loaders (Like we are adding the url-loader above)... I didn't have to here!

Solution 2

In case someone uses next-compose-plugins and getting the above error, here's a fix:

const withCSS = require('@zeit/next-css');
const withImages = require('next-images');
const withPlugins = require('next-compose-plugins');

// fix: prevents error when .css files are required by node
if (typeof require !== 'undefined') {
  require.extensions['.css'] = (file) => {};
}

const nextConfig = {
  target: 'server',
  webpack: (config, { dev }) => {
    config.module.rules.push({
      test: /\.(raw)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
      use: 'raw-loader'
    });

    return config;
  }
};

module.exports = withPlugins([withImages, withCSS({target: 'serverless',
  webpack (config) {
    config.module.rules.push({
      test: /\.(png|svg|eot|otf|ttf|woff|woff2)$/,
      use: {
        loader: 'url-loader',
        options: {
          limit: 8192,
          publicPath: '/_next/static/',
          outputPath: 'static/',
          name: '[name].[ext]'
        }
      }
    })
    return config
  }})], nextConfig);


Share:
18,395

Related videos on Youtube

Antonio Pavicevac-Ortiz
Author by

Antonio Pavicevac-Ortiz

Hi all! I am currently a full-time Web Developer who lives in Queens NYC! I love running and spending time with my rascally little daughter! :)

Updated on June 04, 2022

Comments

  • Antonio Pavicevac-Ortiz
    Antonio Pavicevac-Ortiz over 1 year

    I am using Next.js and want to add the react-semantic-ui, to use one of their login components.

    On the front-end I am getting this error: Failed to compile

    ./node_modules/semantic-ui-css/semantic.min.css
    ModuleParseError: Module parse failed: Unexpected character '' (1:0)
    You may need an appropriate loader to handle this file type.
    (Source code omitted for this binary file)
    

    This is the login component:

    import React from 'react'
    import { Button, Form, Grid, Header, Image, Message, Segment } from 'semantic-ui-react'
    
    const Login = () => (
      /* login JSX markup */
    )
    
    export default Login
    

    This is my next.config.js

      module.exports = {
      webpack: (config, { dev }) => {
        config.module.rules.push(
          {
            test: /\.css$/,
            loader: 'style-loader!css-loader'
          },
          {
            test: /\.s[a|c]ss$/,
            loader: 'sass-loader!style-loader!css-loader'
          },
          {
            test: /\.(png|svg|eot|otf|ttf|woff|woff2)$/,
            use: {
              loader: "url-loader",
              options: {
                limit: 100000,
                publicPath: "./",
                outputPath: "static/",
                name: "[name].[ext]"
              }
            }
          },
          {
            test: [/\.eot$/, /\.ttf$/, /\.svg$/, /\.woff$/, /\.woff2$/],
            loader: require.resolve('file-loader'),
            options: {
              name: '/static/media/[name].[hash:8].[ext]'
            }
          }
        )
        return config
      }
    }
    
    const withCSS = require('@zeit/next-css')
    module.exports = withCSS()
    

    This is my package.js

      {
      "name": "create-next-example-app",
      "scripts": {
        "dev": "nodemon server/index.js",
        "build": "next build",
        "start": "NODE_ENV=production node server/index.js"
      },
      "dependencies": {
        "@zeit/next-css": "^1.0.1",
        "body-parser": "^1.18.3",
        "cors": "^2.8.5",
        "express": "^4.16.4",
        "mongoose": "^5.4.19",
        "morgan": "^1.9.1",
        "next": "^8.0.3",
        "react": "^16.8.4",
        "react-dom": "^16.8.4",
        "semantic-ui-css": "^2.4.1",
        "semantic-ui-react": "^0.86.0"
      },
      "devDependencies": {
        "css-loader": "^2.1.1",
        "file-loader": "^3.0.1",
        "node-sass": "^4.11.0",
        "nodemon": "^1.18.10",
        "sass-loader": "^7.1.0",
        "url-loader": "^1.1.2"
      }
    }
    

    I read somewhere you have to include a _document.js in the pages directory.

    // _document is only rendered on the server side and not on the client side
    // Event handlers like onClick can't be added to this file
    
    // ./pages/_document.js
    import Document, { Html, Head, Main, NextScript } from 'next/document';
    
    class MyDocument extends Document {
      static async getInitialProps(ctx) {
        const initialProps = await Document.getInitialProps(ctx);
        return { ...initialProps };
      }
    
      render() {
        return (
          <Html>
            <Head>
                <link rel='stylesheet' 
                      href='//cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.css'
                />
            </Head>
            <body className="custom_class">
              <Main />
              <NextScript />
            </body>
          </Html>
        );
      }
    }
    
    export default MyDocument;
    

    Is this really this hard?

    Update

    There is an alternate way of getting this to work. When you start up your Next app you get a components folder which includes a head.js and a nav.js file.

    The head.js file ultimately is analogous to a <head></head> tag in HTML. Or I should say that's what the head.js compiles to. ANYWAY, you can just add this in there:

    <link
      rel="stylesheet"
      href="//cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.css"
    />
    

    and that will work.

    But like I said you still can't import the modules like so:

    import 'semantic-ui-css/semantic.min.css'
    
    • Nino Filiu
      Nino Filiu over 4 years
      Does your app compiles normally with CSS that don't have @import statements?
    • Antonio Pavicevac-Ortiz
      Antonio Pavicevac-Ortiz over 4 years
      @NinoFiliu It doesn't compile at all....
    • Nino Filiu
      Nino Filiu over 4 years
      The error might be coming from Webpack. Check this article that does a great job at explaining webpack loaders - what the are, why they are needed and how to use them. In your case, your error looks like Webpack encountered a CSS file but didn't have the required loaders + config to "understand" it.
    • Antonio Pavicevac-Ortiz
      Antonio Pavicevac-Ortiz over 4 years
      @NinoFiliu Thanks my friend, I'll take a look. I bet there is a place somewhere where you have to explicitly configure Webpack.