How to insert (inject?) an existing React app (just a UI without a backend) into a SilverStripe page layout?

这一生的挚爱 提交于 2019-12-02 07:22:05

You can inject a frontend application bundle using Requirements::javascript() calls in your controller, or from your template using <% require %> calls. The fundamental concept is "add your JavaScript (and/or CSS) bundles to my frontend view". From there on it's up to your bundle to initiate itself, given that the bundles are available on the page.


Here's a lightweight example added to a theme:

  • Add a theme folder e.g. themes/my-theme
  • Enable it by adding it to app/_config/theme.yml
  • Add a ReactPage layout (note: the layout is the content section, not the full page layout)
# File: ./themes/my-theme/templates/Layout/ReactPage.ss
<div id="my-react-app">
    If you can see this, your React app hasn't initialised yet
</div>
  • Flush (?flush in your browser) the cache

If you add a ReactPage in the CMS, then open it on your frontend, you should now see the message that your React app hasn't initialised yet. This works because SilverStripe will look up the inheritance chain of pages to find one that has a template matching its class name. Note that this includes the class's namespace, so if your class has one it'd need to be templates/Foo/Bar/Layout/ReactPage.ss instead for example.

Now initialise a demo React app:

  • cd themes/my-theme && create-react-app js
  • cd js && yarn build

You will now need to tell SilverStripe to "expose" your theme assets, which will symlink (by default) them into the public/resources directory, so you can access them from your webroot (public/ folder).

# File: ./composer.json
...
"extra": {
    "expose": [
        "themes/my-theme/build/static/js/bundle.js"
    ]
}

Run composer vendor-expose from your root project folder to re-expose all your resources.

Finally, add your requirements to your SilverStripe template or controller. You can do this via a controller's init() method, or directly in the template:

# File: ReactPageController.php (note that this may not exist and doesn't need to necessarily)
use SilverStripe\View\Requirements;

// ...

protected function init()
{
    parent::init();

    Requirements::javascript('themes/my-theme/js/build/static/js/main.ad956de7.chunk.js');
    Requirements::javascript('themes/my-theme/js/build/static/js/2.6efc73d3.chunk.js');
    Requirements::javascript('themes/my-theme/js/build/static/js/runtime~main.a8a9905a.js');
    Requirements::css('themes/my-theme/js/build/static/css/main.5c68d653.chunk.css');
}

For the purposes of this example I've used the hash names of the files that were created by create-react-app. It'd be easier to integrate in SilverStripe if you have a consistent filename like bundle.js or something.

You could also do this in your template:

# File: ./themes/my-theme/templates/Layout/ReactPage.ss
...
<% require javascript('themes/my-theme/js/build/static/js/main.ad956de7.chunk.js') %>
<% require javascript('themes/my-theme/js/build/static/js/2.6efc73d3.chunk.js') %>
<% require javascript('themes/my-theme/js/build/static/js/runtime~main.a8a9905a.js') %>
<% require css('themes/my-theme/js/build/static/css/main.5c68d653.chunk.css') %>

Load up your browser now and you'll see the React app running. It'll be a little broken, but for the sake of this example it's enough to show how to get a React app running on your page.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!