Prototype rendering JavaScript components with Nuxt

Created on 23 April 2025, about 2 months ago

Overview

For 📌 First-class experience builder support Active we want to render JavaScript components with Nuxt.

This issue fork is used for prototyping possible solutions with SDCs.

📌 Task
Status

Active

Version

0.0

Component

Page builder

Created by

🇦🇹Austria fago Vienna

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @fago
  • 🇦🇹Austria fago Vienna

    During prototyping I identified the following challenges:
    * CORS issues. When loading static JS from another domain, we need to make Nuxt provide suiting CORS headers
    * Browser JS code cannot use helpers exposed by JS modules like Vue's h(). We could expose needed helpers manually from Nuxt

  • 🇦🇹Austria fago Vienna

    I figured there is another problem: The nuxt entry JS file always auto-mounts the Nuxt app to a the pre-configured DOM element, by default #__nuxt. This is not what we want size we need a custom component + mount target. Thus, I explored the option to extend Nuxt via module, such that it exposes an additional JS entry point / JS chunk along with the needed APIs. Unfortunately, I did not get this working because Nuxt has some nuxt-import protection that disallows importing nuxt directly in JS code, what breaks the custom-entry.

    So how else could it work? We could load each nuxt app in isolation, e.g. via iframes with srcDoc. But given that, I figured having one nuxt-app per preview-components is probably not the best idea resource-wise anyway. It would probably get tot resource hungry when there are ~100+ components on a page. Even worse with so many iframes.

    So I came up with a new idea. Use a single nuxt app + Vue teleports: https://vuejs.org/guide/built-ins/teleport As far as I understand, it should be possible to dynamically create teleports - all from one nuxt app - and use it to render dynamically created preview-Components. Will experiment with that next.

  • 🇦🇹Austria fago Vienna

    Got a working prototype with teleports. This seems to be the way to go! Now I need to brush it up a bit more.
    Need to figure out how to deal with the CORS issue best now. Maybe proxying through assets through the Drupal web-server would be the most convenient.

  • 🇦🇹Austria fago Vienna

    ok, I now got the prototype up and running without web-security issues.

    To test,
    - use the nuxtjs-drupal-ce module from https://github.com/drunomics/nuxtjs-drupal-ce/pull/347
    - run it via npm run dev -- --host 0.0.0.0
    - run XB fork from the branch with nuxt-component SDC
    - run it within a nginx/other-server that proxies _nuxt proxy to the frontend (this needs to move to a drupal module)
    - change nuxt-compontent.twig entry.js file path as necessary and clear drupal caches
    - see it working!

    Example proxy config for .ddev/nginx_full/nginx-site.conf:

    
    # Place this BEFORE the Drupal location blocks
    location ^~ /_nuxt/ {
        proxy_pass http://host.docker.internal:3000/_nuxt/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
    
    location ^~ /__vite_hmr {
        proxy_pass http://host.docker.internal:3000/__vite_hmr;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
    
  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Wow! Thanks for this awesome experimentation! 🤩

    Any chance you could share a screencast of it in action? 😇🙏

    I'm surprised to see this piggyback on top of SDC though — will a single SDC be used for all Nuxt JS components? 🤔 How will all available Nuxt JS components then be presented to content creators in XB?

  • 🇳🇱Netherlands balintbrews Amsterdam, NL

    I'm surprised to see this piggyback on top of SDC though

    I suggested to start prototyping like that, because if that works, there's a clear path towards a new component source plugin, which is exactly how we started experimenting with code components. 🙂

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Yep — that's what I figured 😁

    @fago: Let me know if/when you want pointers to turn this into a "proper" ComponentSource plugin that discovers all available Nuxt components and surfaces them.

    Note that this is not a public API yet, and it won't be at beta1 ( 🌱 Milestone 1.0.0-beta1: Start creating non-throwaway sites Active ). Issues about making that plugin type more well-defined can be found in https://www.drupal.org/project/experience_builder/issues/3520484#stable 🌱 [META] Production-ready ComponentSource plugins Active , and specifically 📌 Consider renaming the 'inputs' column on ComponentTreeItem to 'input' Active + 📌 Consider renaming ComponentSource plugins to ComponentType Active come to mind, but there are (many) more things to be ironed out. Still, I'd be happy to provide pointers for a Nuxt ComponentSource plugin, because having more (and more diverse!) examples helps ensure the abstraction is solid prior to it becoming a public API 🤞

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Added this to 🌱 [META] Support component types other than SDC Needs work :)

  • 🇦🇹Austria fago Vienna

    I suggested to start prototyping like that, because if that works, there's a clear path towards a new component source plugin, which is exactly how we started experimenting with code components. 🙂

    Yes, this is just for easy prototyping atm!

    @wim leers: Thanks a lot for the pointers and the summary! I'll definitely reach out for implementing the component-source plugin the right way, atm we are not reay for that yet, but I want to get there soon.

    This prototype is coming along well, but did not explore matching vue component metadata (props/slots) to required format yet, so we can use that nicely register components. So there is some experimentation needed here before we can move on the component-source part side of things.

    > Any chance you could share a screencast of it in action? 😇🙏
    It's not fancy yet, but I'll see what I can do!

  • 🇦🇹Austria fago Vienna

    Here a quick example screenshot!

Production build 0.71.5 2024