4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

deno deployで「ReferenceError: h is not defined」が出たときの対処法

Last updated at Posted at 2022-08-21

deno deploy上でReactなどのライブラリを使ってJSXを記述した際に、「ReferenceError: h is not defined」というエラーが発生することがあります。これは、JSXを使ってSSRする際のオプションの設定方法が原因です。

特にこのエラーは「本番環境ではエラーが出るがローカル開発ではエラーが出ない」という事態になりやすく、なかなか開発中は気づきにくいです。

この記事では、このエラーの解決方法を紹介します。

原因

まず、DenoはJSXを直接実行することができます。ただし実行の際に、裏側ではJSXが素のJavaScriptに変換されたうえでJavaScriptに渡されます。

このソースコードは…
const a = <div>hello world</div>
このように変換されてから実行される
React.createElement(div, null, "hello world"));

上の例ではReact.createElementに変換されていますが、環境や設定によってどの関数に変換されるのかが変わります

具体的には、デフォルトでは以下のようにそれぞれ変換されます。

  • Deno 1.x系で動かす場合 → React.createElementという名前の関数へ変換
  • deno deployで動かす場合 → hという名前の関数へ変換

これらの違いから、ローカル開発でDenoを使用していた時は正常に動作するが、本番環境であるdeno deployに持っていくと動かないという事態が発生します。

なぜこうなっているのか:

  1. TypeScript本体のデフォルト値はReact.createElementなので、DenoのデフォルトもReact.createElementになっている。
  2. ただしDenoではReactが主流ではないので、デフォルト値がReactという名前の関数になっている意味はあまりない。そのためこのデフォルト値をhという名前の関数に変更しようという議論が行われた。これは破壊的変更なので、近々リリースされるDeno 2.0で導入しよう、となった。
  3. そのタイミングでdeno deployが提供開始されたため、deno deployではデフォルト値がhという名前になった
  4. ところが、Deno 2.0リリースが様々な事情で延期されたため、Deno本体のデフォルト値は現在もReact.createElementのままである

という流れのようです。

解決方法

JSXの変換先を明示的に指定する必要があります。
Reactなどのjsxトランスパイラをインストールしている個所すべてに、JSXプラグマを追記します。
JSXプラグマというのは、/** @jsx <JSXの変換先> */という形のコメントです。

変更前
import React from "./server_deps.ts";
変更後
/** @jsxFrag React.Fragment */
/** @jsx React.createElement */
import React from "./server_deps.ts";

このコメントを追記すると、どの関数に変換すればよいのかをトランスパイラに指示することができます。そのため、環境によってトランスパイル結果が変わることが無くなります。

解決方法2

上の解決方法では、JSXを使用するファイルすべてにJSXプラグマを追記する必要がありました。
これが面倒な場合は、あまりメジャーではありませんが、deno.jsonというファイルを作ってその中にtscondigのオプションを書く方法もあります。

deno.json
{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "React.createElement",
    "jsxFragmentFactory": "React.Fragment"
  }
}

まとめ

  • deno deployとDeno 1.0系を併用する場合、JSXがどの形にトランスパイルされるのかを指定する必要がある。
    • 指定方法は、JSXプラグマで指定する方法と、deno.jsonで指定する方法の2種類ある。
4
1
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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?