Nuxt.js: optional chaining code makes error in SSR step

Created on 16 Jul 2020  Â·  17Comments  Â·  Source: nuxt/nuxt.js

Versions

  • nuxt: v2.13.3
  • node: v14.5.0

Reproduction

codesandbox does not work well :(

// index.vue
<template>
  <div>
    <nuxt-link to="/about">about</nuxt-link>
    <div>{{ fullName }}</div>
  </div>
</template>

<script>
export default {
  computed: {
    fullName() {
      const a = { name: { firstName: 'Jack', lastName: 'Nam' } };
      const fullName = `${a.name?.firstName} ${a.name?.lastName}`;
      return fullName;
    },
  },
};
</script>
// about.vue
<template>
  <nuxt-link to="/">index</nuxt-link>
</template>

Steps to reproduce

  1. use create-next-app to create project
  2. create file named index.vue and about.vue in the pages directory
  3. write down code above
  4. run npm run dev in terminal
  5. access 127.0.0.1:3000

What is Expected?

[Fig. 1]



What is actually happening?

[Fig. 2]



When I access to 127.0.0.1:3000 by SSR (entering address directly), the error page(Fig. 2) came out. However when I access by CSR, the right page(Fig. 1) came out.

I think babel does not work properly in SSR.

+ when I ran npm run build command, similar error came out in terminal

ERROR in ./pages/index.vue?vue&type=script&lang=js& (./node_modules/babel-loader/lib??ref--2-0!./node_modules/@nuxt/components/dist/loader.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./pages/index.vue?vue&type=script&lang=js&) 26:33
Module parse failed: Unexpected token (26:33)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
 * ./node_modules/@nuxt/components/dist/loader.js
 * ./node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|         }
|       };
>       const fullName = `${a.name?.firstName} ${a.name?.lastName}`;
|       return fullName;
|     }
 @ ./pages/index.vue?vue&type=script&lang=js& 1:0-227 1:243-246 1:248-472 1:248-472
 @ ./pages/index.vue
 @ ./.nuxt/router.js
 @ ./.nuxt/index.js
 @ ./.nuxt/server.js
 @ multi ./node_modules/@nuxt/components/lib/installComponents.js ./.nuxt/server.js
bug-report

Most helpful comment

The problem was the webpack. Since webpack4 does not understand optional-chaing, babel should transpile it. However the default setting of babel-preset-app in server is server: { node: 'current' } and Node 14 understands optional-chaining.
So, babel did not transplie optional-chaing code. Then, webpack threw error since it can not understand optional chaining.

There are two solutions.

  1. import @babel/plugin-proposal-optional-chaining plugin
  2. downgrade Node to LTS version

All 17 comments

You use optional chaining in your components that does not support by default, In order to use optional chaining you should use @babel/plugin-proposal-optional-chaining
Install @babel/plugin-proposal-optional-chaining and add in your nuxt.config.js

...
  build: {
    babel: {
      plugins: [
        '@babel/plugin-proposal-optional-chaining'
      ]
    }
  },
...

P.S. as Dmitry says in blew commend It should work without additional library.

it should ( and it work) out of box
https://codesandbox.io/s/dreamy-burnell-vtgul?file=/pages/index.vue

Maybe you have some messed up deps e.g. old babel preset which isn't including this. Try to delete your lock file and node modules and reinstall

The problem was the webpack. Since webpack4 does not understand optional-chaing, babel should transpile it. However the default setting of babel-preset-app in server is server: { node: 'current' } and Node 14 understands optional-chaining.
So, babel did not transplie optional-chaing code. Then, webpack threw error since it can not understand optional chaining.

There are two solutions.

  1. import @babel/plugin-proposal-optional-chaining plugin
  2. downgrade Node to LTS version

This should be IMO re-opened and fixed in Nuxt. It works with Node <14 so it's a matter of tweaking the babel preset to enable it for Node 14 also.

@pi0

hey @pi0 I've seen you took care of that. I think the same is to Nullish coalescing etc.
Would be great if ES2020 would be enabled by default. How do you see that? :)

@patzick Indeed that's one of alternatives to use a fixed target for babel preset. Also thanks for reminding about nullish plugin. We will discuss about it with @clarkdo

Thanks for your contribution to Nuxt.js!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you would like this issue to remain open:

  1. Verify that you can still reproduce the issue in the latest version of nuxt-edge
  2. Comment the steps to reproduce it

Issues that are labeled as pending will not be automatically marked as stale.

I'm getting with issue too

Here's my Babel config from nuxt.config.js:

  // Build Configuration (https://go.nuxtjs.dev/config-build)
  build: {
    babel: {
      plugins: [
        '@babel/plugin-proposal-optional-chaining',
        '@babel/plugin-proposal-nullish-coalescing-operator',
      ],
    },
  },

I've tried adding console.error() statements to node_modules/@babel/plugin-proposal-optional-chaining/lib/index.js. Something (presumably Babel) is loading the plugin file but the var _default = (0, _helperPluginUtils.declare)((api, options) => { function in that plugin is never getting loaded.

Here's my node.js version:

$ node -v
v15.2.0

I've tried deleting /node_modules/.cache/babel-loader/ and that didn't fixed it. In fact I tried deleting the whole of /node_modules/ and package-lock.json and that didn't fix it.

