Nuestra empresa se dedica principalmente al desarrollo de tiendas en línea y queremos compartir nuestra experiencia en el desarrollo de un proyecto en un grupo de VueJS + Nuxt + Laravel.
El artículo discutirá cómo decidimos implementar la tienda en línea como un SPA: cómo llegamos a esto, dificultades, facilidad.
El sitio que se discutirá es una tienda en línea casi clásica con un catálogo, filtros, búsqueda, cesta, cuenta personal, es decir Casi todo lo que puede estar en la tienda. El proyecto tiene una lógica, precios y mapeo diferentes para personas jurídicas y particulares.
Por qué SPA
Antes del proyecto actual, nuestra experiencia en el desarrollo de aplicaciones de una sola página consistía en solo unos pocos proyectos internos. Y en muchos sentidos, el SPA para nosotros fue, en cierto sentido, un caballo oscuro.
No hubo una comprensión clara de los problemas asociados con el crecimiento del proyecto, su seo-promoción y estabilidad, cuando, como experiencia y procesos de larga duración en la creación de sitios ordinarios, no plantearon ninguna pregunta para resolver estos problemas.
La elección del enfoque provocó un debate bastante acalorado en nuestra empresa, se completaron tanto las escalas como los argumentos y la decisión fue muy difícil. Nuestros desarrolladores decidieron recopilar un prototipo de varias páginas del proyecto y ver qué dificultades surgirían con cada enfoque. Este enfoque nos ayudó con la solución final. Los prototipos ayudaron a demostrar que administrar el estado del sitio (catálogo, canasta, pago, etc.) es mucho más cómodo y causa menos problemas en la versión SPA. La velocidad de desarrollo e interacción entre las máquinas de escribir y los programadores ha aumentado significativamente debido al hecho de que no es necesario transferir el diseño, solo agregue lógica a los componentes listos para usar. Los problemas que podemos encontrar también se hicieron más claros y esto provocó nuevas acciones. Antes de nosotros estaba la elección de la tecnología.
Fuera de la ventana es el verano de 2017. En Twitter y en medio, las disputas no disminuyen, lo cual es aún mejor, ver o reaccionar. Nuestra oficina no pasó esta tendencia. Los desarrolladores también se dividieron en dos campos, cada uno con sus propios argumentos. Antes de eso, cada uno de nosotros ya había trabajado con ambas tecnologías.
Alguien se ha acercado a jsx, alguien prefiere el html o pug más familiar, alguien cree que la inmutabilidad ayuda a monitorear y controlar mejor el estado de la aplicación, para alguien esto parece una complicación excesiva. Por otro lado, cada marco nos da la oportunidad de crear componentes de un solo archivo, y para ambos ya hay bibliotecas bastante estables con un conjunto de todas las funciones necesarias para nosotros (SSR, gestión de estado global, enrutamiento, gestión de metadatos). Para reaccionar es nextjs, y para vue es nuxtjs. Nuxt en el momento de la selección todavía estaba en beta, pero bastante estable. Porque El proceso de desarrollo se construyó de tal manera que inicialmente tenemos un diseño, y luego construimos la parte del backend y transferimos el diseño de las páginas a la interfaz, la elección del marco fue bastante simple. Elegimos vue y nuxtjs, porque Se decidió crear el sitio y lanzar la API en paralelo. Con este enfoque, es conveniente componer componentes de inmediato y agregarles lógica. Nuestros diseñadores de diseño adoptaron un enfoque más cercano para crear su html habitual.
Un poco sobre backend
En términos de soluciones de servidor y, en general, la elección de tecnologías para construir el backend, tomamos el camino más familiar. El lenguaje fue elegido php, para lo cual utilizamos el marco laravel. Todo gira en nginx. Como solución de base de datos tenemos mysql.
Inicio del desarrollo, paquetes usados y problemas.
Nuxt proporciona paquetes completamente satisfactorios para que podamos administrar el estado de la aplicación (vuex) y el enrutamiento (vue-router). Por lo tanto, comenzar a ensamblar el proyecto y ajustar la lógica a los componentes podría comenzar de inmediato y luego, según sea necesario, buscar los paquetes que necesitamos. En primer lugar, por supuesto, necesitaba una solución para comunicarme con la parte del backend. Para hacer esto, se eligió axios, el estándar ya para todos, y el envoltorio nuxt-axios-module sobre él. También ayudamos de inmediato al proyecto a que no se pierda en el entorno y se ejecute en cada entorno con la configuración deseada: seleccione dotenv y el contenedor nuxt-dotenv-module. Para comenzar el desarrollo, esto es suficiente y el proceso de diseño ha comenzado.
La primera pausa ocurrió cuando fue necesario agregar un control deslizante de imagen al diseño. "¿Dónde está mi slick-slider, quiero jquery" se escuchó desde el lado del diseño de la habitación. Una revisión rápida de las soluciones preparadas reveló varios controles deslizantes adecuados para nosotros. Pero casi todos arrastraron una dependencia en forma de jquery, que no quería agregar al paquete terminado, aumentando así su tamaño. Algunos paquetes no admitían la representación del servidor, lo que también era importante para nosotros. Como resultado, la elección recayó en el impresionante swiper, que cumplió plenamente con nuestros requisitos e incluso un poco más. Después de que el control deslizante se atornillara, nuestros diseñadores de diseño permanecieron perdidos durante mucho tiempo. “Eso es todo, ¿tengo que hacer algo más? ¿Solo especifique una lista de imágenes y funciona?
Luego vino la elección del componente para seleccionar las fechas. Hubo mas suerte Se encontró rápidamente una envoltura para nuestro querido flatpickr. Todo lo que quedaba era darle un poco de estilo.
En varios lugares del sitio hay un mapa. Pero porque no necesitábamos detalles y elaboración perfectos del mapa, no había elección entre los servicios. Sin embargo, en el momento del desarrollo, e incluso ahora, no hay soluciones que cubran idealmente todas nuestras necesidades. En base a todos los pros y los contras, se eligieron google maps y el contenedor vue2-google-maps. El paquete es lo suficientemente grande y genera muchos innecesarios para nosotros, pero resuelve bien sus problemas.
En algunas formas, tenemos campos para ingresar al teléfono. El usuario debe ayudar a ingresar al teléfono, ya que hay demasiadas opciones para el formato, y luego trabajar en el futuro con los datos ingresados en un solo formato es más fácil. Por lo tanto, necesitas una máscara. Quería usar la ya conocida máscara de texto, y aquí tuvimos suerte, ya tenían una solución para vue: vue-text-mask.
Estos paquetes cubrieron casi todos nuestros requisitos. Todo lo que quedaba era rastrear los clics fuera del componente, lo que ayudó a vue-click-outside. Implementamos el desplazamiento rápido de la página usando vue-backtotop. Para trabajar con fechas, usa momento.
El tamaño final del paquete y de dónde vino 1 megabyte
Debe tenerse en cuenta que un criterio importante al elegir los paquetes fue su peso.
En el medio del proyecto, decidimos analizar el proyecto final y ver las dimensiones del ensamblaje. Los resultados fueron, por decirlo suavemente, sorprendentes. El tamaño de la pandilla app.js era de poco más de 950kb gzip. El equipo de análisis de npm run nos trajo una hermosa gráfica con el tamaño de todos los módulos, de la cual nos dimos cuenta de que algunos módulos extraen dependencias innecesarias en forma de jquery, lodash, etc. Tuvieron que rechazar estos paquetes y encontrar una alternativa a ellos. Actualmente, el tamaño del paquete completo es 480kb gzip.

