adobe / aem-spa-page-model-manager

Interface between Adobe Experience Manager and Single Page Application framework.
Apache License 2.0
33 stars 24 forks source link

NextJS | ModelManager.initializeAsync throws 404 on / [bug] #63

Closed giri-jeedigunta closed 3 years ago

giri-jeedigunta commented 3 years ago

Describe the bug Trying to bootstrap a new SPA using adobe model manager. When used ModelManager.initializeAsync it doesn't work as expected. Proxy call to AEM Cloud is not happening throws 404

Here is my implementation:

  React.useEffect(() => {
    ModelManager.initializeAsync({
      path: '/content/my-site/us/en.model.json'
    });
  }, []);

Package version 1.3.11

To Reproduce Steps to reproduce the behavior:

  1. yarn dev
  2. http://localhost:4100/
  3. See error 404 -> http://localhost:4100/content/my-site/us/en.model.json

Expected behavior

Screenshots NA

Additional context

sharanyavinod commented 3 years ago

@giri-jeedigunta FWIU, the SPA with the snippet above is running on a different domain than AEM ie. a remote SPA.ModelManager by itself will not handle proxying to a different domain and fetching the model from the path provided since the AEM instance is running elsewhere and unless mentioned otherwise, it will check on the same domain on which the SPA is running. There are 2 options -

  1. You can pass in a param to initializaAsync for a custom ModelClient(extending this) which accepts the path to your AEM instance and perform a similar fetch.
  2. Setup proxy logic to handle this model fetch. For React, we have a sample for local development here but should be more straightforward for Next.

More details of the use case/content package would be helpful in providing more clarity on the issue.

giri-jeedigunta commented 3 years ago

@sharanyavinod Thanks for shedding some light here. Could you please share a sample code for ModelClient? Also do I have to pass in the host name along with the path?

The proxying in the WKND example works without this additional config. We have the AEM on a remote domain and when we run the react app locally it works. I've setup the env variables for HOST, AUTHORIZATION, PAGE MODEL, ROOT...

I changed the App.js to below and it works ...

import { Page, withModel } from '@adobe/aem-react-editable-components';
import React from 'react';
import { Constants, ModelManager } from '@adobe/aem-spa-page-model-manager';

ModelManager.initializeAsync();

// This component is the application entry point
class App extends Page {
  render() {
    return (
      <div>
        <h1>Hello</h1>
      </div>
    );
  }
}

export default withModel(App);
giri-jeedigunta commented 3 years ago

Found an example here: https://github.com/adobe/aem-spa-page-model-manager/blob/052be877708296a386d6256c3af2c393eaff6eef/test/ModelClient.test.ts#L85 will try it out ...

sharanyavinod commented 3 years ago

@giri-jeedigunta Perfect! Also, 2 points to add -

  1. The WKND example above is for the default case. For editing a remotely hosted SPA on AEM, a better reference would be https://github.com/adobe/aem-guides-wknd-graphql/tree/feature/spa-editor/react-app.

  2. ModelManager initialization should not be done at the component level but at the app root - before the render. This documentation would be helpful in how to set up AEM and the SPA for remote editing.

giri-jeedigunta commented 3 years ago

Thanks @sharanyavinod... I will go through them. Also, I'm trying this out with NextJS so have to figure out the appropriate place to do the ModelManager.initializeAsync();

sharanyavinod commented 3 years ago

@giri-jeedigunta In a simple Next.js app, this might be an appropriate position - just before the App export.

giri-jeedigunta commented 3 years ago

@sharanyavinod I'm able to access the pageModel ... Here is my _app.tsx for anyone who is looking to do this in NextJS. Please do let me know if there is a better way of doing this ...

import React from "react";
import { Constants, ModelManager, ModelClient } from "@adobe/aem-spa-page-model-manager";
import { isEmpty } from 'lodash';

const modelClient = new ModelClient('https://blahblah.adobeaemcloud.com');
ModelManager.initializeAsync({
  path: '/content/blah-blah-site/us/en/home.model.json',
  modelClient
});

