-
Notifications
You must be signed in to change notification settings - Fork 35
Description
Expanding one of the ideas from here - #276. I want to run this past the community before submitting a PR. Please share your thoughts.
Is your feature request related to a problem? Please describe.
The current enhanceApp only applies to the "outer" shell app that is used during development (for a nice HMR experience) and during build time to statically generate the app (as explained by @ElMassimo here - #213 (comment)). This is useful for certain use cases (like the usage of Vue plugins), such as what's discussed in this i18n support thread - #6. However, this "outer" app won't be available in the built app.
Currently, to use Vue plugins inside interactive Islands, the only way is to add the plugin inside the island, as discussed in these threads: #207, #259, #6 (reply in thread), #118 (comment), #213 (comment), #61 (comment). For example:
<script setup lang="ts">
import { getCurrentInstance } from 'vue'
import i18n from '~/services/i18n' // example
const app = getCurrentInstance().appContext.app
app.use(i18n)
</script>This method is very inconvenient, especially when using UI component libraries like Vuetify, where multiple Islands on the page require the same plugin setup. In such cases, we would need to add the following code to each Island. Even if moved outside the SFC, it's an overhead to import the same in each Island.
<script setup lang="ts">
import { getCurrentInstance } from 'vue'
import vuetify from '@/plugins/vuetify'
const app = getCurrentInstance().appContext.app
app.use(vuetify())
</script>Describe the solution you'd like
This feature request is for a new enhanceIslands API that can enhance islands by hooking into the island app's lifecycle:
- For Vue islands, allow
app.use(plugin)for plugins like Vuetify, Pinia, etc. - For Preact-like apps, wrap components in a custom
Providerto manage global data (i18n, themes, etc.). - Add any initial user state to the island.
- Enable shared state across all islands (using a common Pinia store).
- Support Vue/Runes/other reactivity across islands.
Unlike enhanceApp, which applies to the Vue shell, enhanceIslands would apply to all supported frameworks (e.g., Svelte, Preact, Solid). Users would need to manage conditional setup based on the framework-specific setup. Open to suggestions here 😄.
Here's one idea: we could use a simple iles attribute as a convention on the hydrated island definition, pass it to the app object, and use it within enhanceIslands to conditionally apply the required setup.
<IslandBackLink iles="back-link" href="/blog" client:load>I'm a bad example, sorry!</IslandBackLink>The API could look like this:
// app.ts
import { defineApp } from 'iles'
import { createI18n } from '~/logic/i18n'
import { createPinia } from 'pinia'
import { createVuetify } from 'vuetify'
const pinia = createPinia({/* config */})
const vuetify = createVuetify({/* config */})
export default defineApp({
enhanceIslands({ app }) {
if (app.iles === "hero-widget") { // Not required when using only one framework for islands
app.use(pinia)
app.use(vuetify)
}
if (app.iles === "back-link") {
// Some Preact setup for this island.
}
},
enhanceApp({ app }) {
const i18n = createI18n()
app.use(i18n)
i18n.global.locale = import.meta.env.VITE_LOCALE
},
})Describe alternatives you've considered
Astro had a similar API proposal (https://github.com/withastro/roadmap/blob/app-setup/proposals/0000-app-setup.md) to introduce an appEntrypoint for all supported frameworks as part of this PR: withastro/roadmap#326.
Later, Astro, in their community call stream on 4/10/22, decided to drop this idea and introduce appEntryPoint only for Vue via their Vue integration community call stream on 19/10/22 with this PR: withastro/astro#5075. In this, the user creates a _app.ts file and passes it as the appEntryPoint in their Astro Vue integration, which becomes a Vite virtual module, applying the "setup" (like vue.use plugins) for all Vue Islands.
Another related thread - withastro/roadmap#810
We already have the app.ts entry, and the new enhanceIslands can be framework-agnostic, which I believe will be simpler from a usage perspective. Moving to a "framework-specific" module would create a new "layer" in the workflow, which is what Astro follows (via their integrations API) which does have its advantages.
Additional context
This new enhanceIslands API added to the Iles core will be consumed by framework-specific createFrameworkIsland (e.g., createVueIsland) modules. For example, in: https://github.com/ElMassimo/iles/blob/main/packages/hydration/vue.ts
