plasmicapp / plasmic

Visual builder for React. Build apps, websites, and content. Integrate with your codebase.
https://www.plasmic.app
MIT License
4.78k stars 384 forks source link

@plasmicapp/loader-svelte (SvelteKit) #18

Closed jbruxelle closed 7 months ago

jbruxelle commented 2 years ago

Hi,

What is the current progress for Svelte / SvelteKit support ? I tried using @plasmicapp/loader-svelte in a SvelteKit app without success (apparently due to vite).

Thanks !

magick93 commented 2 years ago

Did you manage to get plasmic to work with Sveltkit ?

jbruxelle commented 2 years ago

No I re-tried yesterday and i got an error from dependencies in loader/core so I gave up after a while... They should really do something for Sveltekit.

magick93 commented 2 years ago

What error did you get?

arnlen commented 2 years ago

Hi!

I'm currently testing the latest release of the @plasmicapp/loader-svelte package and I'm getting this error when trying to load a component:

'PlasmicRootProvider' refers to a value, but is being used as a type here.
Did you mean 'typeof PlasmicRootProvider'? ts(2749)

My source files, which are a copy/paste from this React documentation.

// $lib/plasmic-init.ts

import { initPlasmicLoader } from "@plasmicapp/loader-svelte";

const PROJECT_ID = "xxx";
const API_TOKEN = "xxx"

export const PLASMIC = initPlasmicLoader({
  projects: [
    {
      id: PROJECT_ID,
      token: API_TOKEN
    }
  ],
  preview: true,
})
// $routes/plasmicTestPage.svelte

<script lang="ts">
  import { PlasmicRootProvider, PlasmicComponent } from '@plasmicapp/loader-react';
  import { PLASMIC } from '$lib/plasmic-init';

  const COMPONENT_NAME = "Homepage";

  function MyComponent() {
    return (
      <PlasmicRootProvider loader={PLASMIC}>
        <PlasmicComponent component=COMPONENT_NAME />
      </PlasmicRootProvider>
    );
  }
</script>

Does anyone been able to get this Plasmic loader work within Sveltkit? We seem to be really close to working now!

arenzel commented 2 years ago

In your $routes/plasmicTestPage.svelte file:

  1. Change the import source from @plasmicapp/loader-react to @plasmicapp/loader-svelte
  2. Extract the function body to the HTML part of the file.

Your file should look like:

<script lang="ts">
  import { PlasmicRootProvider, PlasmicComponent } from '@plasmicapp/loader-svelte';
  import PLASMIC from '$lib/plasmic-init.svelte';

  const COMPONENT_NAME = "Homepage";
</script>

<PlasmicRootProvider loader={PLASMIC}>
  <PlasmicComponent component={COMPONENT_NAME} />
</PlasmicRootProvider>
arenzel commented 2 years ago

Following my last comment, I was trying to make it run by myself. With the implementation suggested by @arnlen, when trying to access the page, I'm getting a console full of errors:

Screenshot from the Bravo/Chrome console

Capture d’écran 2022-03-16 à 10 55 48

Transcript

PlasmicRootProvider.tsx:175 Uncaught TypeError: Cannot read properties of undefined (reading 'getLookup')
    at buildCss (PlasmicRootProvider.tsx:175:6)
    at PlasmicCss2 (PlasmicRootProvider.tsx:136:20)
    at renderWithHooks (react-dom.development.js:14985:18)
    at updateFunctionComponent (react-dom.development.js:17356:20)
    at updateSimpleMemoComponent (react-dom.development.js:17215:10)
    at updateMemoComponent (react-dom.development.js:17092:14)
    at beginWork (react-dom.development.js:19135:16)
    at HTMLUnknownElement.callCallback2 (react-dom.development.js:3945:14)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:16)
    at invokeGuardedCallback (react-dom.development.js:4056:31)
PlasmicComponent.tsx:40 Uncaught TypeError: Cannot read properties of undefined (reading 'getLookup')
    at PlasmicComponent (PlasmicComponent.tsx:40:37)
    at renderWithHooks (react-dom.development.js:14985:18)
    at mountIndeterminateComponent (react-dom.development.js:17811:13)
    at beginWork (react-dom.development.js:19049:16)
    at HTMLUnknownElement.callCallback2 (react-dom.development.js:3945:14)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:16)
    at invokeGuardedCallback (react-dom.development.js:4056:31)
    at beginWork$1 (react-dom.development.js:23964:7)
    at performUnitOfWork (react-dom.development.js:22776:12)
    at workLoopSync (react-dom.development.js:22707:5)
react-dom.development.js:20085 The above error occurred in the <PlasmicCss2> component:

    at PlasmicCss2 (http://localhost:3000/node_modules/.vite/@plasmicapp_loader-react.js?v=ffe1cc8a:8513:22)
    at PlasmicQueryDataProvider (http://localhost:3000/node_modules/.vite/@plasmicapp_loader-react.js?v=ffe1cc8a:5785:24)
    at PlasmicRootProvider (http://localhost:3000/node_modules/.vite/@plasmicapp_loader-react.js?v=ffe1cc8a:8489:30)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
react-dom.development.js:20085 The above error occurred in the <PlasmicComponent> component:

    at PlasmicComponent (http://localhost:3000/node_modules/.vite/@plasmicapp_loader-react.js?v=ffe1cc8a:9121:25)
    at PlasmicQueryDataProvider (http://localhost:3000/node_modules/.vite/@plasmicapp_loader-react.js?v=ffe1cc8a:5785:24)
    at PlasmicRootProvider (http://localhost:3000/node_modules/.vite/@plasmicapp_loader-react.js?v=ffe1cc8a:8489:30)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
arenzel commented 2 years ago

Hi!

I started over from a fresh installation to avoid any side/edge effect. After integrating the example code sent by @FMota0 on Slack, I'm getting this error:

image

Here is a step by step to reproduce:

1. Create & setup SvelteKit demo app

$ npm init svelte@next sveltekit-plasmic-integration
Need to install the following packages:
  create-svelte@next
Ok to proceed? (y) y

create-svelte version 2.0.0-next.126

Welcome to SvelteKit! [...]

✔ Which Svelte app template? › [SvelteKit demo app]
✔ Use TypeScript? … No / [Yes]
✔ Add ESLint for code linting? … [No] / Yes
✔ Add Prettier for code formatting? … [No] / Yes
✔ Add Playwright for browser testing? … [No] / Yes

Your project is ready!
✔ Typescript
  Inside Svelte components, use <script lang="ts">
[...]

$ npm i @plasmicapp/loader-svelte

2. Create Plasmic init file

// $lib/init.ts

import { initPlasmicLoader } from '@plasmicapp/loader-svelte';

const PROJECT_ID = "xxx";
const API_TOKEN = "xxx";

export const PLASMIC = initPlasmicLoader({
  projects: [
    {
      id: PROJECT_ID,
      token: API_TOKEN
    }
  ],
  preview: true
});

3. Add to a test route file

<!--  $routes/index.svelte -->

<script lang="ts">
  import Counter from '$lib/Counter.svelte';
  import { PLASMIC } from "$lib/init";  // <=== this import causes error
  import { PlasmicComponent, PlasmicRootProvider } from "@plasmicapp/loader-svelte";

  const COMPONENT_NAME = "Home";
</script>

4. Errors :boom:

In the browser

The requested module '/node_modules/isomorphic-unfetch/browser.js?v=84862a93' does not provide an export named 'default'

SyntaxError: The requested module '/node_modules/isomorphic-unfetch/browser.js?v=84862a93' does not provide an export named 'default'

In the terminal

22:52:55 [vite] Error when evaluating SSR module /node_modules/react/index.js?v=84862a93:
ReferenceError: module is not defined
    at /node_modules/react/index.js?v=84862a93:6:3
    at instantiateModule (/<path>/sveltekit-plasmic-integration/node_modules/vite/dist/node/chunks/dep-9c153816.js:56193:15)
22:52:55 [vite] Error when evaluating SSR module /node_modules/@plasmicapp/host/dist/host.esm.js?v=84862a93:
ReferenceError: module is not defined
    at /node_modules/react/index.js?v=84862a93:4:3
    at instantiateModule (/<path>/sveltekit-plasmic-integration/node_modules/vite/dist/node/chunks/dep-9c153816.js:56193:15)
22:52:55 [vite] Error when evaluating SSR module /node_modules/@plasmicapp/loader-react/dist/loader-react.esm.js?v=84862a93:
ReferenceError: module is not defined
    at /node_modules/react/index.js?v=84862a93:4:3
    at instantiateModule (/<path>/sveltekit-plasmic-integration/node_modules/vite/dist/node/chunks/dep-9c153816.js:56193:15)
22:52:55 [vite] Error when evaluating SSR module /node_modules/@plasmicapp/loader-svelte/src/index.js:
ReferenceError: module is not defined
    at /node_modules/react/index.js?v=84862a93:4:3
    at instantiateModule (/<path>/sveltekit-plasmic-integration/node_modules/vite/dist/node/chunks/dep-9c153816.js:56193:15)
22:52:55 [vite] Error when evaluating SSR module /src/lib/init.ts:
ReferenceError: module is not defined
    at /node_modules/react/index.js?v=84862a93:4:3
    at instantiateModule (/<path>/sveltekit-plasmic-integration/node_modules/vite/dist/node/chunks/dep-9c153816.js:56193:15)
22:52:55 [vite] Error when evaluating SSR module /src/routes/index.svelte:
ReferenceError: module is not defined
    at /node_modules/react/index.js?v=84862a93:4:3
    at instantiateModule (/<path>/sveltekit-plasmic-integration/node_modules/vite/dist/node/chunks/dep-9c153816.js:56193:15)
module is not defined
ReferenceError: module is not defined
    at /node_modules/react/index.js?v=84862a93:4:3
    at instantiateModule (/<path>/sveltekit-plasmic-integration/node_modules/vite/dist/node/chunks/dep-9c153816.js:56193:15)
arenzel commented 2 years ago

According to @FMota0, this issue is related to a bug in loader-svelte. I've created the new issue above to track its status. ☝️

✅ For now, a quick fix that works:

// $lib/init.ts

import { initPlasmicLoader } from '@plasmicapp/loader-react'; // <=== WORKAROUND HERE

export const PLASMIC = initPlasmicLoader({
  projects: [
    {
      id: <ID>,
      token: <API_TOKEN>
    }
  ],
  preview: true
});

A huge thanks to @FMota0 for its precious help: I can now move on! 🙏

rohanrajpal commented 2 years ago

Would love to have svelte kit support! Happy to contribute as well (if it is in the pipeline)

Korayem commented 1 year ago

I confirm that latest release of loader-svelte is working without using loader-react hacks

/utils/plasmic-init.ts

import { PUBLIC_PLASMIC_ID, PUBLIC_PLASMIC_TOKEN } from '$env/static/public';

import { initPlasmicLoader } from '@plasmicapp/loader-svelte';

export const PLASMIC = initPlasmicLoader({
  projects: [
    {
      id: PUBLIC_PLASMIC_ID, // ID of a project you are using
      token: PUBLIC_PLASMIC_TOKEN // API token for that project
    }
  ],
  // Fetches the latest revisions, whether or not they were unpublished!
  // Disable for production to ensure you render only published changes.
  preview: import.meta.env.DEV
});

/routes/[...catchall]/+page.server.ts SSR prerender FTW!! 🚀

import { PLASMIC } from '$utils/plasmic-init';
import { error } from '@sveltejs/kit';

/** @type {import('./$types').PageServerLoad} */
export async function load({ params }) {
  if (!params.catchall) throw error(404, '/');
  const plasmicPageData = await PLASMIC.maybeFetchComponentData(params.catchall, 'Component1', 'Component2');
  // This is some non-Plasmic catch-all page
  if (!plasmicPageData) throw error(404, '/');

  // Pass the data in as props.
  return {
    plasmicPageData
  };
}

/routes/[...catchall]/+page.svelte

<script>
  import { PlasmicComponent, PlasmicRootProvider } from '@plasmicapp/loader-svelte';
  import { PLASMIC } from '$utils/plasmic-init';
  import { page } from '$app/stores';
</script>

<PlasmicRootProvider loader={PLASMIC} prefetchedData={$page.data.plasmicPageData}>
  <PlasmicComponent component="Component1" componentProps={{ title: 'Hello from Mars' }} />
</PlasmicRootProvider>

<PlasmicRootProvider loader={PLASMIC} prefetchedData={$page.data.plasmicPageData}>
  <PlasmicComponent component="Component2" componentProps={{ title: 'Hello from Earth' }} />
</PlasmicRootProvider>

<PlasmicRootProvider loader={PLASMIC} prefetchedData={$page.data.plasmicPageData}>
  <PlasmicComponent component={$page.data.plasmicPageData.entryCompMetas[0].displayName} />
</PlasmicRootProvider>

This approach will match any page defined in plasmic You can do the same with specific page You can load plasmic components only (not whole pages) inside your existing sveltekit/svelte pages Calling maybeFetchComponentData() allows page to be prerendered on the server

Current problems I am facing:

/plasmic-host/+page.svelte

<script>
  export const prerender = false;
  export const ssr = false;
  import { PlasmicCanvasHost } from '@plasmicapp/loader-svelte';
  import { PLASMIC } from '$utils/plasmic-init';
  import { browser } from '$app/environment';
</script>

{#if browser}
  <PlasmicCanvasHost />
{/if}