Cet article propose une solution complète pour résoudre les erreurs de chemin fréquentes dans le projet Cool Admin Midway. Vous apprendrez à diagnostiquer, corriger et prévenir ces problèmes pour assurer un démarrage fiable de votre application.
1. Architecture des chemins dans Cool Admin Midway
1.1 Structure des répertoires du projet
Cool Admin Midway adopte une architecture modulaire. Voici un aperçu de sa structure de dossiers :
src/
├── comm/ # Modules communs
│ ├── path.ts # Utilitaire de gestion des chemins
│ ├── port.ts # Configuration des ports
│ └── utils.ts # Fonctions utilitaires générales
├── config/ # Répertoire des fichiers de configuration
└── modules/ # Modules métier
├── base/ # Module de base
├── demo/ # Module d'exemple
└── ... # Autres modules métier
1.2 Module principal de gestion des chemins
Le fichier src/comm/path.ts est le cœur de la gestion des chemins. Il fournit des fonctions utilitaires pour centraliser et normaliser les opérations sur les chemins.
// Extrait de src/comm/path.ts
import { join } from 'path';
import { app } from 'midway';
export class PathUtil {
static getRootPath(): string {
return app.baseDir;
}
static getResourcePath(...paths: string[]): string {
return join(this.getRootPath(), 'src', 'resources', ...paths);
}
// Autres méthodes...
}
2. Types d'erreurs de chemin et diagnostic
2.1 Symptômes courants
- Erreur au démarrage : le projet plante immédiatement avec un message comme
Error: ENOENT: no such file or directory. - Erreur à l'exécution : le projet démarre, mais échoue lors d'une opération spécifique.
- Erreur intermittente : fonctionne en développement, mais échoue en production.
2.2 Causes fréquentes
- Mauvaise utilisation des chemins relatifs : résolution incohérente selon le contexte d'exécution.
- Dépendance aux variables d'environnement : variables non configurées dans certains enviornnements.
- Différences de système de fichiers : utilisation de séparateurs de chemin inadaptés (Windows vs Linux).
- Problèmes de build : erreurs de conversion de chemins lors de la compilation TypeScript.
3. Solutions détaillées
3.1 Utilisation de PathUtil pour centraliser la gestion
Voici un exemple comparatif :
// ❌ Mauvais : chemin relatif direct
import { readFileSync } from 'fs';
const config = JSON.parse(readFileSync('../../config/app.json', 'utf8'));
// ✅ Bon : utilisation de PathUtil
import { PathUtil } from '../comm/path';
import { readFileSync } from 'fs';
const configPath = PathUtil.getResourcePath('config', 'app.json');
const config = JSON.parse(readFileSync(configPath, 'utf8'));
3.2 Gestion des chemins dynamiques
Pour les chemins générés dynamiquement (ex : upload de fichiers) :
// src/modules/base/service/fileService.ts
import { Provide } from '@midwayjs/decorator';
import { PathUtil } from '../../../comm/path';
import { writeFile } from 'fs/promises';
@Provide()
export class FileService {
async saveUploadFile(fileName: string, content: Buffer): Promise<string> {
const date = new Date();
const subDir = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
const fullPath = PathUtil.getResourcePath('uploads', subDir, fileName);
await this.ensureDirExists(PathUtil.getResourcePath('uploads', subDir));
await writeFile(fullPath, content);
return fullPath;
}
private async ensureDirExists(dirPath: string): Promise<void> {
// Logique de création de répertoire...
}
}
</void></string>
3.3 Chemins dans les fichiers de configuration
Utilisez toujours des chemins relatifs dans les configurations, résolus à l'exécution via PathUtil :
// src/config/config.default.ts
export default {
uploadPath: 'resources/uploads', // Relatif, pas absolu
};
// Dans le service
import { Config } from '@midwayjs/decorator';
import { PathUtil } from '../comm/path';
export class UploadService {
@Config('uploadPath')
private uploadPath!: string;
getUploadPath(): string {
return PathUtil.getRootPath(this.uploadPath);
}
}
4. Prévention des erreurs de chemin
4.1 Règles à suivre
- Utilisez PathUtil pour toutes les opérations sur les chemins.
- Évitez tout chemin codé en dur dans le code métier.
- Dans les configurations, utilisez des chemins relatifs au répertoire racine.
- Utilisez
path.join()ou les méthodes de PathUtil pour concaténer les chemins.
4.2 Tests unitaires des chemins
// test/unit/comm/path.test.ts
import { PathUtil } from '../../../src/comm/path';
import { expect } from 'chai';
describe('PathUtil', () => {
describe('getResourcePath', () => {
it('should return correct resource path', () => {
const path = PathUtil.getResourcePath('config', 'app.json');
// Vérification...
});
});
});
4.3 Surveillance des erreurs de chemin
Ajoutez un middleware global pour capturer les erreurs de chemin :
// src/middleware/errorHandler.ts
import { Middleware, IMiddleware } from '@midwayjs/decorator';
import { Context } from 'egg';
@Middleware()
export class ErrorHandlerMiddleware implements IMiddleware<context> {
resolve() {
return async (ctx: Context, next: () => Promise<void>) => {
try {
await next();
} catch (err) {
if (err.code === 'ENOENT' || err.message.includes('path') || err.message.includes('directory')) {
ctx.logger.error('Erreur de chemin :', {
message: err.message,
stack: err.stack,
path: err.path || 'inconnu',
requestId: ctx.requestId,
timestamp: new Date().toISOString()
});
this.sendPathErrorAlert(err, ctx);
}
// Autres erreurs...
}
};
}
private async sendPathErrorAlert(err: Error, ctx: Context): Promise<void> {
// Logique d'alerte...
}
}
</void></void></context>
5. Étude de cas : d'un crash à la reprise
5.1 Problème
Après déploiement en production, le projet plante au démarrage avec :
Error: ENOENT: no such file or directory, open '/root/cool-admin/resources/templates/mail.html'
5.2 Diagnostic
Le service mail utilisait un chemin relatif qui fonctionnait en développement, mais échouait en production car le code compilé se trouve dans dist/.
// Code problématique
const templatePath = '../../resources/templates/mail.html';
const templateContent = fs.readFileSync(templatePath, 'utf8');
5.3 Correction
Remplacez par PathUtil :
import { PathUtil } from '../../../comm/path';
const templatePath = PathUtil.getResourcePath('templates', 'mail.html');
const templateContent = fs.readFileSync(templatePath, 'utf8');
5.4 Mesures préventives
- Ajoutez une vérification des chemins dans le processus de revue de code.
- Créez des tests unitaires pour les chemins.
- Intégrez une validation des chemins dans le pipeline CI/CD.
6. Conclusion
Les erreurs de chemin sont courantes dans Cool Admin Midway, mais peuvent être évitées en centralisant la gestion via PathUtil, en utilisant des chemins relatifs et en automatisant les tests. Suivez ces bonnes pratiques pour garantir un démarrage fiable de votre projet.