Explorer les étapes pour scinder les packages et configurations frontend dans une application e-commerce de type marketplace.
Dans cet article, nous allons explorer les étapes pour scinder les packages et configurations frontend dans une application e-commerce de type marketplace. Ce projet est structuré autour de trois interfaces distinctes :
L'objectif est de découpler les configurations de ces trois espaces afin de permettre une évolution indépendante des librairies utilisées. Comme il s'agit d'un projet existant, nous cherchons une transition progressive sans refonte complète. De plus, nous souhaitons conserver les assets dans le répertoire resources
de Laravel.
Nous allons nous concentrer sur la scission des configurations suivantes :
package.json
webpack
vite
postcss
tailwindcss
Le but est de permettre aux espaces Admin et Seller de fonctionner indépendamment, tout en maintenant l'intégrité du frontend Customer. Cette étape ne concerne que la configuration technique et ne prévoit pas une refonte complète du code.
La structure cible du projet sera la suivante :
project-root/
│-- front-customer/
│ │-- package.json
│ │-- tailwind.customer.config.js
│ │-- vite.customer.config.mjs
│ │-- postcss.customer.config.js
│-- front-seller/
│ │-- package.json
│ │-- tailwind.seller.config.js
│ │-- vite.seller.config.mjs
│ │-- postcss.seller.config.js
│-- front-admin/
│ │-- package.json
│ │-- tailwind.admin.config.js
│ │-- vite.admin.config.mjs
│ │-- postcss.admin.config.js
│-- package.json (racine)
project-root/
│-- front-customer/
│ │-- package.json
│ │-- tailwind.customer.config.js
│ │-- vite.customer.config.mjs
│ │-- postcss.customer.config.js
│-- front-seller/
│ │-- package.json
│ │-- tailwind.seller.config.js
│ │-- vite.seller.config.mjs
│ │-- postcss.seller.config.js
│-- front-admin/
│ │-- package.json
│ │-- tailwind.admin.config.js
│ │-- vite.admin.config.mjs
│ │-- postcss.admin.config.js
│-- package.json (racine)
Chaque commande yarn
devra être exécutée dans le répertoire approprié.
Nous commençons par créer les répertoires :
mkdir front-customer front-seller front-admin
mkdir front-customer front-seller front-admin
Dans chaque répertoire, nous initialisons le projet avec :
yarn init -y
yarn init -y
Puis, installation des dépendances :
yarn add vite laravel-vite-plugin tailwindcss@3.x autoprefixer postcss --dev
yarn add vite laravel-vite-plugin tailwindcss@3.x autoprefixer postcss --dev
Dans front-seller
, créons le fichier vite.seller.config.mjs
:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import { resolve } from 'path';
import postcssConfig from './postcss.seller.config.js';
export default defineConfig({
root: '../',
plugins: [
laravel({
input: [
'resources/assets/css/seller/seller.css',
],
publicDirectory: resolve(__dirname, '../public'),
hotFile: resolve(__dirname, '../public/hot'),
refresh: true,
}),
],
server: {
host: '0.0.0.0',
port: 5173,
cors: true,
},
build: {
outDir: resolve(__dirname, '../public/build'),
},
css: {
postcss: postcssConfig,
}
});
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import { resolve } from 'path';
import postcssConfig from './postcss.seller.config.js';
export default defineConfig({
root: '../',
plugins: [
laravel({
input: [
'resources/assets/css/seller/seller.css',
],
publicDirectory: resolve(__dirname, '../public'),
hotFile: resolve(__dirname, '../public/hot'),
refresh: true,
}),
],
server: {
host: '0.0.0.0',
port: 5173,
cors: true,
},
build: {
outDir: resolve(__dirname, '../public/build'),
},
css: {
postcss: postcssConfig,
}
});
root: '../'
: Définit le répertoire racine relatif pour Vite. Ici, cela permet de référencer les fichiers tout en conservant l'organisation du projet.input
: Définit les fichiers CSS/JS qui seront pris en compte par Vite pour le hot reload et la compilation.publicDirectory
: Définit le répertoire de sortie des fichiers compilés, généralement public/build
.hotFile
: Indique le fichier permettant à Laravel de détecter si le mode de développement est actif.refresh
: Active le rechargement automatique des fichiers lorsque des modifications sont détectées.server
:
host: '0.0.0.0'
: Rend le serveur accessible sur le réseau local.port: 5173
: Définit le port par défaut utilisé par Vite en développement. Pour pouvoir lancer les 3 vite en simultané pensez a mettre un port différent a chaque config.cors: true
: Active le support des requêtes CORS.build
:
outDir
: Définit le répertoire de sortie des fichiers construits pour la production.css.postcss
: Spécifie un fichier de configuration PostCSS personnalisé pour la gestion des styles CSS.Mais cela n’impact que les chemins du input
.
C’est pour ça que pour les autres chemins de fichier j’ai du resolve(__dirname
et reconstruire le chemin par rapport à ça.
Enfin dernier point, je n’ai rien su faire pour le chemin du fichier de config postcss. Aussi j’ai préféré l’importer.
Créons le fichier postcss.seller.config.js
:
import tailwindcss from 'tailwindcss';
import autoprefixer from 'autoprefixer';
export default {
plugins: [
tailwindcss({ config: './tailwind.seller.config.js' }),
autoprefixer(),
],
};
import tailwindcss from 'tailwindcss';
import autoprefixer from 'autoprefixer';
export default {
plugins: [
tailwindcss({ config: './tailwind.seller.config.js' }),
autoprefixer(),
],
};
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
Exemple venant de la ddoc tailwindcss. https://v3.tailwindcss.com/docs/installation/using-postcss
Mais ici on importe le fichier dans vite config, aussi deux points important sont à noter
Je ne suis pas du tout connaisseur de JS, donc je ne saurais pas l’expliquer (cela doit être éviddent pour un dev JS), mais en tout cas c’est ce qu’il y a dans la doc de Vite.
Créons tailwind.seller.config.js
:
module.exports = {
content: [
'./resources/views/seller/**/*.blade.php',
'./resources/views/components/seller/**/*.blade.php',
'./resources/views/components/common/**/*.blade.php',
'./resources/views/vendor/**/*.blade.php',
'./resources/views/livewire/common/**/*.blade.php',
'./resources/views/livewire/seller/**/*.blade.php',
'./resources/assets/css/seller/seller.css',
],
theme: {
extend: {},
},
plugins: [],
};
module.exports = {
content: [
'./resources/views/seller/**/*.blade.php',
'./resources/views/components/seller/**/*.blade.php',
'./resources/views/components/common/**/*.blade.php',
'./resources/views/vendor/**/*.blade.php',
'./resources/views/livewire/common/**/*.blade.php',
'./resources/views/livewire/seller/**/*.blade.php',
'./resources/assets/css/seller/seller.css',
],
theme: {
extend: {},
},
plugins: [],
};
Dans theme
vous pouvez écrire tous vos paramètres de customisation color, padding, font, animation,…
Ajoutons les scripts dev
et build
dans package.json
de front-seller
:
{
"name": "front-seller",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "vite --config vite.seller.config.mjs",
"build": "vite build --config vite.seller.config.mjs"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"dotenv": "^16.4.7",
"laravel-vite-plugin": "^1.2.0",
"postcss": "^8.5.1",
"tailwindcss": "3.x",
"vite": "^6.1.0"
}
}
{
"name": "front-seller",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "vite --config vite.seller.config.mjs",
"build": "vite build --config vite.seller.config.mjs"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"dotenv": "^16.4.7",
"laravel-vite-plugin": "^1.2.0",
"postcss": "^8.5.1",
"tailwindcss": "3.x",
"vite": "^6.1.0"
}
}
Désormais yarn dev
devra être lancé à partir de chaque répertoire, mais rien n’empêche de faire des alias ou des scripts proxy dans le package.json à la racine du projet.
Nous devons maintenant mettre à jour nos fichiers Blade pour inclure les assets avec la directive @vite
.
Voici la doc Laravel a ce sujet https://laravel.com/docs/11.x/vite#loading-your-scripts-and-styles
Exemple pour guest.blade.php
qui est un layout pour les pages non connectées (exemple page de login):
<head>
<meta charset="UTF-8">
<title>{{ $page_title ?? "Application Seller" }}</title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<meta name="robots" content="noindex">
@vite([
'resources/assets/css/seller/seller.css',
])
</head>
<head>
<meta charset="UTF-8">
<title>{{ $page_title ?? "Application Seller" }}</title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<meta name="robots" content="noindex">
@vite([
'resources/assets/css/seller/seller.css',
])
</head>
Il existe plusieurs façons de gérer ça, que vous pouvez trouver dans la documentation Laravel. Nous avons choisie la suivante.
resources/assets/js/seller/static-assets.js
)import.meta.glob([
'../img/**',
]);
import.meta.glob([
'../img/**',
]);
Ici on lui dit de référencer toutes les images du répertoire img positionné relativement au fichier JS. Pas l’idéal vu l’état du répertoire, mais cela veut aussi dire qu’on va devoir faire un peu de ménage et avoir un répertoire d’image par front et potentiellement un common
.
input
dans la config vitelaravel({
input: [
'resources/assets/css/seller/seller.css',
'resources/assets/js/seller/seller.js',
'resources/assets/js/seller/static-assets.js',
],
publicDirectory: resolve(__dirname, '../public'),
hotFile: resolve(__dirname, '../public/hot'),
refresh: true,
}),
laravel({
input: [
'resources/assets/css/seller/seller.css',
'resources/assets/js/seller/seller.js',
'resources/assets/js/seller/static-assets.js',
],
publicDirectory: resolve(__dirname, '../public'),
hotFile: resolve(__dirname, '../public/hot'),
refresh: true,
}),
@vite([
'resources/assets/css/seller/seller.css',
'resources/assets/js/seller/seller.js',
'resources/assets/js/seller/static-assets.js',
])
@vite([
'resources/assets/css/seller/seller.css',
'resources/assets/js/seller/seller.js',
'resources/assets/js/seller/static-assets.js',
])
<img
src="{{ Vite::asset('resources/assets/img/full-logo.svg') }}"
alt="Logo"
class="my-4"
>
<img
src="{{ Vite::asset('resources/assets/img/full-logo.svg') }}"
alt="Logo"
class="my-4"
>
Cette approche permet d'avoir des configurations propres et indépendantes pour chaque espace frontend, améliorant ainsi la maintenabilité du projet. Il sera plus facile d'effectuer des mises à jour et d'introduire des évolutions sans impacter les autres parties du projet.
Photo de Mohammad Rahmani sur Unsplash