@pi0 I've tried created two new codebases using npm init nuxt-app. I've used default options when creating the codebases, except for selecting TypeScript for the second codebase. Both codebases show this bug. See output below. I was suprised they're getting the issue as they're both using the latest version of @nuxt/babel-preset-app which includs the fix from https://github.com/nuxt/nuxt.js/pull/8203

  1. https://github.com/msmsimondean/nuxt-optional-chaining-js/commit/a1935f8b114ae12c15c31981cb085e79eed82c79
  2. https://github.com/msmsimondean/nuxt-optional-chaining-ts/commit/b6ef074eecc9f46aa4459be703a1850d1fc6bdeb

Error with JavaScript

ERROR  Failed to compile with 1 errors                                                                                                                           friendly-errors 17:45:12


 ERROR  in ./pages/index.vue?vue&type=template&id=2a183b29&                                                                                                       friendly-errors 17:45:12

Syntax Error: Unexpected token (1:109)                                                                                                                            friendly-errors 17:45:12

                                                                                                                                                                  friendly-errors 17:45:12
 @ ./pages/index.vue?vue&type=template&id=2a183b29& 1:0-255 1:0-255
 @ ./pages/index.vue
 @ ./.nuxt/router.js
 @ ./.nuxt/index.js
 @ ./.nuxt/client.js
 @ multi ./node_modules/@nuxt/components/lib/installComponents.js eventsource-polyfill webpack-hot-middleware/client?reload=true&timeout=30000&ansiColors=&overlayStyles=&path=%2F__webpack_hmr%2Fclient&name=client ./.nuxt/client.js

Error with TypeScript

 ERROR  Failed to compile with 1 errors                                                                                                                           friendly-errors 17:48:19


 ERROR  in ./pages/index.vue?vue&type=template&id=2a183b29&                                                                                                       friendly-errors 17:48:19

Syntax Error: Unexpected token (1:109)                                                                                                                            friendly-errors 17:48:19

                                                                                                                                                                  friendly-errors 17:48:19
 @ ./pages/index.vue?vue&type=template&id=2a183b29& 1:0-255 1:0-255
 @ ./pages/index.vue
 @ ./.nuxt/router.js
 @ ./.nuxt/index.js
 @ ./.nuxt/client.js
 @ multi ./node_modules/@nuxt/components/lib/installComponents.js eventsource-polyfill webpack-hot-middleware/client?reload=true&timeout=30000&ansiColors=&overlayStyles=&path=%2F__webpack_hmr%2Fclient&name=client ./.nuxt/client.js

I've tried adding this to my nuxt.config.js. Have I tried the right thing?

  // Build Configuration (https://go.nuxtjs.dev/config-build)
  build: {
    babel: {
      presets({ isServer }, [preset, options]) {
        return [
          [
            preset,
            {
              targets: isServer ? { node: '13' } : { ie: 9 }
            }
          ],
        ]
      }
    },
  },

This didn't fix it either:

  // Build Configuration (https://go.nuxtjs.dev/config-build)
  build: {
    babel: {
      presets({ isServer }, [preset, options]) {
        return [
          [
            "@babel/preset-env",
            {
              targets: isServer ? { node: '13' } : { ie: 9 }
            }
          ],
        ]
      },
      plugins: [
        '@babel/plugin-proposal-optional-chaining',
        '@babel/plugin-proposal-nullish-coalescing-operator',
      ],
    },
  },

I've tried downgrading to node.js 12 and that's not fixed it either:

✖ Client
  Compiled with some errors in 2.84s

✖ Server
  Compiled with some errors in 2.81s


 ERROR  Failed to compile with 1 errors                                                                                                                           friendly-errors 18:32:13


 ERROR  in ./pages/index.vue?vue&type=template&id=2a183b29&                                                                                                       friendly-errors 18:32:13

Module Error (from ./node_modules/vue-loader/lib/loaders/templateLoader.js):                                                                                      friendly-errors 18:32:13
(Emitted value instead of an instance of Error) 

  Errors compiling template:

  invalid expression: Unexpected token '.' in

    "\n  "+_s(hello.world?.greeting)+"\n"

  Raw expression: {{ hello.world?.greeting }}


  1  |  
  2  |  <div class="container">
     |                         
  3  |    {{ hello.world?.greeting }}
     |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  4  |  </div>

                                                                                                                                                                  friendly-errors 18:32:13
 @ ./pages/index.vue?vue&type=template&id=2a183b29& 1:0-255 1:0-255
 @ ./pages/index.vue
 @ ./.nuxt/router.js
 @ ./.nuxt/index.js
 @ ./.nuxt/client.js
 @ multi ./node_modules/@nuxt/components/lib/installComponents.js eventsource-polyfill webpack-hot-middleware/client?reload=true&timeout=30000&ansiColors=&overlayStyles=&path=%2F__webpack_hmr%2Fclient&name=client ./.nuxt/client.js

Hi @msmsimondean , from your error log {{ hello.world?.greeting }} , it looks you're using Optional chaining in template, this is not related to babel config which works for script of vue file.

From this vue issue, I think vue 2 doesn't support Optional chaining in template tag yet.

This appears to no longer be an issue, with the exception of the Vue issue linked by @clarkdo which is not related to Nuxt.

Example reproduction - with working out-of-the-box optional chaining and nullish coalescing: https://codesandbox.io/s/stupefied-hill-bz9qp?file=/pages/index.vue

That's great. Thanks for the info @danielroe. Not sure how I missed that.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shyamchandranmec picture shyamchandranmec  Â·  3Comments

bimohxh picture bimohxh  Â·  3Comments

maicong picture maicong  Â·  3Comments

vadimsg picture vadimsg  Â·  3Comments

gary149 picture gary149  Â·  3Comments