Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore property set if document is not present (SSR). #17

Closed
phlegx opened this issue Jun 12, 2024 · 7 comments · Fixed by #19
Closed

Ignore property set if document is not present (SSR). #17

phlegx opened this issue Jun 12, 2024 · 7 comments · Fixed by #19

Comments

@phlegx
Copy link

phlegx commented Jun 12, 2024

Describe the bug
If using in an SSR environment document (/index.ts#L10) is not present. So, the plug-in should ignore setProperty if document is not present.

Error when evaluating SSR module /src/views/Index.vue: failed to import "@capacitor-community/safe-area"
|- ReferenceError: document is not defined
    at setProperty (/.../node_modules/@capacitor-community/safe-area/dist/plugin.cjs.js:12:5)

To Reproduce
Steps to reproduce the behavior:

  1. Using Vue with SSR environment.
  2. Install package @capacitor-community/safe-area
  3. Add config to capacitor.config.ts
  4. Add package with import '@capacitor-community/safe-area'

Expected behavior
It should work for web in a SSR environment.

if (typeof window !== 'undefined') {
  setProperty('top');
  setProperty('left');
  setProperty('bottom');
  setProperty('right');
}
@tafelnl
Copy link
Member

tafelnl commented Jun 13, 2024

I don't have any experience in using Capacitor in an SSR environment. On this line the document is also being called. Are you saying that's fine like that?

@phlegx
Copy link
Author

phlegx commented Jun 13, 2024

In my opinion, yes. SSR loads only js scripts for web (Node JS server) and not related code of Android and iOS. Other extensions for React, Vue, etc. that uses window.* handles code sequences in the same way to distinguish between SSR environment and non-SSR.

@tafelnl
Copy link
Member

tafelnl commented Jun 17, 2024

But it's still important to call setProperty('*') at some point in time. Because that's where the fallback is set. Which is especially important for iOS and web. So when to call these?

@phlegx
Copy link
Author

phlegx commented Jun 17, 2024

If you want to still call setProperty() then we need to check if document exists inside setProperty /src/index.ts:

function setProperty(position: 'top' | 'left' | 'bottom' | 'right') {
  if (typeof window === 'undefined') return

  document /* is window.document */
    .querySelector<HTMLElement>(':root')
    ?.style.setProperty(
      `--safe-area-inset-${position}`,
      `max(env(safe-area-inset-${position}), 0px)`,
    );
}

or

function setProperty(position: 'top' | 'left' | 'bottom' | 'right') {
  if (typeof window !== 'undefined' && 'document' in window) {
    document /* is window.document */
      .querySelector<HTMLElement>(':root')
      ?.style.setProperty(
        `--safe-area-inset-${position}`,
        `max(env(safe-area-inset-${position}), 0px)`,
      );
  }
}

@tafelnl
Copy link
Member

tafelnl commented Jun 17, 2024

Yeah, I can implement such a check, I understand that. But it would only prevent the error being thrown. It wouldn't solve the actual problem. The actual problem is that those fallback CSS variables should be injected at some point in time - the earlier the better. Since Capacitor in combination with SSR is a not so usual use case, I have no idea where to inject the variables instead. I don't think there is a universal hydration method or document ready listener

@phlegx
Copy link
Author

phlegx commented Jun 18, 2024

I understand, but it is not possible to set this CSS variables on SSR (server side) because there is no window. On client side (web), the code is executed (because of presence of window) and the CSS variables are set. Therefore it should work anyway. I have per default set the CSS variables, that are overwritten by @capacitor-community/safe-area on the client side. It works!

 :root {
  --safe-area-inset-bottom: 0;
  --safe-area-inset-left: 0;
  --safe-area-inset-right: 0;
  --safe-area-inset-top: 0;
}

@tafelnl
Copy link
Member

tafelnl commented Jun 18, 2024

Opened a PR that should solve your problem #19

By the way, you probably shouldn't be doing this:

 :root {
  --safe-area-inset-bottom: 0;
}

Because on iOS and web, you now lost the fallback to the natively supported env(safe-area-inset-*) CSS variables. Instead, you should be doing something like this:

 :root {
  --safe-area-inset-bottom: max(env(safe-area-inset-bottom), 0px);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants