Example to show how Liferay Portlets can be developed with es module functionality

LIFERAY ES MODULE PORTLET

Sample repository to show how to use Liferay portlets with es modules.

Goal

Provide packages and components with a portlet and import them on runtime into a portlet. This should increase build time to a minimum because the liferay-npm-bundler doesn’t has to transpile files and only creates a jar file.

Explenation

The concept includes two modules. A provider module and a consumer modules. They are connected in a n to n relation.

Provider Module

A provider module exposes a package or component or basically anything through a portlet and serves the module then through an url.

To make this work, the following steps have to be done.

  1. Create an entry which is required for the liferay-npm-bundler.

    export default function main () {}

    See es-react-provider/src/entry.js as an example

  2. Create an index module which exports all modules which you’d like to provide through this module.

    import SampleModule from './modules/SampleModule' 
    import AnotherSampleModule from './modules/AnotherSampleModule'
    
    export { SampleModule, AnotherSampleModule }

    See es-react-provider/src/index.ts as an example

  3. Create two bundle processes which bundle the entry for the liferay-npm-bundler and the index.ts file.

    • The entry for the liferay-npm-bundler needs to be placed inside the build folder in the commonjs format for liferay to handle it correctly.
    • The bundled version of the index.ts needs to be placed inside the assets folder in the es format, preferably in the lib subfolder.

    See es-react-provider/rollup.config.js as an example

  4. Define the liferay-npm-bundler to

    • ignore the assets folder
    • make the portlet available through a defined url
    • create a jar file

    See es-react-provider/.npmbundlerrc as an example

Consumer Module

A consumer module uses the provided es modules from provider modules.

  1. Create an entry which includes a script html tag and imports a file.

    export default function main(entryParams) {
        const node = document.getElementById(entryParams.portletElementId);
    
        const script = document.createElement('script')
        script.setAttribute('type', 'module')
        script.innerText = `
            import { main } from '/o/es-react-portlet/lib/index.js';
            main(${JSON.stringify(entryParams)});
        `
    
        node.append(script)
    }

    See es-react-portlet/src/entry.ts as an example

  2. Create an index module, which (in our example) consumes some of the provided modules.

    import { SampleModule, AnotherSampleModule } from '/o/es-provider/lib/index.js'
    
    export function main (entryParams) { ... }

    See es-react-portlet/src/index.tsx as an example

  3. Create two bundle processes which bundle the entry for the liferay-npm-bundler and the index file.

    • The entry for the liferay-npm-bundler needs to be placed inside the build folder in the commonjs format for liferay to handle it correctly.
    • The bundled version of the index needs to be placed inside the assets folder in the es format, preferably in the lib subfolder.
    • The /o/es-provider/lib/index.js has to be defined to be an external module, so the bundler doesn’t throws an error on build time.

    See es-react-portlet/rollup.config.js as an example

  4. Define the liferay-npm-bundler to

    • ignore the assets folder
    • make the portlet available through a defined url
    • create a jar file

    See es-react-portlet/.npmbundlerrc as an example

Example

This workspace contains three modules.

Modules

es-react-provider

Contains and exposes react and react-dom as es modules.

es-react-components

Contains components which can be imported into a portlet.

es-react-portlet

Contains the actual portlet which uses the react and react-dom from the es-react-provider module and includes a sample component from the es-react-components module.

How to run

To run this example, all modules need to be built and deployt onto a liferay instance. After that, everything should work as expected.

GitHub

View Github