Developed a rest api client to query Plone 6 backend [GSoC'23]

Project Description

The project aims to develop a restapi client written in TypeScript and built on the top of Tanstack Query to query Plone 6 backend. It is possible to use this client in React/Vue/Solid/Svelte projects.

Community Benefits

This project will benefit the community by discontinuing the use of the deprecated AsyncConnect library and migrating the Server State handling to TanStack Query. This will improve data fetching capabilities and streamline the development process.

Example usage

Here's an example of how the new approach can be implemented using the @plone/client library:


import ploneClient from '@plone/client';

const client = ploneClient.initialize({

apiPath: 'http://localhost:8080/Plone',

});

const { useGetContent } = client;

const { data, isLoading } = useGetContent({ path: pathname });

This code demonstrates the utilization of the useGetContent action hook in Volto. For more details, refer to the quick-start guide.

Key Features

  • The usage of @tanstack/react-query provides powerful state management capabilities and brings caching benefits.
  • Thorough TypeScript integration ensures strong typing throughout the project.
  • The incorporation of Zod offers runtime validation for JavaScript projects, extending its utility beyond TypeScript.
  • Compatibility extends not only to React-based frameworks but also to various JavaScript frameworks.
  • Adoption is straightforward and effortless.
  • A comprehensive collection of actions provides extensive functionality.
  • Detailed documentation ensures ease of understanding and implementation.

Framework-Agnostic Approach

The inclusion of hooks supports frameworks like react and nextjs, and the library can be utilized by other frameworks by using query and mutation objects with tanstack query directly.

Modes of Usage

This package offers two distinct usage methods:

  1. React-based frameworks can directly utilize the actions via custom hooks.
  2. Other frameworks can employ the query creator function in conjunction with the suitable version of TanStack Query.

Possible future improvements:

Separate out the react-query part from @plone/client into a separate package

This would make the integration of @plone/client into other projects like volto cleaner. We could create a wrapper over @tanstack/react-query that provides our enhanced ploneClient (just like queryClient in @tanstack/react-query) to the entire package via react-context.

SSR support in @plone/client

For implementing SSR with TanStack Query, the challenge is to figure out the data dependencies for a component that is rendered on the server.

We can consider the following approaches to implement SSR:

  1. Manual approach: In this approach, Server-Side Rendering (SSR) is achieved by explicitly controlling the prefetching and caching of queries using the TanStack Query library in conjunction with the @plone/client library.
    Refer to official docs for more information: SSR | TanStack Query Docs

  2. Automatic caching approach: In this approach we detect @plone/client use in components and cache automatically on the server. It involves rendering the component twice on the server.

POC using the approach described below: GitHub - hemant-hc/tanstack-query-ssr-example: Example React React Server-Side Rendering (SSR) application using react-grid-system and react-i18nify

The inspiration for this approach came from useSSE.

For a more comprehensive view of potential enhancements, follow this link

Issues faced and their resolution:

  • Initially, I started developing this package from a react based approach. But, since this package is supposed to work with different frameworks. I decide to take a framework agnostic approach first and build the react-specific parts on top of it

  • In the Proof of Concept (PoC) phase, the initial API fetch layer relied on legacy Volto code and utilized superagent. However, this posed issues due to incompatibility with frameworks like Next.js. After evaluating alternatives, I switched to using axios, a widely supported library with robust features. With guidance from Mr. Victor, the blueprint for refactoring was established. Leading to the seamless integration of axios.

  • When implementing actions, testing brought challenges. Test execution order impacted outcomes, causing test flakiness. To address this, I introduced a new test configuration, ensuring ordered and isolated test runs for stable testing.

  • As the project neared completion, I focused on implementing custom hooks for actions. I realized that most of the work had already been done and I could simply create a utility function that would receive the existing query or mutation functions and return a custom hook based on them. This made the process of implementing custom hooks a lot easier and faster.

Accessing Project Contributions

For access to project contributions, kindly follow this link.

Words of Thanks to Mr. Victor and the Plone Foundation

I extend my heartfelt gratitude to my assigned mentor, Mr. Victor, and the Plone Foundation for granting me the invaluable opportunity to engage in this project. Mr. Victor's unwavering guidance and support facilitated each step of my contribution journey, making the entire process significantly smoother. The Plone Foundation's extensive documentation proved to be an invaluable resource, offering me indispensable assistance throughout the project duration.

5 Likes

You can find the documentation in:

This is the late August 2023 Release (alpha-5):

This is the Github repo:

and this repo is the demo for Plone on a NextJS app.

Feedback required! We will issue a final 1.0.0 before the conference.

sounds interesting. How do I apply in Plone frontend Volto?

Tips welcome.

/Users/katjasuss/Volto/volto/build/server.js:115605
module.exports = require("@plone/client");
                 ^
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/katjasuss/Volto/volto/node_modules/@plone/client/dist/plone-client.umd.js from /Users/katjasuss/Volto/volto/build/server.js not supported.
plone-client.umd.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename plone-client.umd.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /Users/katjasuss/Volto/volto/node_modules/@plone/client/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

@ksuess Interesting, you imported it in server.js I assume.

We still have a lot to play with it and tune it up, so it's usable in all kind of environments that we'd like to use it. We decided it to be a module package, but that could have unexpected consequences in non-modules commonjs world.

Fixed in Release @plone/client 1.0.0-alpha.6 · plone/plone.restapi-client · GitHub

Please try it out!

1 Like

Awesome! It works with a minimal adjustment on initialization of the client.
So, now, no more actions and reducers? Can we have the @plone/client in Volto already prepared? That would be nice. Far less boilerplate.

See the client in action in Volto: [Do not merge] POC for @plone/client integration with Volto by hemant-hc · Pull Request #5133 · plone/volto · GitHub