Optimización de aplicaciones Next.js con Nx

 

 

 

  • SmashingConf Freiburg 2024
  • Design Patterns For AI Interfaces, with Vitaly Friedman

  • Índice
    1. ¿Qué es Nx?
    2. ¿Por qué utilizar Nx?
    3. Nx para bibliotecas publicables
    4. Creación de una aplicación Next.js y Nx
      1. Construyendo la API
      2. Generando páginas Next.js con Nx
      3. Consumo de API en la aplicación Next.js
      4. Otros comandos CLI para Nx
    5. Conclusión

    Nx es un marco de compilación que facilita la optimización, el escalado eficiente de aplicaciones y otras características como bibliotecas y componentes compartidos. En este artículo, veremos cómo podemos escalar eficazmente las aplicaciones Next.js utilizando Nx.

     

    En este artículo, veremos cómo optimizar y crear una aplicación Next.js de alto rendimiento utilizando Nx y sus ricas funciones. Veremos cómo configurar un servidor Nx, cómo agregar un complemento a un servidor existente y el concepto de monorepo con una visualización práctica.

    Si es un desarrollador que busca optimizar aplicaciones y crear componentes reutilizables en todas las aplicaciones de manera efectiva, este artículo le mostrará cómo escalar rápidamente sus aplicaciones y cómo trabajar con Nx. Para seguir adelante, necesitará conocimientos básicos del marco Next.js y TypeScript.

    ¿Qué es Nx?

    Nx es un marco de construcción de código abierto que le ayuda a diseñar, probar y construir a cualquier escala, integrándose perfectamente con tecnologías y bibliotecas modernas, al tiempo que proporciona una sólida interfaz de línea de comandos (CLI), almacenamiento en caché y gestión de dependencias. Nx ofrece a los desarrolladores herramientas CLI avanzadas y complementos para marcos, pruebas y herramientas modernos.

    En este artículo, nos centraremos en cómo funciona Nx con las aplicaciones Next.js. Nx proporciona herramientas estándar para probar y diseñar sus aplicaciones Next.js, como Cypress, Storybook y componentes con estilo. Nx facilita un monorepo para sus aplicaciones, creando un espacio de trabajo que puede contener el código fuente y las bibliotecas de múltiples aplicaciones, lo que le permite compartir recursos entre aplicaciones.

    ¿Por qué utilizar Nx?

    Nx proporciona a los desarrolladores una cantidad razonable de funcionalidad lista para usar, incluidos textos estándar para pruebas de extremo a extremo (E2E) de su aplicación, una biblioteca de estilos y un monorepo.

     

    El uso de Nx conlleva muchas ventajas y analizaremos algunas de ellas en esta sección.

    • Ejecución de tareas basada en gráficos
      Nx utiliza la ejecución distribuida de tareas basada en gráficos y el almacenamiento en caché de cálculo para acelerar las tareas. El sistema programará tareas y comandos utilizando un sistema gráfico para determinar qué nodo (es decir, aplicación) debe ejecutar cada tarea. Esto maneja la ejecución de aplicaciones y optimiza el tiempo de ejecución de manera eficiente.
    • Testing
      Nx proporciona herramientas de prueba preconfiguradas para pruebas unitarias y pruebas E2E.
    • Caching
      Nx también almacena el gráfico del proyecto en caché. Esto le permite volver a analizar solo los archivos actualizados. Nx realiza un seguimiento de los archivos modificados desde la última confirmación y le permite probar, crear y realizar acciones sólo en esos archivos; esto permite una optimización adecuada cuando se trabaja con una base de código grande.
    • Gráfico de dependencia
      El gráfico de dependencia visual le permite inspeccionar cómo interactúan los componentes entre sí.
    • Almacenamiento en la nube
      Nx también proporciona almacenamiento en la nube e integración con GitHub, para que pueda compartir enlaces con los miembros del equipo para revisar los registros del proyecto.
    • Compartir código
      Crear una nueva biblioteca compartida para cada proyecto puede resultar bastante agotador. Nx elimina esta complicación, permitiéndole concentrarse en la funcionalidad principal de su aplicación. Con Nx, puede compartir bibliotecas y componentes entre aplicaciones. Incluso puede compartir código reutilizable entre sus aplicaciones de front-end y back-end.
    • La compatibilidad con monorepos
      Nx proporciona un espacio de trabajo para múltiples aplicaciones. Con esta configuración, un repositorio de GitHub puede albergar el código fuente de varias aplicaciones en su espacio de trabajo.

    Nx para bibliotecas publicables

    Nx le permite crear bibliotecas publicables. Esto es esencial cuando tienes bibliotecas que usarás fuera del monorepo. En cualquier caso en el que esté desarrollando componentes de interfaz de usuario organizacional con la integración de Nx Storybook, Nx creará componentes publicables junto con sus historias. Los componentes publicables pueden compilar estos componentes para crear un paquete de biblioteca que puede implementar en un registro externo. Usarías la --publishableopción al generar la biblioteca, a diferencia de --buildable, que se usa para generar bibliotecas que se usan solo en el monorepo. Nx no implementa las bibliotecas publicables automáticamente; puede invocar la compilación mediante un comando como nx build mylib(dónde mylibestá el nombre de la biblioteca), que luego producirá un paquete optimizado en la carpeta dist/ mylibque se puede implementar en un registro externo.

     

    Nx le ofrece la opción de crear un nuevo espacio de trabajo con Next.js como valor preestablecido o agregar Next.js a un espacio de trabajo existente.

    Para crear un nuevo espacio de trabajo con Next.js como ajuste preestablecido, puede usar el siguiente comando:

    npx create-nx-workspace happynrwl --preset=next --style=styled-components --appName=todo

    Este comando creará un nuevo espacio de trabajo de Nx con una aplicación Next.js llamada "todo" y styled-componentscomo biblioteca de estilos.

    Luego, podemos agregar la aplicación Next.js a un espacio de trabajo de Nx existente con el siguiente comando:

    npx nx g @nrwl/next:app

    Creación de una aplicación Next.js y Nx

    El complemento Nx para Next.js incluye herramientas y ejecutores para ejecutar y optimizar una aplicación Next.js. Para comenzar, necesitamos crear un nuevo espacio de trabajo de Nx con nextun valor preestablecido:

    npx create-nx-workspace happynrwl --preset=next --style=styled-components --appName=todo

    El bloque de código anterior generará un nuevo espacio de trabajo de Nx y la aplicación Next.js. Recibiremos un mensaje para usar Nx Cloud. Para este tutorial, seleccionaremos "No" y luego esperaremos a que se instalen nuestras dependencias. Una vez hecho esto, deberíamos tener un árbol de archivos similar a este:

     happynrwl ┣ apps ┃ ┣ todo ┃ ┣ todo-e2e ┃ ┗ .gitkeep ┣ libs ┣ node_modules ┣ tools ┣ .editorconfig ┣ .eslintrc.json ┣ .gitignore ┣ .prettierignore ┣ .prettierrc ┣ README.md ┣ babel.config.json ┣ jest.config.js ┣ jest.preset.js ┣ nx.json ┣ package-lock.json ┣ package.json ┣ tsconfig.base.json ┗ workspace.json

    En la appscarpeta tendremos nuestra aplicación Next.js “todo”, con la prueba E2E preconfigurada para la aplicación de tareas pendientes. Todo esto se genera automáticamente con la poderosa herramienta Nx CLI.

    Para ejecutar nuestra aplicación, use el npx nx serve todocomando. Una vez que haya terminado de servir la aplicación, debería ver la siguiente pantalla:

    Página predeterminada de Nx para una nueva aplicación. ( Vista previa grande )

    Construyendo la API

    En este punto, hemos configurado el espacio de trabajo. Lo siguiente es construir la API CRUD que usaremos en la aplicación Next.js. Para hacer esto, usaremos Express; Para demostrar la compatibilidad con monorepo, construiremos nuestro servidor como una aplicación en el espacio de trabajo. Primero, tenemos que instalar el complemento Express para Nx ejecutando este comando:

    npm install --save-dev @nrwl/express

    Una vez hecho esto, estamos listos para configurar nuestra aplicación Express en el espacio de trabajo proporcionado. Para generar una aplicación Express, ejecute el siguiente comando:

     

    npx nx g @nrwl/express:application --name=todo-api --frontendProject=todo

    El comando nx g @nrwl/express:applicationgenerará una aplicación Express a la que podemos pasar parámetros de especificación adicionales; para especificar el nombre de la aplicación, use la --namebandera; para indicar la aplicación front-end que utilizará la aplicación Express, pase el nombre de una aplicación en nuestro espacio de trabajo a --frontendProject. Algunas otras opciones están disponibles para una aplicación Express . Una vez hecho esto, tendremos una estructura de archivos actualizada en la appscarpeta con la todo-apicarpeta agregada.

     happynrwl ┣ apps ┃ ┣ todo ┃ ┣ todo-api ┃ ┣ todo-e2e ┃ ┗ .gitkeep …

    La todo-apicarpeta es un modelo estándar Express con un main.tsarchivo de entrada.

    /** * This is not a production server yet! * This is only minimal back end to get started. */import * as express from 'express';import {v4 as uuidV4} from 'uuid';const app = express();app.use(express.json()); // used instead of body-parserapp.get('/api', (req, res) = { res.send({ message: 'Welcome to todo-api!' });});const port = process.env.port || 3333;const server = app.listen(port, () = { console.log(`Listening at https://localhost:${port}/api`);});server.on('error', console.error);

    Crearemos nuestras rutas dentro de esta aplicación. Para comenzar, inicializaremos una matriz de objetos con dos pares clave-valor itemy idjusto debajo de la declaración de la aplicación. Artículos de danza y ballet

    /** * This is not a production server yet! * This is only minimal back end to get started. */import * as express from 'express';import {v4 as uuidV4} from 'uuid';const app = express();app.use(express.json()); // used instead of body-parserlet todoArray: Array{ item: string; id: string } = [ { item: 'default todo', id: uuidV4() },];…

    A continuación, configuraremos la ruta para recuperar todas las listas de tareas pendientes en app.get():

    …app.get('/api', (req, res) = { res.status(200).json({ data: todoArray, });});…

    El bloque de código anterior devolverá el valor actual de todoArray. Posteriormente, tendremos rutas para crear, actualizar y eliminar elementos de tareas pendientes de la matriz.

    …app.post('/api', (req, res) = { const item: string = req.body.item; // Increment ID of item based on the ID of the last item in the array. let id: string = uuidV4(); // Add the new object to the array todoArray.push({ item, id }); res.status(200).json({ message: 'item added successfully', });});app.patch('/api', (req, res) = { // Value of the updated item const updatedItem: string = req.body.updatedItem; // ID of the position to update const id: string = req.body.id; // Find index of the ID const arrayIndex = todoArray.findIndex((obj) = obj.id === id); // Update item that matches the index todoArray[arrayIndex].item = updatedItem res.status(200).json({ message: 'item updated successfully', });});app.delete('/api', (req, res) = { // ID of the position to remove const id: string = req.body.id; // Update array and remove the object that matches the ID todoArray = todoArray.filter((val) = val.id !== id); res.status(200).json({ message: 'item removed successfully', });});…

    Para crear una nueva tarea pendiente, todo lo que necesitamos es el valor del nuevo elemento como una cadena. Generaremos una ID incrementando la ID del último elemento de la matriz en el servidor. Para actualizar un elemento existente, pasaríamos el nuevo valor del elemento y el ID del objeto del elemento que se actualizará; en el servidor, recorreríamos cada elemento con el forEachmétodo y actualizaríamos el elemento en el lugar donde la ID coincide con la ID enviada con la solicitud. Finalmente, para eliminar un elemento de la matriz, enviaríamos el ID del elemento que se eliminará con la solicitud; luego, filtramos la matriz y devolvemos una nueva matriz de todos los elementos que no coinciden con el ID enviado con la solicitud, asignando la nueva matriz a la todoArrayvariable.

     

    Nota: Si busca en la carpeta de la aplicación Next.js, debería ver un proxy.conf.jsonarchivo con la siguiente configuración:

    { "/api": { "target": "https://localhost:3333", "secure": false }}

    Esto crea un proxy, lo que permite que todas las llamadas API a rutas coincidentes /apise dirijan al todo-apiservidor.

    Generando páginas Next.js con Nx

    En nuestra aplicación Next.js, generaremos una nueva página homey un componente de elemento. Nx proporciona una herramienta CLI para que podamos crear fácilmente una página:

    npx nx g @nrwl/next:page home

    Al ejecutar este comando, se nos pedirá que seleccionemos la biblioteca de estilos que queremos usar para la página; Para este artículo, seleccionaremos styled-components. ¡Voilá! Nuestra página está creada. Para crear un componente, ejecute npx nx g @nrwl/next:component todo-item; esto creará una componentcarpeta con el todo-itemcomponente.

    Consumo de API en la aplicación Next.js

    En cada tarea pendiente, tendremos dos botones, para editar y eliminar la tarea pendiente. Las funciones asincrónicas que realizan estas acciones se pasan como accesorios desde la página de inicio.

    …export interface TodoItemProps { updateItem(id: string, updatedItem: string): Promisevoid; deleteItem(id: string): Promisevoid; fetchItems(): Promiseany; item: string; id: string;}export const FlexWrapper = styled.div` width: 100%; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #ccc; padding-bottom: 10px; margin-top: 20px; @media all and (max-width: 470px) { flex-direction: column; input { width: 100%; } button { width: 100%; } }`;export function TodoItem(props: TodoItemProps) { const [isEditingItem, setIsEditingItem] = useStateboolean(false); const [item, setNewItem] = useStatestring | null(null); return ( FlexWrapper Input disabled={!isEditingItem} defaultValue={props.item} isEditing={isEditingItem} onChange={({ target }) = setNewItem(target.value)} / {!isEditingItem Button onClick={() = setIsEditingItem(true)} Edit /Button} {isEditingItem Button onClick={async () = { await props.updateItem(props.id, item); //fetch updated items await props.fetchItems(); setIsEditingItem(false) }} Update /Button} Button danger onClick={async () = { await props.deleteItem(props.id); //fetch updated items await await props.fetchItems(); }} Delete /Button /FlexWrapper );}

    Para la funcionalidad de actualización, tenemos una entrada que está deshabilitada cuando el isEditingItemestado es false. Una vez que se hace clic en el botón "Editar", cambia el isEditingItemestado truey muestra el botón "Actualizar". Aquí, el componente de entrada está habilitado y el usuario puede ingresar un nuevo valor; cuando se hace clic en el botón "Actualizar", llama a la updateItemfunción con los parámetros pasados ​​y vuelve a isEditingItemcambiar a false.

     

    En el homecomponente de página, tenemos las funciones asincrónicas que realizan la operación CRUD.

     … const [items, setItems] = useStateArray{ item: string; id: string }([]); const [newItem, setNewItem] = useStatestring(''); const fetchItems = async () = { try { const data = await fetch('/api/fetch'); const res = await data.json(); setItems(res.data); } catch (error) { console.log(error); } }; const createItem = async (item: string) = { try { const data = await fetch('/api', { method: 'POST', body: JSON.stringify({ item }), headers: { 'Content-Type': 'application/json', }, }); } catch (error) { console.log(error); } }; const deleteItem = async (id: string) = { try { const data = await fetch('/api', { method: 'DELETE', body: JSON.stringify({ id }), headers: { 'Content-Type': 'application/json', }, }); const res = await data.json(); alert(res.message); } catch (error) { console.log(error); } }; const updateItem = async (id: string, updatedItem: string) = { try { const data = await fetch('/api', { method: 'PATCH', body: JSON.stringify({ id, updatedItem }), headers: { 'Content-Type': 'application/json', }, }); const res = await data.json(); alert(res.message); } catch (error) { console.log(error); } }; useEffect(() = { fetchItems(); }, []);…

    En el bloque de código anterior, tenemos fetchItems, que regresa todoArraydel servidor. Luego tenemos la createItemfunción, que toma una cadena; el parámetro es el valor de la nueva tarea pendiente. La updateItemfunción toma dos parámetros, el ID del elemento a actualizar y el updatedItemvalor. Y la deleteItemfunción elimina el elemento que coincide con el ID que se pasa.

    Para representar la tarea pendiente, asignamos el itemsestado:

     …return ( StyledHome h1Welcome to Home!/h1 TodoWrapper {items.length 0 items.map((val) = ( TodoItem key={val.id} item={val.item} id={val.id} deleteItem={deleteItem} updateItem={updateItem} fetchItems={fetchItems} / ))} /TodoWrapper form onSubmit={async(e) = { e.preventDefault(); await createItem(newItem); //Clean up new item setNewItem(''); await fetchItems(); }} FlexWrapper Input value={newItem} onChange={({ target }) = setNewItem(target.value)} placeholder="Add new item…" / Button success type="submit" Add + /Button /FlexWrapper /form /StyledHome );…

    Nuestro servidor y nuestra interfaz ya están configurados. Podemos servir la aplicación API ejecutando npx nx serve todo-apiy, para la aplicación Next.js, ejecutamos npx nx serve todo. Haga clic en el botón "Continuar" y verá una página con la tarea pendiente predeterminada.

     

    La página de tareas pendientes de la aplicación. ( Vista previa grande )

    Ahora tenemos una aplicación Next.js y Express funcionando juntas en un solo espacio de trabajo.

    Nx tiene otra herramienta CLI que nos permite ver el gráfico de dependencia de nuestra aplicación en nuestra ejecución de terminal. Ejecute npx nx dep-graphy deberíamos ver una pantalla similar a la imagen a continuación, que muestra el gráfico de dependencia de nuestra aplicación.

    Gráfico de departamento de aplicación. ( Vista previa grande )

    Otros comandos CLI para Nx

    • nx list
      Enumera los complementos de Nx actualmente instalados.
    • nx migrate latest
      Actualiza los paquetes package.jsona la última versión.
    • nx affected
      Realiza la acción solo en las aplicaciones afectadas o modificadas.
    • nx run-many --target serve --projects todo-api,todo
      Ejecuta el comando de destino en todos los proyectos enumerados.

    Conclusión

    Como descripción general de Nx, este artículo ha cubierto lo que ofrece Nx y cómo nos facilita el trabajo. También explicamos cómo configurar una aplicación Next.js en un espacio de trabajo de Nx, agregar un complemento Express a un espacio de trabajo existente y usar la función monorepo para albergar más de una aplicación en nuestro espacio de trabajo.

    Encontrarás el código fuente completo en el repositorio de GitHub . Para obtener información adicional sobre Nx, consulte la documentación o la documentación de Nx para Next.js.

    (ks, vf, yk, il, al)Explora más en

    • Reaccionar
    • javascript
    • Aplicaciones
    • Mecanografiado
    • Herramientas





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Optimización de aplicaciones Next.js con Nx

    Optimización de aplicaciones Next.js con Nx

    SmashingConf Freiburg 2024 Design Patterns For AI Interfaces, with Vitaly Friedman Índice ¿Qué es Nx?

    programar

    es

    https://pseint.es/static/images/programar-optimizacion-de-aplicaciones-next-1125-0.jpg

    2024-04-04

     

    Optimización de aplicaciones Next.js con Nx
    Optimización de aplicaciones Next.js con Nx

     

     

    Top 20