Liferay 7.4中如何在其他React Portlet复用共享React组件?
Liferay中React可复用组件的正确实现方案
你当前操作的问题
- 直接跨Portlet导入源码文件:Liferay的OSGi模块是隔离的,不能通过相对路径直接引用其他Portlet的源码文件,这会导致模块加载器无法解析依赖,出现
Exports is not defined和加载失败的错误。 - 未按Liferay模块规范导出可复用组件:你的可复用组件没有被打包成可被其他模块识别的OSGi模块或者npm包,无法被消费端Portlet正确加载。
正确实现方案(两种可选)
方案一:基于OSGi模块的组件复用(Liferay原生方式)
改造可复用组件为OSGi模块
- 在可复用组件的项目中,确保
bnd.bnd文件配置正确,将组件打包成js-module类型的OSGi模块:Bundle-SymbolicName: com.example.reusable-react-component Bundle-Version: 1.0.0 Web-ContextPath: /reusable-react-component Export-Package: com.example.reusable.component Js-Module: src/main/resources/jsx/ReusableComponent.js - 修改
ReusableComponent.js,用Liferay的模块导出方式暴露组件:import React from 'react'; const ReusableComponent = () => { return <div>This is a reusable React component.</div>; }; // 用Liferay的模块导出API暴露组件 Liferay.Loader.define('com.example.reusable-react-component/src/main/resources/jsx/ReusableComponent', ['exports', 'react'], function (exports, React) { Object.defineProperty(exports, '__esModule', {value: true}); exports.default = ReusableComponent; });
- 在可复用组件的项目中,确保
消费端Portlet导入组件
- 在消费端Portlet的
Portlet1.js中,通过Liferay的模块加载器导入:import React from 'react'; import ReusableComponent from 'com.example.reusable-react-component/src/main/resources/jsx/ReusableComponent'; const Portlet1 = () => { return ( <div> <h2>Portlet 1</h2> <ReusableComponent /> </div> ); }; export default Portlet1; - 确保消费端Portlet的
bnd.bnd中声明对可复用模块的依赖:Require-Bundle: com.example.reusable-react-component;bundle-version="[1.0.0,2.0.0)"
- 在消费端Portlet的
方案二:基于npm包的组件复用(适合用Liferay npm工具链的场景)
将可复用组件打包为npm包
- 在可复用组件项目中初始化npm项目,修改
package.json:{ "name": "@example/reusable-react-component", "version": "1.0.0", "main": "dist/ReusableComponent.js", "peerDependencies": { "react": "^17.0.0 || ^18.0.0" } } - 用babel打包组件,配置
babel.config.json:{ "presets": ["@babel/preset-env", "@babel/preset-react"] } - 执行打包命令生成
dist目录:npx babel src/main/resources/jsx/ReusableComponent.js --out-dir dist - 将npm包发布到私有npm仓库或者本地link。
- 在可复用组件项目中初始化npm项目,修改
消费端Portlet安装并使用组件
- 在消费端Portlet的npm项目中安装依赖:
npm install @example/reusable-react-component - 在
Portlet1.js中正常导入使用:import React from 'react'; import ReusableComponent from '@example/reusable-react-component'; const Portlet1 = () => { return ( <div> <h2>Portlet 1</h2> <ReusableComponent /> </div> ); }; export default Portlet1; - 用Liferay npm工具链打包部署消费端Portlet:
npm run build blade deploy
- 在消费端Portlet的npm项目中安装依赖:
额外注意事项
- 确保React版本在可复用组件和消费端Portlet中保持一致,避免版本冲突。
- 如果使用Liferay 7.4+,推荐使用
@liferay/js-toolkit来构建React模块,它会自动处理模块导出和依赖问题。
内容的提问来源于stack exchange,提问作者Geek
相关产品推荐
相关产品推荐

