Expand my Community achievements bar.

SOLVED

Multiple React cras with aem-clientlib-generator

Avatar

Level 7

Hi folks,

I am integrating a bunch of different React CRAs into an AEM Page template. I am not using the "SPA Editor". I'm just integrating them directly with custom components,  but I am using the very handy aem-clientlib-generator npm plugin to   create the clientlibs from "build/static" and copy them into my AEM codebase.

 

I looked at the JS for each CRA and I see that the default CRA webpack configuration has "chunked" the JS.  There is one file called "main.<hash>.chunk.js", one called "runtime-main.<hash>.js" and one called "2.<hash>.chunk.js".

From what I can see, "main.<hash>.chunk.js" is my colleagues' React code and "2.<hash>.chunk.js" is the React libraries, react and react-dom.  Now I would like to share the "2.<hash>.chunk.js"  files for all the CRAs rather than have these react libraries duplicated lots of times in lots of clientlibs in my AEM page. The problem is when I look into the JS file, there is some webpack configuration i.e. a webpack object called webpackJsonp<CRA name>  at the top of the file so I can't throw away all of these files except one which was my original hope.

 

I know that this is more of a Webpack/react question than an AEM question but I was hoping someone might have come across this before and know what to do.

 

I noticed a similar but not quite the same question whereby the OP had  multiple CRAs with the same name which didn't work. 

 

thx

Fiona 

 

 

https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/aem-react-run-multiple-rea...

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @fionas76543059 ,

 

Please find below one of the approach to integrate multiple react projects in AEM without using SPA editor.

 

Firstly, we are using these configurations to get rid of chunk files so that js which is included in the zip package through your build process is main.hash.js

.rescriptsrc.js

module.exports = config => {
config.optimization.runtimeChunk = false;
config.optimization.splitChunks = {
cacheGroups: {
default: false
}
};
return config;
};

Now, through build process, different zip packages can be generated for different react applications (assuming different applications are in different repos) e.g react-application-1.zip , react-application-2.zip (these zip contains clientlibs to be installed in AEM)

 

In AEM, there will be a template page for react app, which can have a component to accept application id.

Depending on the configured application id, you can include client lib dynamically.

So, you will have to make sure that your application id and installed client lib category in AEM should match.

example application-id configured on the page - react-application-1 and your template will have this code

<c:when test="${not empty application-id}">
<cq:includeClientLib css="${application-id}" />
<%-- Javascript Application render --%>
<div id="${application-id}"></div>

Above is in jsp, you can change to sightly.

 

View solution in original post

8 Replies

Avatar

Correct answer by
Community Advisor

Hi @fionas76543059 ,

 

Please find below one of the approach to integrate multiple react projects in AEM without using SPA editor.

 

Firstly, we are using these configurations to get rid of chunk files so that js which is included in the zip package through your build process is main.hash.js

.rescriptsrc.js

module.exports = config => {
config.optimization.runtimeChunk = false;
config.optimization.splitChunks = {
cacheGroups: {
default: false
}
};
return config;
};

Now, through build process, different zip packages can be generated for different react applications (assuming different applications are in different repos) e.g react-application-1.zip , react-application-2.zip (these zip contains clientlibs to be installed in AEM)

 

In AEM, there will be a template page for react app, which can have a component to accept application id.

Depending on the configured application id, you can include client lib dynamically.

So, you will have to make sure that your application id and installed client lib category in AEM should match.

example application-id configured on the page - react-application-1 and your template will have this code

<c:when test="${not empty application-id}">
<cq:includeClientLib css="${application-id}" />
<%-- Javascript Application render --%>
<div id="${application-id}"></div>

Above is in jsp, you can change to sightly.

 

Avatar

Level 7
Thanks for that. I take it that either you have ejected the CRA or you are using some extra plugin that allows you to edit the webpack.config.js. Then you include the css in the component ( and the js I assume at the end of the component?). I can try this. Is it o.k. to put CSS into a <body> though?, I guess it works for you!. Thanks. I will try it out.

Avatar

Community Advisor

Hi @fionas76543059,

css is in the head and js in the body like this

<body>

<div id="react-application-1" >

<script src="/etc/clientlibs/react-application-1.js"></script>;

 

The root/app id of your react application should be matching above div id which in this case is "react-application-1"

Avatar

Level 7
OK. thanks. I get you now. We just have very simple static templates which don't have any components or component logic. You are putting the "div" with react id into the template whereas I was putting it into a component to be placed in a column control.

Avatar

Level 7
Hi, I found a way of doing what I wanted built on the npm plugin that you have above, "rescript". First I stop the chunking as you suggest. Then I added this to the ..rescriptsrc.js

Avatar

Level 7

config.output.libraryTarget = 'umd';

config.externals = {

   'react': {

       root: 'React',

      commonjs2: 'react',

      commonjs: 'react',

     amd: 'react' },

   'react-dom': {

      root: 'ReactDOM',

      commonjs2: 'react-dom',

      commonjs: 'react-dom',

      amd: 'react-dom' } }; return config ;

 

Then I included an umd version of react.js and react-dom.js in a new clientlib. I made the other clientlibs dependent on it. 

Now my react and react-dom code is not repeated when I have multiple react components on the page.