Optional Chaining （？．）

オプショナルチェイニングはどうでも良いが、エラーがエグくて判明まで時間がかかったのでメモしとく

## ことの発端

こんなコードを書いてみて、Storybookで確認しようとしたら、エラーになる。

```vuejs
<template>
  <canvas ref="canvas"></canvas>
</template>

<script lang="ts">
import { defineComponent, ref, watch } from "@vue/composition-api";

interface Props {}

export default defineComponent<Props>({
  name: "WebGL",
  props: {},
  setup: (props, ctx) => {
    const canvas = ref<HTMLCanvasElement>();
    watch(canvas, () => {
      const gl = canvas.value?.getContext("webgl");
      if (gl) {
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.clear(gl.COLOR_BUFFER_BIT);
      }
    });
    return { canvas };
  }
});
</script>
```

```
ERROR in ./src/components/_sandbox/WebGL.vue?vue&type=script&lang=ts& (./node_modules/vue-docgen-loader/lib??ref--12!./node_modules/ts-loader??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/_sandbox/WebGL.vue?vue&type=script&lang=ts&) 8:36
Module parse failed: Unexpected token (8:36)
File was processed with these loaders:
 * ./node_modules/vue-docgen-loader/lib/index.js
 * ./node_modules/vue-docgen-loader/lib/index.js
 * ./node_modules/ts-loader/index.js
 * ./node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|         const canvas = ref();
|         watch(canvas, () => {
>             const gl = canvas.value?.getContext("webgl");
|             if (gl) {
|                 gl.clearColor(0.0, 0.0, 0.0, 1.0);
 @ ./src/components/_sandbox/WebGL.vue?vue&type=script&lang=ts& 1:0-236 1:252-255 1:257-490 1:257-490
 @ ./src/components/_sandbox/WebGL.vue
 @ ./src/components/_sandbox/WebGL.stories.ts
 @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./.storybook/generated-stories-entry.js
 @ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/frameworks/common/config.js-generated-other-entry.js ./node_modules/@storybook/addon-docs/dist/frameworks/vue/config.js-generated-other-entry.js ./node_modules/@storybook/addon-links/dist/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/preset/addArgs.js-generated-other-entry.js ./node_modules/@storybook/addon-backgrounds/dist/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-backgrounds/dist/preset/addParameter.js-generated-other-entry.js ./node_modules/@storybook/addon-knobs/dist/preset/addDecorator.js-generated-other-entry.js ./.storybook/preview.js-generated-config-entry.js ./.storybook/generated-stories-entry.js (webpack)-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined
```

ここで、 Optional Chaining が問題だと気付くまで小一時間。
前にも同じ事があったような。。。


## Optional Chaining って今どんな状況？

ちなみに、```plugin-proposal-optional-chaining```で簡単に解決することは気付いていたが、もしかるすと、自分が時代遅れな事をやろうとしているんじゃないかと、もうちょい別の方法を模索する。。。

### TypeScript の Optional Chaining

そもそも TypeScript 3.7 で導入された機能ってことは知っているんだけど...
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html
ふむふむ、package.jsonのTypeScriptは3.9.3だから良いとして。。。


### ECMAScript の Optional Chaining

あ〜、そもそも ECMAScript で採用ってされてるんだっけ？　って事で調べてみると。。。
お〜 ECMAScript 2020 で採用って記事が出てるやん！

で、早速、ECMAに行ってみて。。。　「ECMA-262 11th Edition / June 2020」 を見てみる。
https://www.ecma-international.org/wp-content/uploads/ECMA-262.pdf
12.3.9 で定義されてますね。ここでは、「Optional Chaining」じゃなくて「Optional Chains」って名称になったんか。

### Mozilla の Optional Chaining

さて、次は、Mozillaでサポート状況を調べてみますか。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining

サポート状況は分かったが、仕様の項目に「オプショナルチェイニング" 演算子の提案」ってなんだ？？　って、ことで見てみる。
https://tc39.es/proposal-optional-chaining/#sec-scope

あれれ？？　まだ提案段階なの？？
う〜ん、Mozillaの更新が遅れているのかな？（汗）

### Babel の Optional Chaining

あ、最後に Babel 確認しとかないと。。。
https://babeljs.io/docs/en/
ES2015以降であれば「Babel has support for the latest version of JavaScript through syntax transformers.」って、何これ？　魔法なのか？？　今度調べておかないと。。。（疲）
まぁ、いい。。。大丈夫そうだ。。。　って、今回の件はコレが臭いのだけど、大丈夫なのか？？


## 結果どうする？

Optional Chaining のサポート状況云々より、そもそも babel が ES2015 で生きている以上```plugin-proposal-optional-chaining```を追加するしか無いと判断したので、本家を調べる。
https://storybook.js.org/docs/react/configure/babel

なるほど。。。
で、現在の設定を調べてみたいので、```.storybook/main.js```でこんなことをしてみる。

```js:.storybook/main.js
module.exports = {
  babel: async (options) => {
    console.log(JSON.stringify(options));
    return options;
  }
};
```

そしたら何と！　既に ```plugin-proposal-optional-chaining``` が設定されていると。。。
ということは。。。
どういうことだ？
あれ？　babel-loader 動いてない？？

んじゃ〜って事で、こうしてみる。

```js:.storybook/main.js
module.exports = {
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.(tsx|ts)$/,
      exclude: /node_modules/,
      use: [
        {
          loader: "babel-loader"
        },
        {
          loader: "ts-loader",
          options: {
            transpileOnly: true
          }
        }
      ]
    });
}
```

ようやく動いた。。。 orz

いや、違う。。。
何だか、納得できない。。。

ts-loader 動いてるんだから、babel云々じゃなくね？
んじゃ、```tsconfig.json```だわ。
って、ことで、```.storybook/main.js``` の変更は破棄して、```tsconfig.json```を覗いてみる。

あ。。。　targetが esnext やんけ。。。
ちゅうことで、target を ES5 に変更して無事解決。


## つまり。。。

```tsconfig.json```の ```target``` を ```"ES5"``` にする。
ふぅ。。。


## う〜ん

実はまだ解せないので、もうちょい調べる。
そもそも、誰がエラーを出していたのか、もう一度振り返ること。