Engineering

⌘K
  1. Home
  2. Docs
  3. Engineering
  4. React Progressive Web App...
  5. Embedding React Web App Inside WordPress Plugin

Embedding React Web App Inside WordPress Plugin

Pre-requisites:

Register Shortcode in WordPress

Create the WordPress plugin folder, e.g. in folder wp-content/plugins, create folder embed-react.

Create the plugin file embed-react.php with skeleton as follows:

<?php
/*
  Plugin Name: Embed React
  Plugin URI: https://soluvas.com/
  Description: Embed React
  Author: Hendy Irawan
  Version: 1.0.0
  Author URI: https://soluvas.com/
*/

class EmbedReact_Plugin {

  public static $instance;

  public static function get_instance() {
    if (!self::$instance) {
      self::$instance = new EmbedReact_Plugin();
    }
    return self::$instance;
  }

  public function __construct() {
    add_shortcode( 'embed_react', [$this, 'handle_shortcode'] );
  }

  public function handle_shortcode($atts) {
    return <<<HERE
    Let's embed... yay...!
    HERE;
  }

}

EmbedReact_Plugin::get_instance();

Activate that plugin, then let’s test it.

In WordPress dashboard, create a new Page with slug “chat“.

Add a new Shortcode block, put: [embed_react]

Go to http://your_site/chat/ and ensure you can see your plugin’s shortcode working.

Embed Ant Design Pro App

In the Ant Design Pro project, create a new config/config.wordpress.ts file:

// https://umijs.org/config/
import { defineConfig } from 'umi';

export default defineConfig({
  base: '/chat/',
  publicPath: '/wp-content/plugins/embed-react/dist/',
});

Explanation:

  • base: this must match your WordPress frontend page’s permalink URL
  • publicPath: this must match your WordPress plugin’s path

Build your Ant Design Pro app using the UMI_ENV=wordpress:

UMI_ENV=wordpress yarn build

Copy the generated dist/ folder into your WordPress project under plugins/embed-react/.

Edit the plugin’s handle_shortcode() function to include the React root element and CSS/script calls:

  public function handle_shortcode($atts) {
    $umi_dist = plugins_url('dist', __FILE__);
    return <<<HERE

    <link rel="stylesheet" href="$umi_dist/umi.143062e9.css" />
    <script>
      window.routerBase = "/chat/";
    </script>
    <script>
      //! umi version: 3.3.9
    </script>

    <div id="root">
      <style>
        html,
        body,
        #root {
          /* height: 100%; */
          margin: 0;
          padding: 0;
        }
        #root {
          background-image: url("$umi_dist/home_bg.png");
          background-repeat: no-repeat;
          background-size: 100% auto;
        }
        .page-loading-warp {
          display: flex;
          align-items: center;
          justify-content: center;
          padding: 98px;
        }
        .ant-spin {
          position: absolute;
          display: none;
          -webkit-box-sizing: border-box;
          box-sizing: border-box;
          margin: 0;
          padding: 0;
          color: rgba(0, 0, 0, 0.65);
          color: #1890ff;
          font-size: 14px;
          font-variant: tabular-nums;
          line-height: 1.5;
          text-align: center;
          list-style: none;
          opacity: 0;
          -webkit-transition: -webkit-transform 0.3s
            cubic-bezier(0.78, 0.14, 0.15, 0.86);
          transition: -webkit-transform 0.3s
            cubic-bezier(0.78, 0.14, 0.15, 0.86);
          transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
          transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86),
            -webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
          -webkit-font-feature-settings: "tnum";
          font-feature-settings: "tnum";
        }

        .ant-spin-spinning {
          position: static;
          display: inline-block;
          opacity: 1;
        }

        .ant-spin-dot {
          position: relative;
          display: inline-block;
          width: 20px;
          height: 20px;
          font-size: 20px;
        }

        .ant-spin-dot-item {
          position: absolute;
          display: block;
          width: 9px;
          height: 9px;
          background-color: #1890ff;
          border-radius: 100%;
          -webkit-transform: scale(0.75);
          -ms-transform: scale(0.75);
          transform: scale(0.75);
          -webkit-transform-origin: 50% 50%;
          -ms-transform-origin: 50% 50%;
          transform-origin: 50% 50%;
          opacity: 0.3;
          -webkit-animation: antspinmove 1s infinite linear alternate;
          animation: antSpinMove 1s infinite linear alternate;
        }

        .ant-spin-dot-item:nth-child(1) {
          top: 0;
          left: 0;
        }

        .ant-spin-dot-item:nth-child(2) {
          top: 0;
          right: 0;
          -webkit-animation-delay: 0.4s;
          animation-delay: 0.4s;
        }

        .ant-spin-dot-item:nth-child(3) {
          right: 0;
          bottom: 0;
          -webkit-animation-delay: 0.8s;
          animation-delay: 0.8s;
        }

        .ant-spin-dot-item:nth-child(4) {
          bottom: 0;
          left: 0;
          -webkit-animation-delay: 1.2s;
          animation-delay: 1.2s;
        }

        .ant-spin-dot-spin {
          -webkit-transform: rotate(45deg);
          -ms-transform: rotate(45deg);
          transform: rotate(45deg);
          -webkit-animation: antrotate 1.2s infinite linear;
          animation: antRotate 1.2s infinite linear;
        }

        .ant-spin-lg .ant-spin-dot {
          width: 32px;
          height: 32px;
          font-size: 32px;
        }

        .ant-spin-lg .ant-spin-dot i {
          width: 14px;
          height: 14px;
        }

        @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
          .ant-spin-blur {
            background: #fff;
            opacity: 0.5;
          }
        }

        @-webkit-keyframes antSpinMove {
          to {
            opacity: 1;
          }
        }

        @keyframes antSpinMove {
          to {
            opacity: 1;
          }
        }

        @-webkit-keyframes antRotate {
          to {
            -webkit-transform: rotate(405deg);
            transform: rotate(405deg);
          }
        }

        @keyframes antRotate {
          to {
            -webkit-transform: rotate(405deg);
            transform: rotate(405deg);
          }
        }
      </style>
      <div
        style="
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          height: 100%;
          min-height: 420px;
        "
      >
        <img src="$umi_dist/pro_icon.svg" alt="logo" width="256" />
        <div class="page-loading-warp">
          <div class="ant-spin ant-spin-lg ant-spin-spinning">
            <span class="ant-spin-dot ant-spin-dot-spin"
              ><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i
              ><i class="ant-spin-dot-item"></i><i class="ant-spin-dot-item"></i
            ></span>
          </div>
        </div>
        <div
          style="display: flex; align-items: center; justify-content: center"
        >
          <img
            src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
            width="32"
            style="margin-right: 8px"
          />
          Ant Design
        </div>
      </div>
    </div>

    <script src="$umi_dist/umi.97a47641.js"></script>
    HERE;
  }

Check your WordPress page:

How can we help?