amplify-js: Next.js project fails to build, Unexpected token : at dist/style.css

Description I have Next.js project and have added aws-amplify. During the build, I get the following error:

> Build error occurred
{ /Users/imyjimmy/_tea/react-frontend/node_modules/@aws-amplify/ui/dist/style.css:13
:root {
^

SyntaxError: Unexpected token :
    at new Script (vm.js:79:7)
    at createScript (vm.js:251:10)
    at Object.runInThisContext (vm.js:303:10)
    at Module._compile (internal/modules/cjs/loader.js:656:28)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
    at Module.load (internal/modules/cjs/loader.js:598:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
    at Function.Module._load (internal/modules/cjs/loader.js:529:3)
    at Module.require (internal/modules/cjs/loader.js:636:17)
    at require (internal/modules/cjs/helpers.js:20:18) type: 'SyntaxError', '$error': '$error' }
error Command failed with exit code 1.

I have looked at the solution described in https://github.com/aws-amplify/amplify-js/issues/1934 and my next.config.js has been set up accordingly:

if (typeof require !== 'undefined') {
  require.extensions['.less'] = () => {}
  require.extensions['.css'] = file => {}
}

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.png$/,
      loader: require.resolve('url-loader'),
    })
    config.module.rules.push({
      test: /\.css$/,
      loader: [
        require.resolve('style-loader'),
        require.resolve('css-loader'),
        require.resolve('postcss-loader'),
      ],
    })
    return config
  },
  distDir: 'build',
}

However, the build still fails.

To Reproduce I will create a minimum github project that shows this issue. For now, clone my repo: I’ve created a minimum repo that shows this issue:

  1. git@github.com:imyjimmy/nextjs-aws-amplify.git
  2. yarn
  3. yarn build

Or, if you prefer to recreate from npx:

  1. npx create-next-app
  2. add the following: url-loader, css-loader, style-loader, postcss-loader, autoprefixer, aws-amplify, aws-amplify-react
  3. next.config.js
if (typeof require !== 'undefined') {
  require.extensions['.less'] = () => {}
  require.extensions['.css'] = file => {}
}

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.png$/,
      loader: require.resolve('url-loader'),
    })
    config.module.rules.push({
      test: /\.css$/,
      loader: [
        require.resolve('style-loader'),
        require.resolve('css-loader'),
        require.resolve('postcss-loader'),
      ],
    })
    return config
  },
  distDir: 'build',
}
  1. pages/index.js
import { Authenticator } from 'aws-amplify-react'
...
<Nav />
<Authenticator hideDefault={true}>
  <div className='hero'>
  ...
</Authenticator>
  1. yarn build

Expected behavior I expect the build to complete.

Desktop (please complete the following information):

  • OS: macOS 10.14.5
  • node v10.12.0
  • aws-amplify ^1.1.36
  • aws-amplify-react ^2.3.12

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 9
  • Comments: 27 (3 by maintainers)

Most upvoted comments

Bump

As a temporary stopgap I published my own package, https://www.npmjs.com/package/aws-amplify-react-jz, which is a fork of aws-amplify-react minus the offending line, and it seems to work. It reflects their version 2.3.12

OK here is my current next.config.js and everything is working ok


if (typeof require !== 'undefined') {
  require.extensions['.less'] = () => {}
  require.extensions['.css'] = file => {}
}

module.exports = withPlugins([withCSS, withSass, withTM], {
  transpileModules: ['bs-platform', 'bs-css', 'reason-apollo-hooks', 're-formality'],
  pageExtensions: ['jsx', 'js', 'bs.js'],
  resolve: {
    modules: ['sass_loader'],
    cssModules: true,
  },
  webpack (config, options) {
    config.module.rules.push({
      test: /\.css$/,
      loader: [
        require.resolve('postcss-loader'),
      ],
    });

    // Fixes npm packages that depend on `fs` module
    config.node = {
      fs: 'empty'
    };
    return config
  },
})

Updated next.config.js that works for both dev and build (be sure to install amplify with npm i --save aws-amplify@next)

const withCSS = require('@zeit/next-css')
const resolve = require('resolve')
global.navigator = () => null
module.exports = withCSS({
    webpack (config, options) {
        const { dir, isServer } = options
        config.externals = []
        if (isServer) {
          config.externals.push((context, request, callback) => {
            resolve(request, { basedir: dir, preserveSymlinks: true }, (err, res) => {
              if (err) {
                return callback()
              }
              if (
                res.match(/node_modules[/\\].*\.css/)
                && !res.match(/node_modules[/\\]webpack/)
                && !res.match(/node_modules[/\\]@aws-amplify/)
              ) {
                return callback(null, `commonjs ${request}`)
              }
              callback()
            })
          })
        }
        return config
      }
});

Okay, yeah, that’s the same experience that I had. Sorry I didn’t realize that those examples didn’t use the react bindings. I ejected from aws-amplify-react, too, and it has been nice to get away from.

There are still various issues but they can usually be resolved by making sure that everything runs on the client with componentDidMount or useEffect. Sometimes I would use dynamic imports to make sure the package wasn’t imported on the server

Have you tried starting from the next.js provided examples?

Go to either with-aws-amplify or with-aws-amplify-typescript https://github.com/zeit/next.js/tree/canary/examples

Next and amplify can be made to behave with each other but it can be quite painful, mostly from Amplify’s end.

