できない.dev

esbuild「The JSX syntax extension is not currently enabled」の原因と直し方

esbuild の The JSX syntax extension is not currently enabled は、.js のファイルに JSX を書くと出る。
拡張子を .jsx にするか、--loader:.js=jsx で .js を JSX として読ませれば直る。

公開:

要約

esbuild は拡張子でローダーを選び、.js には JSX を読まない js ローダーを使う。
そのため .js のファイルに JSX を書いてバンドルすると、esbuild 0.28.2 では次の表示になり、終了コード 1 で止まった。

✘ [ERROR] The JSX syntax extension is not currently enabled
 
    src/app.js:2:24:
      2 │ function App() { return <h1>hello</h1>; }
        ╵                         ^
 
  The esbuild loader for this file is currently set to "js" but it must be set to "jsx" to be able to parse JSX syntax. You can use "--loader:.js=jsx" to do that.

ファイル名を .jsx にするか、--loader:.js=jsx を付ければ直る。
エラーの最後の行も同じ指定を案内している。

解決策

1. 拡張子を変えるか、.js のローダーを jsx にする

mv src/app.js src/app.jsx
npx esbuild src/app.jsx --bundle --outfile=out.js

ファイル名を変えたくないときは、.js を JSX として読ませる。

npx esbuild src/app.js --bundle --loader:.js=jsx --outfile=out.js

どちらも終了コード 0 で通った。
ビルドスクリプトで JavaScript API を使っているなら、loader に同じ指定を書く。

await esbuild.build({
  entryPoints: ["src/app.js"],
  bundle: true,
  outfile: "out.js",
  loader: { ".js": "jsx" },
});

2. 標準入力なら --loader=jsx を付ける

echo 'const a = <div/>;' | npx esbuild --loader=jsx

標準入力には拡張子が無いので、ローダーを 1 つだけ指定する形になる。

3. 依存パッケージの .js も同じ指定で読める

--loader:.js=jsx はバンドルに含まれるすべての .js に効く。node_modules の中の JSX で止まっていたバンドルも、この指定を足すと通った。

4. 通った後に React is not defined が出る場合

esbuild の既定の変換は JSX を React.createElement(...) に書き換える。
ファイルで React を import していないと、ビルドは通っても実行時に ReferenceError: React is not defined になった。
各ファイルで import するか、--jsx=automatic を付けて JSX の実行時ライブラリを esbuild に読み込ませる。

npx esbuild src/app.jsx --bundle --jsx=automatic --outfile=out.js

よくある原因

  1. JSX を .js に書いている。
    Create React App などから移ってきたプロジェクトは .js に JSX を書いていることが多く、esbuild に替えた時点でこのエラーになる。
  2. 標準入力からコードを渡している。echo 'const a = <div/>;' | npx esbuild は <stdin>:1:10 を指して同じエラーになった。
  3. 依存パッケージが JSX を .js のまま配布している。
    エラーの位置が node_modules/... を指していれば、自分のコードではなくそのパッケージのファイルが原因である。
  4. tsconfig.json の jsx を設定しても、.js のローダーは変わらない。"jsx": "react-jsx" を置いても同じエラーが出た。