echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

【VSCode】VS Code Meetup #19 - フロントエンド開発Nightで登壇しました(トラブル編)

はじめに

前回、「『VS Code Meetup #19 - フロントエンド開発Night』というイベントで『Remote-Containersでnext.js環境を作った話』という内容で登壇」した話を書きました。

前回は登壇内容の補足(Remote-Containersについて&どのようなツールを入れたか)がメインでしたが、今回はトラブル編ということで「環境を構築する際に困ったこと」について書きたいと思います。

内容

  • ts-jestで「Cannot use import statement outside a module」エラーが出る
  • emotionでエラーが出る

ts-jestで「Cannot use import statement outside a module」エラーが出る

現象

TypeScript→JavaScript変換時たまに発生する、ES Module非対応のソースでimport xxx from yyyを行うと発生するエラーです。

対策方法として割とよく知られているのは以下の方法だと思いますが、どれもうまくいかず、困っていました。

  • 拡張子を.mts(.mjs)にする
    • 関連するnode_modulesパッケージもすべて拡張子変更する必要があり、さすがに無理。
    • 自作のものならまだ何とかなるけど...
  • package.json"type":"module"定義を付与する
    • これも上と同様node_modulesパッケージもすべて拡張子変更する必要があり、無理がある。
    • 一応プロジェクト直下のpackage.jsonには定義したが、現象変わらず
  • babelを使う
    • これが一番良い方法かも
    • ただ、色々情報調べて試したが、自分の環境ではうまくいかなかった
解決方法

...と思っていたんですが、ts-jestっていつの間にかES Module対応されていたんですね。(公式Doc読めよ...)

ESM Support | ts-jest

という訳で、下記を行えばOKです。

  • 設定ファイルに以下を追加する
    • ts-jestに対して"useESM": "true"の設定を追加する
    • extensionsToTreatAsEsmに*.tsを追加する

※公式ドキュメントでは「tsconfigのmoduleもES Moduleの値(es2020など)かどうかを確認」と書いてあるが、これはpresetがCommonJSに変換する形式なら不要?

Presets | ts-jest

{
    ...(jestのほかの設定), 
    
    "preset": "ts-jest",
     "globals": {
      "ts-jest": {
        "tsConfig": "tsconfig.json",
        "useESM": true  // これを追加
      }
    },
    // これも追加
    "extensionsToTreatAsEsm": [
      ".ts",
      ".tsx"
    ]
  }

emotionで「インターフェイス 'JSX.IntrinsicElements' が存在しないため、暗黙的に JSX 要素の型は 'any' になります。」というエラーが出る

emotionの公式サイトに従って、下記のようにコードを書きますが、なぜかcssの箇所で「インターフェイス 'JSX.IntrinsicElements' が存在しないため、暗黙的に JSX 要素の型は 'any' になります。」というエラーが発生する現象です。(@emotion/react@emotion/styledはインストール済み)

import { css } from '@emotion/react'  
  
const myCss = css({
  margin: '10px;'
})  
  
export const ComponentDruaga: VFC<ComponentDruagaProps> = ({treasures}) => {
    const {state, changeState}: UseMyStateType = useMyState();

    return (  
       // なぜかここで上記エラーが発生する
      <div css={myCss}>
        <div>{`stateは${state}です。`}</div>
        <button onClick={changeState}>stateを変える</button>
      </div>
    )
}

公式サイトのIntroductionに特に記載があるわけでもないので、最初は分かりませんでした...

解決方法

解決方法ですが、公式サイトのここにあるように@emotion/babel-pluginを導入すれば解決できました。
※公式サイトでもこの@emotion/babel-pluginは強く推奨とあるのですが「version8以上では必須ではない」と書いてあったため、インストールしてませんでした。

@emotion/babel-pluginをインストール後、.babelrcファイルに書きを定義すればOKです。

{
    "presets": [
      [
        "next/babel",
        {
          "preset-react": {
            "runtime": "automatic",
            "importSource": "@emotion/react"
          }
        }
      ]
    ],
    "plugins": ["@emotion/babel-plugin"]
}

ちなみに、下記サイトにめちゃくちゃ分かりやすいemotion+TypeScript環境の作成のやり方が書いてあるので、おススメです。(自分もここを参照しました)

【Next.js & TypeScript】Emotionの導入が大変だったので手順をまとめておく

まとめ

以上、「環境を構築する際に困ったこと」でした。
色々有益な情報が各種ブログなどにあったので、助かりました。

あと教訓として、やはり「公式サイトはまず最初に見ろ!」ですね。はい。(自戒も込めて)

それでは、今回はこの辺で。