1
0

More than 3 years have passed since last update.

Optional Chaining (?.)

Last updated at Posted at 2021-02-10

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

ことの発端

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

<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でこんなことをしてみる。

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

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

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

.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.jsontarget"ES5" にする。
ふぅ。。。

う〜ん

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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0