'Error (Unexpected Token) using optional chaining syntax in Node 14/Vue2.js

Optional chaining isn't working on my Vue.js (v2) project on Node 14.17.

const adventurer = {
  name: 'Alice',
  cat: {
    name: 'Dinah'
  }
};

const dogName = adventurer.dog?.name;
console.log(dogName);
// expected output: undefined

console.log(adventurer.someNonExistentMethod?.());
// expected output: undefined

I get the following error:

 ERROR  Failed to compile with 1 error                                                                                                                                                                                                                                                                              11:04:50
 error  in ./src/components/Thing.vue?vue&type=script&lang=js&

Module parse failed: Unexpected token (497:39)
File was processed with these loaders:
 * ./node_modules/cache-loader/dist/cjs.js
 * ./node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.  
|             }
|         };
>         const dogName = adventurer.dog?.name;
|         console.log(dogName);
|         // expected output: undefined

 @ ./src/components/Thing.vue
 @ ./src/components/xx-thing.vue?vue&type=script&lang=js&
 @ ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/Home.vue?vue&type=script&lang=js&
 @ ./src/views/Home.vue
 @ ./src/router.js
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://172.16.8.210:8080/sockjs-node (webpack)/hot/dev-server.js ./src/main.js

I'm having a hunch it may be related to one of the below. I've installed Babel 7 as well, but perhaps the project still uses 6, as the Babel module name has apparently changed. But I don't know how to check, or how to switch it to 7, and even if that could be done without breaking the Vue project -- and perhaps it has nothing to do with that..

node -v
v14.17.6

npm ls webpack
[email protected]

npm ls @babel/core
7.15.5 (=latest)

npm ls @vue/cli-plugin-babel
4.5.13 (=latest)

npm ls @babel/plugin-proposal-optional-chaining
7.14.5 (=latest)

vue info

Environment Info:

  System:
    OS: Windows 10 10.0.18363
    CPU: (8) x64 Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
  Binaries:
    Node: 14.17.6 - C:\Program Files\nodejs\node.EXE
    Yarn: Not Found
    npm: 6.14.15 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 92.0.4515.131
    Edge: Spartan (44.18362.1474.0)
  npmPackages:
    @vue/babel-helper-vue-jsx-merge-props:  1.2.1
    @vue/babel-helper-vue-transform-on:  1.0.2
    @vue/babel-plugin-jsx:  1.0.7
    @vue/babel-plugin-transform-vue-jsx:  1.2.1
    @vue/babel-preset-app:  4.5.13
    @vue/babel-preset-jsx:  1.2.4
    @vue/babel-sugar-composition-api-inject-h:  1.2.1
    @vue/babel-sugar-composition-api-render-instance:  1.2.4
    @vue/babel-sugar-functional-vue:  1.2.2
    @vue/babel-sugar-inject-h:  1.2.2
    @vue/babel-sugar-v-model:  1.2.3
    @vue/babel-sugar-v-on:  1.2.3
    @vue/cli-overlay:  3.12.1
    @vue/cli-plugin-babel: ^4.5.13 => 4.5.13
    @vue/cli-plugin-eslint: ^3.11.0 => 3.12.1
    @vue/cli-plugin-pwa: ^4.2.3 => 4.5.13
    @vue/cli-service: ^3.11.0 => 3.12.1
    @vue/cli-shared-utils:  3.12.1 (4.5.13)
    @vue/cli-upgrade: ^3.12.1 => 3.12.1
    @vue/component-compiler-utils:  3.2.2
    @vue/preload-webpack-plugin:  1.1.2
    @vue/web-component-wrapper:  1.3.0
    eslint-plugin-vue: ^7.4.0 => 7.17.0 (4.7.1)
    vue: ^2.6.10 => 2.6.14
    vue-cli-plugin-vuetify: ^0.6.3 => 0.6.3
    vue-eslint-parser:  7.11.0 (2.0.3)
    vue-force-next-tick: ^1.1.0 => 1.1.0
    vue-head: ^2.2.0 => 2.2.0
    vue-hot-reload-api:  2.3.4
    vue-loader:  15.9.8
    vue-meta: ^2.3.2 => 2.4.0
    vue-router: ^3.0.3 => 3.5.2
    vue-sse: ^1.0.2 => 1.1.1
    vue-style-loader:  4.1.3
    vue-template-compiler: ^2.6.10 => 2.6.14
    vue-template-es2015-compiler:  1.9.1
    vue-the-mask:  0.11.1
    vuedraggable:  2.24.3
    vuetify: ^2.5.8 => 2.5.8
    vuetify-form-base: ^0.3.2 => 0.3.3
    vuetify-loader: ^1.4.3 => 1.7.3
  npmGlobalPackages:
    @vue/cli: Not Found

I've also tried adding plugins: ["@babel/plugin-proposal-optional-chaining"], to babel.config.js

I've also tried to uninstall babel 6, but the npm uninstaller fails to actually uninstall it.

Could have a similar root cause, (unfortunately unresolved): Optional chaining not working in Node 14 LTS?



Solution 1:[1]

Cause

This is because Vue 2 is using webpack 4. And Webpack 4 is using Acorn 6. Wheras support for optional chaining wasn't implemented into Acorn until version 7.2.0.

Solution

To use optional chaining, and other newer features, you will need to use Babel. This feature is available in @babel/plugin-proposal-optional-chaining, which is also included in the ECMA-262 / @babel/preset-env, or specificially for Vue apps: just @vue/app.

If you've not already done so, you'll need vue add @vue/cli-plugin-babel. Then just update your Babel config with a valid preset, e.g.

"babel": {
  "presets": [
    "@vue/app"
  ]
}

A more detailed guide, can be found here.

Restart the dev server/ rebuild the app, and optional chaining should now work :)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Lissy93