Base para un gran SPA modular en Laravel + Vue + ElementUI con generador CRUD

imagen

En los últimos años, me las arreglé para trabajar en varios proyectos grandes y no muy grandes utilizando diferentes marcos de back-end y front-end. Frente a varios problemas que surgieron a medida que la aplicación creció.

Ahora puedo concluir a partir de qué soluciones tuvieron éxito y cuáles no.
Utilizando la experiencia acumulada, me propuse recopilar las mejores soluciones, en mi opinión, y crear mi propia base para SPA.

No diré cómo crear un sitio en Laravel o qué es SPA. Hay suficiente información de este tipo en Internet. Este artículo está destinado a desarrolladores más o menos experimentados, por lo que extrañaré algunos detalles.

Quién no puede esperar, al final del artículo hay un enlace a mi repositorio de github.

Las tecnologías principales fueron seleccionadas por Laravel y Vue.js + Vuex ya que esta es mi pila principal.

Para un desarrollo rápido, tomé el kit de interfaz de usuario: ElementUI .

el objetivo principal


Para crear una base para un proyecto mediano y grande que:

  • ayudará a evitar la cohesión rígida de los módulos
  • comprensible para un programador con poca experiencia
  • ayudar a evitar la duplicación de código
  • será fácil de expandir
  • reducir el tiempo de inicio del proyecto
  • reducir el tiempo de soporte del proyecto y navegación de código

Para hacer la vida lo más fácil posible, para no confundirse en el proyecto, necesita estructurar adecuadamente su ego. Inicialmente, la aplicación debe dividirse en niveles de responsabilidad, tales como interfaz de usuario, base de datos, lógica de negocios.

Además, cada capa debe dividirse primero por la funcionalidad, y luego cada módulo funcional debe dividirse de acuerdo con el patrón seleccionado.

Inspirado por la filosofía DDD, decidí dividir el front-end y el back-end en módulos semánticos. Pero estos no son los dominios clásicos que describe Evans. Su modelo tampoco es perfecto. En cualquier aplicación, con el tiempo, siempre aparecen relaciones entre componentes, las mismas relaciones entre modelos.

Dejó los modelos como una capa separada, porque parecían duplicar la base de datos, con todas sus conexiones.

Creó un directorio al frenteresources / js / modules , en el que se ubicarán los diferentes módulos. Cada uno tendrá api - métodos para trabajar con el back-end, componentes - todos los componentes y páginas, almacenamiento - almacenamiento y rutas .

{moduleName}/
├── routes.js
├── api/
│   └── index.js
├── components/
│   ├── {ModuleName}List.vue
│   ├── {ModuleName}View.vue
│   └── {ModuleName}Form.vue
└── store/
    ├── store.js
    ├── types.js
    └── actions.js

En resources / js , se crea la carpeta principal , donde se encuentran los componentes principales del sistema.
También hay bootstrap e incluye carpetas para configurar bibliotecas y utilidades adicionales, respectivamente.

El proyecto utiliza la carga dinámica de modelos. Es decir, en el núcleo / rutas y en el núcleo / estados, cargamos los archivos de enrutamiento y almacenamiento correspondientes automáticamente (no es necesario registrar nada).

Aquí hay un ejemplo de cómo se cargaron store.js desde diferentes módulos automáticamente.

// Load store modules dynamically.
const requireContext = require.context('../../modules', true, /store\.js$/) 
 
let modules = requireContext.keys() 
    .map(file => 
        [file.replace(/(^.\/)|(\.js$)/g, ''), requireContext(file)] 
    )
    .reduce((modules, [path, module]) => { 
        let name = path.split('/')[0] 
        return { ...modules, [name]: module.store } 
    }, {})
 
modules = {...modules, core} 
 
export default new Vuex.Store({
    modules
})
 

En el backend en el directorio de la aplicación habrá módulos similares. Cada módulo contendrá carpetas Controladores, Solicitudes, Recursos . El archivo con rutas también se ha movido aquí: routes_api.php .

{ModuleName}/
├── routes_api.php
├── Controllers/
│   └──{ModuleName}Controller.php
├── Requests/
│   └──{ModuleName}Request.php
└── Resources/
    └── {ModuleName}Resource.php
 

Otros patrones de diseño como eventos, trabajos, políticas, etc. no se incluirán en los módulos, ya que se usan con menos frecuencia y es más lógico mantenerlos en una capa separada.

Todas las manipulaciones con la carga dinámica de los módulos se realizan de modo que el compromiso mínimo late entre ellos. Esto le permite agregar y quitar módulos sin consecuencias. Ahora puede hacer que el comando artesanal cree un módulo de este tipo. Con su ayuda, podemos llenar rápidamente el proyecto con las entidades necesarias junto con la funcionalidad CRUD.

Una vez ejecutado el comando php artisan make:module {ModuleName}, tendremos todos los archivos necesarios, incluidos el modelo y las migraciones, para que funcione el CRUD completo. Solo tienes que completar la migraciónphp artisan migratey todo funcionará Lo más probable es que necesite agregar campos adicionales, así que antes de la migración, no olvide agregarlos al modelo, la migración y también la salida a vue.



En esta plantilla, se usó la tecnología JWT-Auth para la autenticación , pero puede ser redundante y debe rehacerse para Laravel Sanctum. A su vez, vue-auth se usa en el front-end , facilita la administración de la autorización y los roles del usuario.

En el futuro, me gustaría mejorar el sistema. Agregue un bus de eventos global, conecte websockets. Añadir pruebas. Es posible crear una opción de gestión de roles en sucursales separadas o crear sucursales con otro kit de interfaz de usuario. Sería bueno escuchar recomendaciones, comentarios.

Inicialmente, esta plantilla fue desarrollada para sus necesidades, pero ahora espero que sea útil para otros usuarios.

Todo el código se puede ver en mi repositorio github .

All Articles