Yup, those examples which use only the aws-amplify package work perfectly. It’s the React bindings (aws-amplify-react package) that make everything fall apart. Unfortunately this ties into #3365. Due to non-modularized code, it’s tough to import anything from aws-amplify-react without pulling every bit of aws-related code into our app along with it. We’re not actually using any of the presentational components, but we still get the CSS for them.

Going forward we’ll probably go ahead with Next 9, and just remove aws-amplify-react and write our own bindings for aws-amplify. It’ll be a bit of a pain, but will neatly solve this CSS issue and probably slim our bundle size too.

Have you tried starting from the next.js provided examples?

Go to either with-aws-amplify or with-aws-amplify-typescript https://github.com/zeit/next.js/tree/canary/examples

Next and amplify can be made to behave with each other but it can be quite painful, mostly from Amplify’s end.

Hmm, 2 days of tweaking the Webpack config, and I’m still stumped. I’ve tried the following

  1. Tried the approach from the Next with-ant-design example, which is to regex match the specific problem files (in our case, @aws-amplify/ui/dist/style.css), and then both externalize them and add a rule to use null-loader for them. No effect, Same error message as before, on both dev and build.

  2. Tried a scorched-earth approach of excluding every single CSS file with the above method. No effect. Same error message as before, on both dev and build.

  3. Tried approach 1, but removing the isServer check, so that @aws-amplify/ui/dist/style.css gets excluded from both the server it client bundles. No effect. Same error message as before, on both dev and build.

  4. Tried approach 2, but removing the isServer check, so that all CSS gets excluded from both the server and client bundles. No effect. Same error message as before, on both dev and build.

5-8. Tried each of the above, but now with next-css. Identical results in each case.

As best I can tell, regardless of what we do in the Webpack config is next.config.js, something is still pulling in @aws-amplify/ui/dist/style.css. I can’t seem to get verbose enough output from next or webpack to figure out why this occurs.

  1. Skipped all this Webpack sorcery, and simply did the old require.extensions hack from above:
if (typeof require !== 'undefined') {
  require.extensions['.less'] = () => {}
  require.extensions['.css'] = file => {}
}

This one is the only one that’s made a difference. When I do this, I can at least get dev working. But build fails, same error message as before. Curiously, it fails after it reaches Compiled successfully. I’ve poked around in the next source, and it looks like the automatic prerendering (that ijjk said causes this issue) occurs after this message prints. This is as far as I’ve gotten.

Only thing I’ve found that gets build working is the horrible, horrible hack of going into @aws-amplify/ui/dist/style.css in a text editor and deleting its contents. That makes everything load just fine, as long as you don’t actually want that CSS, and also don’t care about breaking npm forever!

Have you tried using @zeit/next-css ?

@rakannimer Ah, just saw that @imyjimmy 's example wasn’t using next-css. I was using next-css, but have tried it without also.

Can confirm I experience this as well. App builds fine with npm run dev, but crashes with the unexpected token error on npm run build. I know that #3279 is planned to fix this problem, but in the interest of finding a temporary workaround in the meanwhile, here’s some more info.

Not sure if this is useful info, but: the solution from #1934 is helping, but in npm run dev only. If you remove this fix:

if (typeof require !== 'undefined') {
  require.extensions['.less'] = () => {}
  require.extensions['.css'] = file => {}
}

…you will then find that npm run dev and npm run build now both fail with the same error.

Been surveying related issues, and what’s interesting is that it appears this fix used to work in both dev and build, prior to around July 2019! But since July it has failed to work on build. This coincides with some other, similar issues popping up with unexpected token errors in css imports from node_modules with next (see, for example, zeit/next-plugins#266, zeit/next-plugins#498). This coincides with the release of Next 9. and in fact, according to JJ Kasper’s reply this is because of a change in build in Next 9!

Now that we know exactly what’s causing it, I think all we need for a hacky workaround is to do some Webpack magic to exclude those imports. I expect to have this working within a day or two and will post my fix when I do.

@mlabieniec Thanks for your solution. Unfortunately it doesn’t work when using React hooks due to config.externals = []

As quoted, hooks don’t work with this solution. Has anybody found a solution that doesn’t break hooks?

Edit: the solution by @eastuto appears to be working.

Edit2: wrote a gist that implements this solution more granularly and without using deprecated features of node.js.

I had the same issue using react-flexbox-grid. Managed to solve it using the module next-transpile-modules, like so:

const withSass = require('@zeit/next-sass');
const withCSS = require('@zeit/next-css');
const withTM = require('next-transpile-modules');

module.exports = withCSS(withSass(withTM({
  transpileModules: ['react-flexbox-grid']
})));

To get past the > :root { issue and render the Authenticator in Next.js you need to include @zeit/next-css package npm i --save @zeit/next-css. So your root ./next.config.js file should look like this:

const withCSS = require('@zeit/next-css')
global.navigator = () => null
if (typeof require !== 'undefined') {
    require.extensions['.less'] = () => {}
    require.extensions['.css'] = file => {}
}
module.exports = withCSS({
});

This will render the full withAuthenticator with styles and also polyfill the navigator for analytics so everything works for dev. Seems like some of this can be solved with a postcss config file as outlined in the next docs, example here: https://stackoverflow.com/questions/46592310/postcss-modules-and-next-js

Seems like in general there is an issue loading css from node_modules discussed here (this still fails on production build): https://github.com/zeit/next-plugins/issues/266

And RFC for css support in next.js here: https://github.com/zeit/next.js/issues/8626