AMP package

Whoops, that made 0 sense because we donā€™t run stuff on the client in AMP of course so weā€™re not updating the DOM :man_facepalming:

Iā€™ve tested it and indeed react-helmet-async will just spit out 1 script tag on the server, even if we add call <Helmet> multiple times - for example for each iframe element in the page.

I notice that in some of the AMP processors in the previous version of the framework, we did some additional work like ensuring that iframes load over HTTPS or calculating the dimensions of the <video/> element.

I think the burden should be on the user to ensure that their content conforms to the AMP spec. Both because it could make the user think that their content is AMP-compliant when itā€™s not and also because there are probably too many restrictions on the AMP content for us to reasonably be able to catch all of them.

In case that we decide to still implement this, I think it should be beyond the scope of the beta version of the AMP package.

Another idea for the amphtml tags in the main site could be to add them with an option on the @frontity/yoast and @frontity/head-tags packages.

Hey folks, Iā€™ve started yesterday to work on Make @frontity/comscore-analytics AMP-aware [5pt] #712 and I have some questions that I think is worth mentioning here.

Regarding ā€œAMP-aware componentsā€, this is what is written down in the implementation proposal:

My questions are: Does the amp entry point still apply? Or this is how we should code this kind of components? Could we create two different components for each mode or is that not possible anymore?

Do you mean having both a src/index.js for React and a src/amp.js for AMP?

By the way, I was thinking that maybe doing the AMP-aware logic based on state.amp is not safe enough.

If a user uses by mistake some AMP settings in his main site it will break the site. For example:

const settings = {
  name: "main",
  state: {
    frontity: {
      url: "https://domain.com",
    },
    amp: {
      ssrFallback: true // <- Breaks the site because `state.amp` is truthy
    }
  },
  packages: [
    // ...
  ],
}

What about state.amp?.isAmp:

const Image = ({ state, src }) => {
  if (state.amp?.isAmp) {
    return <amp-img src={src} />;
  } else {
    return <img src={src} />;
  }
};

We could also use a mode setting in the frontity namespace:

const Image = ({ state, src }) => {
  if (state.frontity.mode === "amp") {
    return <amp-img src={src} />;
  } else {
    return <img src={src} />;
  }
};

Or just populate isAmp in the frontity namespace:

const Image = ({ state, src }) => {
  if (state.frontity.isAmp) {
      return <amp-img src={src} />;
        } else {
            return <img src={src} />;
              }
              };
              ```

Yes, I mean exactly that. :slightly_smiling_face:

I already implemented the changes using a src/amp.js file for the AMP version of the component but, after reading again the implementation proposal, I think thatā€™s not the way of doing it. :sweat_smile:

Also, reading the docs is like there are only two entry points: client.js and server.js (apart from index.js). In the case of AMP components, what would be the way of separate the AMP logic from the non-AMP logic? Or are developers forced to ship the same code for AMP and non-AMP components?

Well, we could still create two different components, one for client.js and another one for server.js, and add the AMP logic only to the server.js's component. Is this the expected approach?

The ā€œentry points settingā€ is part of the AMP IP, but it is not in the tasks for the beta.

So for now add the logic to the src/server.js file and once we have that feature we will move it to the src/amp.js file if necessary.

Thanks @luisherranz for the clarification, Iā€™ll do that. :+1:

No problem :slightly_smiling_face:

In the case of AMP components, what would be the way of separate the AMP logic from the non-AMP logic? Or are developers forced to ship the same code for AMP and non-AMP components?

:thinking: Someone who wants to have a amp website, will have to define a different set of settings, for that website. So, the codebase will be the same, but the processors and delivery will be different. Or is it allowed to include custom amp components as such the main website has different content than the amp one? AMP noob here :grinning_face_with_smiling_eyes:

Iā€™ve always imagined that if one wants to have an AMP aware website, by using our amp package, amp processors, and such, including custom components should not be something that would be possible?

Well, not custom components but a different implementation of the same component. If I remember correctly, in the past we did that for complex components like carousel galleries and such that needed a different implementation for AMP.

And, I guess it would be better if you donā€™t add the AMP code to the bundle as itā€™s only needed in SSR, right? For me, the easiest way to do so is having a different entry point. Thatā€™s my point.

Got it @David. Yeah, I think that would be great to avoid the bloat.

What do you think about this guys?

OK, I spent some time thinking about this and, from my point of view, the best option would be to use state.frontity.mode.

First, because it would be a setting that would change the behavior of all the packages installed; therefore, it makes sense to include it in the frontity namespace.

Second, because if we add different ā€œmodesā€ in the future, for me itā€™s not a good idea to have a different property or flag for each of them, as it should not be possible to have two different modes working at the same time, right? The state.frontity.mode prop would ensure that only a single mode is active.

In the case we want to implement props like state.amp.ssrFallback, what that property could do is to change the ā€œmodeā€ Frontity works in case some condition is reached.

And this is my opinion. :slightly_smiling_face:

Uhmā€¦ that is a good way to think about it. Thanks @david!

I agree that if we end up with different modes, it would be nicer to have a common property.

For example, a package that wants to do something only for the default mode would use:

if (state.frontity.mode === "default") {
  // ...
}

And if not it would have to know about all modes:

if (!state.frontity.isAmp && !state.frontity.isAnother && !state.frontity.isYetAnother) {
  // ...
}

That doesnā€™t scale.

The only limitation would be if there is a need to have two of those ā€œmodesā€ at the same time.

state.frontity.isAmp = true;
state.frontity.isAnother = true;

But I guess that makes less sense because mode will refer to the ā€œrendering modeā€, which will usually be only one.

Could you please elaborate this one? I didnā€™t get it :sweat_smile:

Haha, sorry. I think I didnā€™t choose the right words.

I just wanted to say that it would be useful that packages could change the Frontity mode on their own. And that behavior could be controlled using package-specific settings.

Maybe state.apm.ssrFallback is not a good example, I donā€™t know how that feature is going to be implemented. :sweat_smile:

I like using frontity.mode, you convinced me David :slightly_smiling_face: .

Just one thing, if we use it, should we make it more explicit and not use just mode? I am wondering that we are also talking about modes with the Embedded and Decoupled approaches for example, and I guess thatā€™s different right?

Yeah, thatā€™s totally right. We have to come up with a name that is not already used and mode is already used for Embedded and Decoupled modes. It would be confusing.

We cannot use state.frontity.rendering either because it is already used with ssr and csr values.

Any other ideas? :grinning_face_with_smiling_eyes:

Not really :grinning_face_with_smiling_eyes: Is there any ā€œmodeā€, apart from AMP, that you have in mind?