Liferay npm Bundler React Preset
The `liferay-npm-bundler-preset-reactjs` package, currently at stable version 2.0.1, provides a pre-configured solution for integrating React applications with the Liferay Portal ecosystem. It functions as a configuration preset for the `liferay-npm-bundler`, streamlining the setup by including necessary Babel presets like `babel-preset-liferay-standard` and Liferay-specific plugins such as `liferay-npm-bundler-plugin-replace-browser-modules`. This preset is designed to adapt standard React development workflows for Liferay's widget-based architecture and its unique AMD loading mechanism. It handles complexities like package namespacing for module isolation and facilitates dependency sharing across multiple widgets, which differentiates it from generic bundlers like Webpack that produce single JavaScript files. While the preset itself is stable, the underlying `liferay-npm-bundler` is officially deprecated as of Liferay 2024.Q4/Portal GA129 and is slated for removal, encouraging developers to transition to standard JavaScript build tools like esbuild or Webpack for future projects. This impacts the long-term relevance and future release cadence of this preset, which is now primarily in a maintenance or deprecated state.
Common errors
-
Uncaught ReferenceError: React is not defined
cause The React library was not correctly loaded or made available in the browser context where your Liferay widget attempts to render. This often happens if the `liferay-npm-bundler` failed to bundle/inject React, or if React is expected as a shared library but is missing.fixEnsure `react` and `react-dom` are properly declared as `devDependencies` in your `package.json`. Confirm that the `liferay-npm-bundler` processed your project successfully and generated the necessary `META-INF/resources` structure with React. If using Liferay's shared library feature, verify React is deployed and accessible as a global module. -
Webpack and liferay-npm-bundler loaders are not compatible.
cause This is a conceptual incompatibility rather than a direct error message. `liferay-npm-bundler` has its own loader and plugin system, inspired by Webpack but designed specifically for Liferay's AMD-based widget architecture, not for generating single JS bundles. Attempting to apply Webpack-specific configurations or loaders directly will fail.fixAvoid mixing Webpack configurations with `liferay-npm-bundler`. If you must use Webpack, configure it independently and then integrate its output into the Liferay development workflow without relying on `liferay-npm-bundler` for the actual bundling process. Alternatively, consider fully migrating to standard build tools as recommended by Liferay.
Warnings
- breaking The `liferay-npm-bundler` (the core tool this preset configures) underwent significant changes from v1.x to v2.x. Version 2.x introduced automatic AMD `define()` wrapping, package name prefixing for isolation, and improved peer dependency support. Projects migrating from older bundler versions may experience changes in module resolution and dependency management.
- deprecated The `liferay-npm-bundler` itself is officially deprecated as of Liferay 2024.Q4/Portal GA129 and is planned for future removal. Liferay recommends migrating to standard JavaScript tooling like esbuild, Vite, or Webpack using ES Modules (ESM) for new and existing projects, as this offers better performance and a more modern development experience.
- gotcha Older versions of the Babel loader used by `liferay-npm-bundler` (e.g., `liferay-npm-bundler-loader-babel-loader`) might have used Babel 6 internally. This can cause compatibility issues when attempting to use `@babel/` scoped presets and plugins designed for Babel 7+ with this preset.
- gotcha While the bundler handles some aspects of shared dependencies, effectively managing shared libraries like React across multiple Liferay widgets to prevent duplicate downloads and version conflicts still requires careful strategy. Improper handling can lead to performance degradation and larger bundle sizes.
Install
-
npm install liferay-npm-bundler-preset-reactjs -
yarn add liferay-npm-bundler-preset-reactjs -
pnpm add liferay-npm-bundler-preset-reactjs
Quickstart
# 1. Create a new Liferay-compatible project structure (example)
mkdir my-react-widget
cd my-react-widget
npm init -y
# 2. Install the React preset as a dev dependency
npm install --save-dev liferay-npm-bundler-preset-reactjs
# 3. Create a .npmbundlerrc file in your project root to use the preset
echo '{ "preset": "liferay-npm-bundler-preset-reactjs" }' > .npmbundlerrc
# 4. Create a simple React component file (e.g., src/main/resources/META-INF/resources/index.js)
mkdir -p src/main/resources/META-INF/resources
cat << EOF > src/main/resources/META-INF/resources/index.js
import React from 'react';
import ReactDOM from 'react-dom';
const App = () => {
return (
<div>
<h1>Hello from Liferay React Widget!</h1>
<p>This component is bundled using liferay-npm-bundler-preset-reactjs.</p>
</div>
);
};
// For Liferay portlets, components are often rendered into a specific DOM element
// and exported as a function for Liferay to invoke.
class MyReactPortlet extends React.Component {
render() {
return <App />;
}
}
export default function(portletId) {
ReactDOM.render(<MyReactPortlet />, document.getElementById(portletId));
}
EOF
# 5. Add React and ReactDOM as development dependencies
npm install --save-dev react react-dom
# Note: In a deployed Liferay DXP environment, React/ReactDOM are often provided as shared libraries.
# The bundler is designed to inject peer dependencies if needed.
# 6. (Optional) Run the Liferay npm bundler (requires 'liferay-npm-bundler' to be installed globally or as a dev dep)
# npm install -g liferay-npm-bundler
# liferay-npm-bundler