如果不需要 SSR,如何编译 JS 文件以在 WordPress 主题中使用 React 组件?

How to compile the JS file to use a React component in a WordPress theme if I do not need SSR?

我有一个 WordPress 主题,其中一部分我想使用 React 组件(我不需要 SSR)。我过去使用过 create-react-app 但现在我有这个代码:

<div id="react-nav-bar"></div>

<script src="https://unpkg.com/react@17/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js" crossorigin></script>

<script src="<?php echo get_template_directory_uri() ?>/react-nav-bar/build/static/js/runtime-main.39639aca.js"></script>

而且它不起作用。对 runtime-main.39639aca.js 的请求成功,但它没有加载我的导航栏。

问题是 create-react-app 生成的不仅仅是一个 JS 文件,我只需要一个可以放入主题中的 JS 文件。

我用 webpack 尝试了一些东西但没有成功。我在 GitHub 上搜索了一些东西,我不知道该尝试哪一个。我试过 react-embedded and it threw me an error. I also tried this 但它对我不起作用。

我也不喜欢 ES Lint 警告(我使用 VS Code)。

更新 1

这个命令部分地完成了我想要的:

npx babel --watch react-nav-bar/src --out-dir react-nav-bar/dist --presets react-app/prod

这是我在没有 WebPack 的情况下尝试过的方式,但是 VS Code 中的编辑器充满了红色波浪线,尽管它编译得很好,而且我无法导入 npm 模块。有没有办法导入 npm 模块?自动完成让我 很多 更有效率。

我尝试了 Rollup,效果非常好。

我在 DevTools 控制台中收到一些警告,但它有效!带有自动完成和 npm 模块包含。

基于 this gist 我有这些文件:

src/index.tsx

import * as React from "react";
import { render } from 'react-dom';

const App = () => {
  return <button onClick={() => alert('React from WordPress !')}>Cool!!!</button>;
};

window.addEventListener('DOMContentLoaded', () => {
  render(<App />, document.getElementById('react-nav-bar'));
});

package.json

只有两个额外的脚本:

"build": "rollup -c",
"watch": "rollup -cw"

与上面链接的要点相比,不寻常的依赖关系:

"@rollup/plugin-commonjs": "^18.0.0",
"@rollup/plugin-node-resolve": "^11.2.1",
"rollup-plugin-typescript": "^1.0.1",

rollup.config.js

import typescript from 'rollup-plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';

export default {
    input: './src/index.tsx',
    output: {
        file: './dist/bundle.js',
    },
    format: 'iife',
    plugins: [ resolve(), typescript(), commonjs() ],
};

tsconfig.json

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "forceConsistentCasingInFileNames": true,
    "jsx": "react",
    "module": "es6",
    "moduleResolution": "node",
    "noImplicitAny": true,
    "outDir": "./dist",
    "preserveConstEnums": true,
    "target": "es5",
    "allowSyntheticDefaultImports": true
  },
  "exclude": [
    "node_modules"
  ]
}

为了让 React 与此一起工作,我有特殊的行:"allowSyntheticDefaultImports": true

../footer.php

<div id="react-nav-bar"></div>

<script>try { process.env.NODE_ENV } catch(e) { var process = { env: { NODE_ENV: 'production' } }; }</script>
<script src="<?php echo get_template_directory_uri() ?>/react-nav-bar/dist/bundle.js"></script>

这很有帮助:https://github.com/hybridsjs/hybrids/issues/27#issuecomment-452346986