function App({ Component, pageProps }: AppProps) {

  const [pageModel, updatePageModel] = React.useState({});

  React.useEffect(() => {
    ModelManager.getData().then(data => {
      updatePageModel(data);
    });
  }, []);

  return !isEmpty(pageModel) && <Component {...pageProps} 
    cqChildren={pageModel[Constants.CHILDREN_PROP]}
    cqItems={pageModel[Constants.ITEMS_PROP]}
    cqItemsOrder={pageModel[Constants.ITEMS_ORDER_PROP]}
    cqPath={pageModel[Constants.PATH_PROP]}
  />;
}

export default App;

Just seeing 1 error / warning in the console:

Error on initialization - Error: Attempting to retrieve model data from a non-browser.
                Please provide the initial data with the property key model

What am I missing?

Kinbaum commented 3 years ago

@giri-jeedigunta Can you post your barebones Next.js implementation? I've tried something similar, but as soon as I place the AEMResponsiveGrid on my pages/index.js page, in AEM i run into an infinite loop with calls going out to http://localhost:4502/content/wknd-app/us/en/home/jcr:content/root/responsivegrid.model.json and the components added to the grid never render.

Here is a link to an issue I opened: https://github.com/adobe/aem-spa-project-core/issues/38

giri-jeedigunta commented 3 years ago

Hey @Kinbaum here is my code: nextjs-aem-poc

Some learnings from my experience:

Making it work with AEM:

Making it work outside AEM

import React from "react";
import { AppProps } from "next/app";
import {
  Constants,
  ModelManager,
  ModelClient,
} from "@adobe/aem-spa-page-model-manager";
import { isEmpty } from "lodash";
import { QueryClient, QueryClientProvider } from "react-query";
import "../styles/globals.css";
import { useRouter } from "next/router";

// Outside AEM
const modelClient = new ModelClient('http://localhost:4502');

// AEM
// ModelManager.initializeAsync();

// Outside AEM
ModelManager.initializeAsync({
  path: "/content/poc-spa-site/us/en/home.model.json",
  modelClient,
});

const queryClient = new QueryClient();

function App({ Component, pageProps }: AppProps) {
  const [pageModel, updatePageModel] = React.useState<any>({});

  React.useEffect(() => {
    ModelManager.getData().then((data) => {
      updatePageModel(data);
    }).catch(e => console.log('data error: ', e));
  }, []);

  return (
    !isEmpty(pageModel) && (
      <QueryClientProvider client={queryClient}>
        <Component
          {...pageProps}
          cqChildren={pageModel[Constants.CHILDREN_PROP]}
          cqItems={pageModel[Constants.ITEMS_PROP]}
          cqItemsOrder={pageModel[Constants.ITEMS_ORDER_PROP]}
          cqPath={pageModel[Constants.PATH_PROP]}
        />
      </QueryClientProvider>
    )
  );
}

export default App;

Also @sharanyavinod also have some examples on NextJs and AEM https://github.com/sharanyavinod/nextjs-sample-app and I see the ResponsiveGrid implementation

I saw you issue and you are almost there ... I hope this helps !

giri-jeedigunta commented 3 years ago

I also had to do some changes on AEM for nextjs to work. I had to add / hardcode <div id="__next"></div> inside one of the files for in-context editing to work.

Kinbaum commented 3 years ago

Thank you for sharing. Yeah there is a page template specific for next as a remote spa. But the docs are lacking. Unfortunately my site isn't purely static.

giri-jeedigunta commented 3 years ago

Thank you for sharing. Yeah there is a page template specific for next as a remote spa. But the docs are lacking. Unfortunately my site isn't purely static.

Once you have the base setup working inside and outside of AEM you can pretty much do anything... i have built some complex custom components... can definitely help you out if you are stuck.

Kinbaum commented 3 years ago

I tried following what was outlined by @sharanyavinod but it's still not working. The example there doesn't run. What do you make of this error?

Screen Shot 2021-07-06 at 2 21 27 PM Screen Shot 2021-07-06 at 2 22 27 PM

Seems like this error is preventing the drag and drop section from appearing.

giri-jeedigunta commented 3 years ago

@Kinbaum sorry to hear about the errors ... Not sure if I can help... the WKND POC ships a react code, try your changes over thr and see if everything working as expected and move piece by piece to NextJS. That kinda worked for me? Adding NextJS into the mix with poor to no documentation is a nightmare... May be start a discussion on this repo see if anyone else can help.