Esté atento a las dependencias y verifique periódicamente el tamaño de su aplicación.
Página de carga inicial y datos obtenidos por api
Nuxt ofrece una oportunidad conveniente para llenar la tienda con datos en el lado del servidor antes de cargar el cliente. Para esto, se utiliza la acción nuxtServerInit. Se ve así para nosotros:

Dado que utilizamos categorías y algunas otras entidades en varios componentes a la vez, fue más conveniente para nosotros obtenerlos de inmediato y ponerlos en la tienda.
Pero aquí hay un problema con el tamaño json que obtienes. Como el servidor envía todos los datos recibidos al cliente para la representación inicial, el tamaño html puede ser demasiado grande. Nos encontramos con esto cuando en categorías comenzamos a transferir imágenes, descripciones y otros campos que no eran necesarios para nosotros en todas las páginas que pertenecen a cada categoría. El tamaño de json estaba por encima de 2mb. Afortunadamente, esto se puede solucionar fácilmente eliminando campos innecesarios de los datos que proporciona el servidor.
Fugas de memoria
Después de un tiempo, la aplicación en nuestro servidor de prueba, comenzamos a observar un aumento antinatural en el consumo de memoria. pm2 ocupó hasta el 90% de toda la memoria del servidor y la aplicación se bloqueó periódicamente. En la página de github, nuxt ya colgó
algunos problemas con el mismo problema.
El problema surgió cuando realizamos varias solicitudes en el método asyncData de nuestras páginas.

Afortunadamente, los desarrolladores de nuxt resolvieron rápidamente este problema, y actualmente el proceso consume alrededor de 40 MB de memoria.
Problemas interesantes y sus soluciones.
Artículos componentesEn el panel de control del sitio, es posible agregar artículos e insertar varios bloques en el contenido del artículo, por ejemplo, un bloque con productos.

El HTML que proviene del servidor se parece a esto:

$ product-4 indica que el componente Product.vue con el identificador 4 debe estar en lugar de este puntero.Vue nos brinda amplias posibilidades para renderizar el componente utilizando el método de renderizado. Primero, buscamos todas las referencias a punteros a componentes en el html que ha llegado y obtenemos por API los datos necesarios para mostrar este componente. Luego, dividimos todo el html en un árbol. La biblioteca del himalaya nos ayudó con esto. Y luego recopilamos html de nuevo reemplazando punteros con componentes listos para usar.
... Y no había suficiente fuerza para escribir un artículo) Comenzaron a escribir el artículo en el verano de 2017 durante el desarrollo del proyecto, y ya es verano de 2018 en el patio, el proyecto se lanzó y el artículo no se ha publicado.
Por lo tanto, publicamos lo que hemos reunido, pero todavía tenemos muchos temas y observaciones interesantes.
Si será interesante, escribe, dale me gusta)) Bueno, ¿qué más sería interesante escuchar, que te perdiste?
Quiero decir que el proyecto ha estado funcionando durante aproximadamente 4 meses. No hubo problemas especiales con él, y la velocidad del sitio es impresionante y lo distingue de otras tiendas.