Search code examples
reactjswordpresswebpackembedcreate-react-app

Use "Create React App" inside a WordPress plugin


I'd like to develop a plugin, where the admin frontend (e.g. wp-admin pages) is rendered with React.

I'm using create-react-app for developing the app in a subfolder.

For loading the React App into the WordPress admin, I'm looking at the entrypoints in build/asset-mainfest.json and ensure to enqueue them in the right order.

The React App starts nicely, but all relative paths are broken, e.g. following does not work (I know this is a Webpack feature):

import logo from "./logo.jpg";

function App() {
  return <img src={logo} alt="" />;
}

export default App;

The reason it's breaking is, that Webpack assumes the build folder to be at the root.

I've seen some solutions to this, but none are satisfying for my needs:

  1. Here the author just prevents code-splitting, but still suffers from the same issue as above. It just does not consider other assets.
  2. Here the author is setting "homepage": "/wp-content/plugins/my-plugin/react-app/build" in package.json. But I think this would break, if WordPress was hosted in a subdirectory itself (like mywebsite.com/blog)
  3. Here the homepage is set to a specific domain, too, which makes the plugin not distributable.
  4. There was another article that suggested adding a HTML base attribute to the head. But there may be other relative links that get broken by that.
  5. Setting the homepage to "." won't work either, since I'm not serving the build folder itself.

Do you have a good idea for how I should go about importing assets with create-react-app here? I want the plugin to work however WordPress was set up.
My best guess is to pass React the URL to an assets folder and write something like <img src={props.assetsUrl + '/logo.jpg'} />, just avoiding these imports altogether.
I'd like to avoid using an iframe, because this causes other troubles I don't want to deal with... :)


Solution

  • Seems I've found someone else, who had the same problem:
    https://dev.to/n1ru4l/configure-the-cra-public-url-post-build-with-node-js-and-express-4n8

    You can set the PUBLIC_URL env var to a placeholder (in package.json)
    "build": "cross-env PUBLIC_URL=__PUBLIC_URL_PLACEHOLDER__ react-scripts build && node scripts/patch-public-url.js"

    ... and call a script to replace all your placeholders with window.__PUBLIC_URL__ (see the provided link for scripts/patch-public-url.js, there only JavaScript files get processed).

    Then you can localize the script with
    wp_localize_script( $handle, '__PUBLIC_URL__', $assets_url );
    where $assets_url is the URL to your React build folder, determined dynamically.

    Done! You may want to choose something else than __PUBLIC_URL__, just in case.