Working with Liferay and ReactJS Portlets

Development Tips and Troubleshooting

Back in March 2020, we were assigned to create a POC that involves integrating Liferay and ReactJS. As a newcomer to Liferay myself, I had plenty of questions and was unsure of what I was doing most of the time. This blog post aims to highlight the lessons learned and the challenges encountered during the development of that POC.

As for specifications, the ReactJS POC needs to support both admin and user views. The ReactJS component will be the front-end, and will use Liferay's Headless APIs as a means of communication. With all things considered, the team decided that it would be best to develop a standalone ReactJS application, and then later integrate it to Liferay once we come to a comfortable working base.


Lesson 1: Think in Portlets

During the development of the standalone app, both user and admin views were implemented basing on the idea that user credentials would determine the view. This would be problematic later on during integration since Liferay has different portlets for each view.  A better approach would've been doing 2 separate standalone apps, 1 for each user and admin views.

Lesson 2: Utilize Different Portlet Types

During the integration phase, we had to use different portlet types for both the user and admin views. For the user view, integration was pretty straightforward. However, the admin view needed to be slightly tweaked for it to be displayed correctly on the control panel.


Troubleshooting React Portlet Integration Errors

The team spent a lot of time debugging  the different errors we encountered during the integration phase. Most of these errors are shown on the browser's console screen so keep an eye out for them!

Error: Missing dependency for .css, .scss, or static files

This is caused when the liferay-npm-bundler-loaders are not properly configured. To fix this, make sure you have the necessary liferay-npm-bundler-loaders in your package.json and add them to the .npmbundlerrc file. See blow for sample code changes.

Sample .npmbundlerrc

{
  "sources": ["src", "assets"],
  "rules": [
    {
      "test": "\\.json$",
      "exclude": "node_modules",
      "use": ["json-loader"]
    },
    {
      "test": "\\.scss$",
      "exclude": "node_modules",
      "use": ["sass-loader", "css-loader"]
    },
    {
      "test": "^assets/",
      "exclude": "node_modules",
      "use": ["copy-loader"]
    }
  ],
  "create-jar": {
    "output-dir": "dist",
    "features": {
      "js-extender": true,
      "web-context": "/portlet-name"
    }
  },
  "dump-report": true
}

Sample package.json (snippet)

 "devDependencies": {
    "liferay-npm-build-support": "2.18.4",
    "liferay-npm-bundler": "2.18.4",
    "liferay-npm-bundler-loader-copy-loader": "2.18.4",
    "liferay-npm-bundler-loader-css-loader": "2.18.4",
    "liferay-npm-bundler-loader-json-loader": "2.18.4",
    "liferay-npm-bundler-loader-sass-loader": "2.18.4",
    "liferay-npm-bundler-loader-style-loader": "2.18.4",
  },

Error: Missing version constraints for "package-name" in package.json

This error most likely involves a missing entry on the dependencies part of your package.json. Make sure that all libraries being imported by your Javascript files are listed there.

Error: Missing version constraints for babel-polyfill

One error we noticed during development is that Liferay's npm bundler does not work very well with babel-polyfill. In order to resolve this, we have opted to use the newer alternative; core-js and regenerator-runtime.

To make thee change, remove the babel-polyfill entry from devDependencies in package.json and run:

npm install --save regenerator-runtime core-js

After that's done, remove the "import babel-polyfill" on your entrypoint (index.js / App.js) and replace it with the following:

import "core-js/stable";
import "regenerator-runtime/runtime";

Notes:

I'd like dedicate this part to thank everyone who has helped the team during development. I hope this will be of help to anyone who's currently working with Liferay and ReactJS. If you have any questions or clarifications, don't hesitate to contact me or leave a comment so we can both learn.

Blogs

I have this problem:

ERROR:Missing version constraints for my-app3$fs in package.json of my-app3$jspdf@2.1.1'

 

And this my package.json

"dependencies": {

        "@material-ui/core": "^4.11.1",

        "@material-ui/icons": "^4.9.1",

        "jspdf": "^2.1.1",

        "react": "16.8.6",

        "react-bootstrap": "^1.4.0",

        "react-dom": "16.8.6",

        "react-router-dom": "^5.2.0"

    },