docs(modules): update module structure to reflect tsup build workflow
- fix entry point path from `index.js` to `src/index.js` compiled to `dist/index.js` - update file tree to show `src/` as source root and `dist/` as published output - update `package.json` example with correct `main`, `exports`, `files`, and build scripts - add explanation of mandatory pre-build step before publish - document why JSX must be compiled (turbopackIgnore + Node native resolution) - add minimal `tsup.config.js` example with `bundle: false` and JSX loader - add verification step to check compiled output before publishing
This commit is contained in:
+56
-24
@@ -30,7 +30,7 @@ Pour chaque module trouvé, le core vérifie qu'il exporte les bons symboles, pu
|
||||
Le point d'entrée du package (`main` ou `exports["."]`) doit exporter :
|
||||
|
||||
```js
|
||||
// @zen/module-blog/index.js
|
||||
// @zen/module-blog/src/index.js (compilé vers dist/index.js par tsup)
|
||||
|
||||
export const manifest = {
|
||||
name: '@zen/module-blog',
|
||||
@@ -221,38 +221,70 @@ Toute variable requise par le module doit être déclarée dans `manifest.envVar
|
||||
|
||||
```
|
||||
@zen/module-blog/
|
||||
├── package.json # name: "@zen/module-blog", main: "./index.js"
|
||||
├── package.json # name: "@zen/module-blog", main: "./dist/index.js"
|
||||
├── tsup.config.js # build avec bundle: false, loader JSX, outbase: 'src'
|
||||
├── README.md # documente les env vars et la configuration
|
||||
├── index.js # exporte manifest, register, createTables, dropTables
|
||||
└── src/
|
||||
├── db.server.js # createTables/dropTables
|
||||
├── register-server.js # imports déclencheurs (chargé par register())
|
||||
├── api.server.js # routes API (registerApiRoutes)
|
||||
├── admin/
|
||||
│ ├── BlogAdminPage.client.js # registerPage + composant
|
||||
│ └── widgets/... # registerWidgetFetcher + registerWidget
|
||||
└── public/
|
||||
└── BlogPublicPage.js # registerPublicModulePage
|
||||
├── src/
|
||||
│ ├── index.js # exporte manifest, register, createTables, dropTables
|
||||
│ ├── db.server.js # createTables/dropTables
|
||||
│ ├── register-server.js # imports déclencheurs (chargé par register())
|
||||
│ ├── api.server.js # routes API (registerApiRoutes)
|
||||
│ ├── admin/
|
||||
│ │ ├── BlogAdminPage.client.js # registerPage + composant
|
||||
│ │ └── widgets/... # registerWidgetFetcher + registerWidget
|
||||
│ └── public/
|
||||
│ └── BlogPublicPage.js # registerPublicModulePage
|
||||
└── dist/ # généré par `npm run build` — c'est ce qui est publié
|
||||
```
|
||||
|
||||
Tout le code du module vit dans `src/`. Seul `index.js` reste à la racine — c'est le point d'entrée public lu par le core via `main: "./index.js"`. Il importe depuis `./src/` :
|
||||
|
||||
```js
|
||||
// index.js
|
||||
export async function register() {
|
||||
await import('./src/register-server.js');
|
||||
}
|
||||
export { createTables, dropTables } from './src/db.server.js';
|
||||
```
|
||||
|
||||
Le champ `files` dans `package.json` publie uniquement `index.js`, `src/`, `README.md` et `LICENSE` :
|
||||
Le champ `files` dans `package.json` publie **uniquement** `dist/`, `README.md` et `LICENSE` :
|
||||
|
||||
```json
|
||||
"files": ["index.js", "src", "README.md", "LICENSE"]
|
||||
{
|
||||
"main": "./dist/index.js",
|
||||
"exports": { ".": { "import": "./dist/index.js" } },
|
||||
"files": ["dist", "README.md", "LICENSE"],
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"prepublishOnly": "npm run build"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Build obligatoire avant publish
|
||||
|
||||
**Tout module `@zen/module-*` doit être pré-compilé avant publication.** Les fichiers du module ne doivent jamais contenir de JSX brut au runtime — le JSX doit être transformé en `React.createElement` (ou équivalent) par le build du module lui-même.
|
||||
|
||||
**Pourquoi.** Le core découvre les modules via `import(/* turbopackIgnore */ name)` dans [`discover.server.js`](../src/core/modules/discover.server.js) ; le commentaire `turbopackIgnore` est nécessaire pour empêcher Turbopack/Webpack de tenter de bundler un nom de package dynamique. Conséquence : tout l'arbre d'imports transitifs du module est résolu et exécuté par Node natif, **sans** transformation JSX. Un fichier `.client.js` qui contient `<MyComponent />` au runtime fait planter `register()` avec `Unexpected token '<'`.
|
||||
|
||||
Le module doit donc utiliser le même setup que `@zen/core` : un build `tsup` avec `bundle: false`, qui transforme JSX → JS standard tout en préservant la structure de fichiers (un fichier d'entrée → un fichier de sortie). Le `'use client'` est conservé en haut des fichiers `.client.js` compilés, ce qui permet à Next.js de respecter les frontières RSC quand le projet consommateur bundle le module.
|
||||
|
||||
### Exemple de `tsup.config.js` minimal
|
||||
|
||||
```js
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/**/*.js', 'src/**/*.jsx'],
|
||||
format: ['esm'],
|
||||
outDir: 'dist',
|
||||
outbase: 'src',
|
||||
bundle: false,
|
||||
splitting: false,
|
||||
clean: true,
|
||||
loader: { '.js': 'jsx' },
|
||||
jsx: 'automatic',
|
||||
});
|
||||
```
|
||||
|
||||
### Vérifier qu'un module est correctement compilé
|
||||
|
||||
Avant `npm publish`, ouvrir `dist/` et confirmer qu'aucun fichier ne contient de syntaxe JSX brute (chercher `<` suivi d'une majuscule). Tous les composants doivent apparaître sous forme d'appels `jsx(...)` ou `React.createElement(...)`.
|
||||
|
||||
---
|
||||
|
||||
## Cycle de vie complet
|
||||
|
||||
| Étape | Côté core | Côté module |
|
||||
|
||||
Reference in New Issue
Block a user