Évolution future vers un module Nuxt 4
La phase actuelle publie QForm Builder comme Nuxt Layer npm.
La prochaine évolution naturelle consiste à créer un vrai module Nuxt 4 :
export default defineNuxtConfig({
modules: ['@vevedh/nuxt-qform-builder'],
qformBuilder: {
prefix: '',
installPinia: true,
installFormKit: true,
installQuasar: true,
injectCss: true
}
})Références officielles :
- Modules Nuxt : https://nuxt.com/docs/4.x/guide/modules
- Nuxt Kit modules : https://nuxt.com/docs/api/kit/modules
- Recettes module : https://nuxt.com/docs/4.x/guide/modules/recipes-basics
Différence entre layer et module
| Sujet | Nuxt Layer | Module Nuxt 4 |
|---|---|---|
| Activation | extends | modules |
| Effort actuel | faible | plus élevé |
| Contrôle des options | limité | excellent |
| Isolation des routes de démo | possible | naturelle |
| Installation automatique de modules | héritée du layer | contrôlée par installModule() |
| Préfixe de composants | peu pratique | simple via addComponentsDir() |
| API publique | conventionnelle | explicite |
| Meilleur choix long terme | bon | excellent |
Pourquoi ne pas convertir tout de suite ?
Le projet est déjà exploitable comme layer.
La conversion en module demande une migration plus profonde :
src/
├── module.ts
└── runtime/
├── assets/
├── components/
├── composables/
├── constants/
├── stores/
├── types/
└── utils/Cela implique aussi de remplacer progressivement les imports internes trop liés au layer.
Structure cible du futur module
nuxt-qform-builder/
├── src/
│ ├── module.ts
│ └── runtime/
│ ├── assets/
│ ├── components/
│ ├── composables/
│ ├── constants/
│ ├── stores/
│ ├── types/
│ └── utils/
├── playground/
│ ├── app.vue
│ └── pages/
├── docs/
├── package.json
└── README.mdOptions cible
export interface QFormBuilderModuleOptions {
prefix: string
installPinia: boolean
installFormKit: boolean
installQuasar: boolean
injectCss: boolean
exposeTypes: boolean
}Exemple cible de module.ts
import {
addComponentsDir,
addImportsDir,
createResolver,
defineNuxtModule,
installModule
} from '@nuxt/kit'
export interface QFormBuilderModuleOptions {
prefix: string
installPinia: boolean
installFormKit: boolean
installQuasar: boolean
injectCss: boolean
}
export default defineNuxtModule<QFormBuilderModuleOptions>({
meta: {
name: '@vevedh/nuxt-qform-builder',
configKey: 'qformBuilder',
compatibility: {
nuxt: '^4.0.0'
}
},
defaults: {
prefix: '',
installPinia: true,
installFormKit: true,
installQuasar: true,
injectCss: true
},
async setup(options, nuxt) {
const resolver = createResolver(import.meta.url)
if (options.installPinia) {
await installModule('@pinia/nuxt')
}
if (options.installFormKit) {
await installModule('@formkit/nuxt')
}
if (options.installQuasar) {
await installModule('nuxt-quasar-ui', {
lang: 'fr',
iconSet: 'material-icons',
plugins: ['Dialog', 'Loading', 'Notify']
})
}
addComponentsDir({
path: resolver.resolve('./runtime/components'),
prefix: options.prefix,
pathPrefix: false,
global: true
})
addImportsDir(resolver.resolve('./runtime/composables'))
addImportsDir(resolver.resolve('./runtime/stores'))
addImportsDir(resolver.resolve('./runtime/utils'))
if (options.injectCss) {
nuxt.options.css.push(resolver.resolve('./runtime/assets/scss/index.scss'))
}
}
})Refactors nécessaires avant module
1. Stabiliser les imports internes
Dans un layer, ~ pointe naturellement vers la source du layer pendant son développement.
Dans un module, le runtime est publié dans src/runtime. Il faut donc privilégier :
import type { FormBuilderSchema } from '../types/form-builder'ou créer des alias de module :
#qform-builder/types
#qform-builder/runtime2. Exporter les types publics
Objectif futur :
import type {
FormBuilderSchema,
FormBuilderValues,
FormBuilderSavePayload
} from '@vevedh/nuxt-qform-builder/types'3. Rendre le catalogue extensible
Le module doit exposer une option :
qformBuilder: {
catalog: [],
configPanels: {}
}ou un système de plugin runtime :
export default defineNuxtPlugin(() => {
defineQFormElement({
type: 'nfz-service-select',
label: 'Sélecteur service NFZ',
schema: {},
configPanel: () => import('./NfzServiceSelectConfig.vue')
})
})4. Séparer builder et viewer
Le futur module pourra permettre :
qformBuilder: {
components: {
builder: true,
viewer: true
}
}Cela permettra à une app runtime légère d’installer seulement FormViewer.
Roadmap module
Phase M1 — packaging module minimal
- créer
src/module.ts; - déplacer
app/*verssrc/runtime/*; - enregistrer composants, composables et stores ;
- garder un
playgroundde test ; - publier sous
@vevedh/nuxt-qform-builder.
Phase M2 — options configurables
prefix;injectCss;installQuasar;installFormKit;installPinia;- activation séparée builder/viewer.
Phase M3 — parité Vueform Builder
- custom elements ;
- custom config panels ;
- catalog public ;
- conditions avancées ;
- validation avancée ;
- i18n ;
- theming ;
- export/import UI ;
- génération depuis Zod/NFZ/IA.
Convention à conserver
La phase layer npm doit rester stable tant que le module n’est pas publié.
Le module Nuxt 4 devra être une évolution contrôlée, pas un remplacement brutal :
@vevedh/qform-builder-layer # phase actuelle stable
@vevedh/nuxt-qform-builder # évolution future module Nuxt 4