Open7

自前のJSXファクトリ関数のimportをRollupに任せる

21f21f

@rollup/plugin-injectimport { Hoge } from "hoge"; を追加するだけなので、自作のファクトリ関数はバンドルしてくれない。(その後に別の処理が必要?)

21f21f

JSXの処理にはBabelを使用する。Rollupから使うには @rollup/plugin-babel を入れる。

また、BabelからJSXを変換するため @babel/plugin-transform-react-jsx を入れる。

npm install --save-dev \
  @rollup/plugin-babel \
  @babel/core \
  @babel/preset-env \
  @babel/plugin-transform-react-jsx

今回は自前のファクトリ関数 jsx() を使用するため、 babel.config.json に次の記述をする。

{
    "presets": ["@babel/preset-env"],
    "plugins": [["@babel/plugin-transform-react-jsx", { "pragma": "jsx" }]]
}
21f21f

実はRollupには最終出力の先頭や末尾にコードを追加するオプションがある。

このオプションに jsx() の中身を指定すればよさそうだ。

import { babel } from "@rollup/plugin-babel";

const config = {
    input: ...,
    output: {
        format: "es",
        intro: `
function jsx(type, props, ...children) {
    ...
}
`,
    },
    plugins: [
        babel({ babelHelpers: "bundled" }),
    ],
};
export default config;
21f21f

Rollupはプラグインを簡単に書くことができ、output.intro を追加する部分をプラグイン化すると次のようになる。

inject-jsx-runtime.js では jsx() 関数はtoStringメソッドで文字列化して(importなどがあると動かないので注意)……

import { jsx } from "./src/jsx-runtime.js";

const jsxCode = `${jsx.toString()}\n`;
// → function jsx(...) { ... } という文字列になる

export function injectJsxRuntime() {
    return {
        name: "inject-jsx-runtime",
        intro: jsxCode,
    };
}

そして rollup.config.js は

import { babel } from "@rollup/plugin-babel";
import { injectJsxRuntime } from "./inject-jsx-runtime.js";

const config = {
    ...,
    plugins: [
        babel({ babelHelpers: "bundled" }),
        injectJsxRuntime(),
    ],
};
export default config;

これで出力コードの先頭に function jsx(...) { ... } が入るようになる。

21f21f

最近のReactだといちいち import React from "react" を書かなくていいが、それはプラグイン @babel/plugin-transform-react-jsx のおかげ。

自動でJSX用の宣言をimportしてくれる設定は "runtime": "automatic".

プラグインの設定で "importSource": "hoge" とすると、コードに import { jsx, jsxs, Fragment } from "hoge/jsx-runtime" を挿入してくれるようだが、プロジェクト内の jsx-runtime.js を読み込ませる方法は分からなかった。なので "runtime": "classic"(デフォルト)として動作させることに。