
Compartir:
Soy desarrollador de JavaScript y educador de desarrolladores en Vonage. A lo largo de los años me han entusiasmado las plantillas, Node.js, las aplicaciones web progresivas y las estrategias offline-first, pero lo que siempre me ha encantado es una API útil y bien documentada. Mi objetivo es hacer que tu experiencia usando nuestras APIs sea la mejor posible.
Crear una aplicación Nexmo completa con Express y React
Con el JavaScript Nexmo Client SDK, puede proporcionar una aplicación front-end que permita a los usuarios controlar las conversaciones de las que forman parte. A Conversación Nexmo puede incluir dos usuarios o muchos, y utilizar múltiples medios diferentes. Permitir que los participantes controlen elementos de la conversación solo abre más opciones para lo que tu aplicación puede ofrecer.
React es una opción muy popular para la construcción de aplicaciones para el front-end, y conceptos como Conversaciones y Usuarios dentro del Client SDK de Nexmo se adaptan muy bien a los componentes de React con sus propios controles de estado. Sin embargo, hay algunas cosas que el Client SDK de Nexmo no puede hacer, por lo que la imagen completa de tu aplicación no emerge hasta que también consideramos el back-end. Usando Express, puedes añadir algunas rutas simples para apoyar tu front-end en la gestión de usuarios y hacer cualquier otro trabajo que creas que es mejor mantener en el servidor.
A diferencia de una aplicación tradicional proporcionada por un servidor, tu front-end React es una aplicación por derecho propio, lo que significa que tu aplicación "full stack" es en realidad dos aplicaciones. Cada una escuchará en su propio puerto y responderá a las peticiones sin comprobar con la otra parte. Lo que esto parece desde una perspectiva de estructura de archivos es una aplicación dentro de una aplicación. Configurarás tu servidor Express en la raíz de tu directorio, luego añadirás la aplicación React -completa con su propio directorio separado package.json-en un subdirectorio.
Configuración de Applications
En la raíz del directorio del proyecto, empezarás creando un directorio package.json para tu aplicación Express y un directorio server.js que la contendrá. También querrás crear un archivo .env que almacenará las credenciales sensibles de tu aplicación y Account. Necesitarás instalar algunos paquetes de npm: Express, body-parser, dotenvy por supuesto el Nexmo Nodo SDK:
Para iniciar sus dos aplicaciones a la vez, también querrá concurrently instalado como dependencia de desarrollo:
A continuación, proporcionará las claves, ID y secretos necesarios para identificar su aplicación aplicación Nexmoque puedes almacenar en tu archivo .env archivo:
Puede encontrar su clave y secreto API en la página Primeros pasos de su panel de control de Nexmo. Puede obtener un ID de aplicación y una clave privada generada para descargar desde la página Crear una página de aplicación (si tu aplicación es de mensajería, puedes utilizar la página Crear una aplicación de mensajes en su lugar). En el ejemplo, la clave privada se guarda en la raíz de su directorio, así que asegúrese de actualizar la ruta en .env si la mueves a otro lugar.
Una vez completada la configuración, puedes pasar a crear la aplicación cliente.
Crear una aplicación React
Puede crear rápidamente un andamiaje para su cliente utilizando la práctica función create-react-app. Como esta aplicación React vivirá en un subdirectorio de tu proyecto, puedes especificar el nombre de subdirectorio que prefieras cuando ejecutes el comando (aunque puede que quieras cambiar el nombre de la aplicación a algo más descriptivo una vez que genere su package.json). En nuestro ejemplo, hemos llamado al subdirectorio "cliente":
Esto te dará la mayor parte de lo que necesitas en el cliente, incluyendo las dependencias de React y un conjunto de scripts para hacer cosas como iniciar y construir tu aplicación. El único paquete adicional que necesitarás de npm es el Client SDK de Nexmo:
En su cliente package.json también querrás añadir un proxy, que hará referencia a tu servidor Express y al puerto en el que se ejecuta:
"proxy": "http://localhost:3001", Servidor exprés
La inicialización de su servidor Express debería resultarle familiar si ha trabajado antes con Express. También querrá requerir dotenv y body-parserque adjuntarás a tu aplicación como middleware:
require('dotenv').config();
// init server
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.json());A continuación querrás crear un nuevo cliente Nexmo, proporcionándole las variables que guardaste en tu archivo .env que dotenv serán accesibles como miembros de process.env:
// create a Nexmo client
const Nexmo = require('nexmo');
const nexmo = new Nexmo({
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
applicationId: process.env.APP_ID,
privateKey: __dirname + process.env.PRIVATE_KEY
}, {debug: true});Para este sencillo ejemplo, sólo crearemos endpoints para obtener un JWT y crear un nuevo usuario. Puedes definir las firmas de tus endpoints ahora, y suministraremos la lógica para ambas aplicaciones juntas en un paso posterior. Por último, por supuesto, querrás que tu servidor Express escuche en el puerto especificado en el comando de React package.json:
app.post('/getJWT', function(req, res) {});
app.post('/createUser', function(req, res) {});
app.listen(3001); Componente de aplicación React
Cuando ejecutó create-react-appdebería haber creado un punto de entrada a su aplicación en src/index.js en el subdirectorio del cliente. Esto carga el componente definido en src/App.js y lo renderiza como el cuerpo de su página de destino. Este componente es un lugar ideal para realizar tareas administrativas como obtener un JWT e iniciar sesión en su aplicación Nexmo. También es un buen contenedor para dos componentes hijos: User y Conversation. Para empezar, importa dos componentes que crearás en un momento:
import React from 'react';
import User from './User';
import Conversation from './Conversation';
import nexmoClient from 'nexmo-client';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.login = this.login.bind(this);
this.getJWT = this.getJWT.bind(this);
this.userUpdated = this.userUpdated.bind(this);
}
login() {}
getJWT() {}
userUpdated() {}
render() {}
};
export default App;Mientras estamos en ello, se puede ver que también hemos importado el Nexmo Client SDK y limpiado la clase creada por lo que está listo para rellenar con nuestra lógica. También hemos añadido marcadores de posición para las funciones que necesitaremos.
Ahora que tienes referencias a los dos componentes hijos (aunque todavía no los hemos creado), puedes actualizar tu función render para cargarlos en tu página:
render() {
return (
<div className="nexmo">
<User onUpdate={this.userUpdated} />
<Conversation app={this.state.app} loggedIn={!!this.state.token} />
</div>
);
}
Inicio de sesión en la aplicación Nexmo
El componente User va a llamar a userUpdated cuando quiera informar de cambios en su estado, por lo que esa función se convierte en el primer eslabón de su cadena de ejecución. Buscará una propiedad username en el objeto de estado que reciba y, si existe, continuará para obtener un JWT para ese usuario:
userUpdated(user) {
if (user.username) {
this.getJWT(user.username);
}
}Su función getJWT consistirá principalmente en un fetch y el manejo de su respuesta. Necesitarás POST el nombre de usuario que recibe la función al servidor Express como JSON, luego analizar los datos y guardar tu nuevo JWT como la propiedad state token. Una vez hecho esto, puedes llamar a la función login para finalizar la inicialización de tu aplicación:
getJWT(username) {
fetch('/getJWT', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: username})
})
.then(results => results.json())
.then(data => {
this.setState({
token: data.jwt
});
this.login();
});
}
Obtener un JWT del servidor
Volvamos rápidamente a nuestra aplicación Express en server.js y proporcionemos el endpoint al que llamará la función getJWT del lado del cliente. Usando el Nexmo Node SDKpodemos generar un JWT proporcionando nuestro ID de aplicación una vez más; el subo nombre de usuario, que estamos enviando desde el cliente; una expiración en segundos; y los permisos que queremos que tenga este token. En el código de abajo, el usuario puede hacer cosas relacionadas con usuario, conversaciones, sesiones y aplicaciones, lo cual es suficiente para nuestra muy simple aplicación:
app.post('/getJWT', function(req, res) {
const jwt = nexmo.generateJwt({
application_id: process.env.APP_ID,
sub: req.body.name,
exp: Math.round(new Date().getTime()/1000)+3600,
acl: {
"paths": {
"/v1/users/**":{},
"/v1/conversations/**":{},
"/v1/sessions/**":{}
}
}
});
res.send({jwt: jwt});
});Ahora que tu servidor está enviando un token a la aplicación React, puedes volver a App.js y proporcionar la lógica para tu función final, login. Realmente no hay mucho que hacer. Usando el nuevo token guardado en el estado del componente App, inicias sesión en el cliente Nexmo y recibes una referencia a tu aplicación Nexmo conectada. Puedes guardarlo en el estado del componente, ¡y ya está hecho!
login() {
let nexmo = new nexmoClient();
nexmo.createSession(this.state.token).then(app => {
this.setState({
app: app
});
});
}
Componente de usuario React
Dado que su componente App está esperando en el componente Usuario para activar el flujo de inicio de sesión, vamos a crear ese componente ahora. En un nuevo archivo User.js en el mismo directorio que App.jspuede proporcionar un esquema del componente:
import React from 'react';
class User extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.createUser = this.createUser.bind(this);
this.setUsername = this.setUsername.bind(this);
};
createUser() {}
setUsername() {}
render() {}
};
export default User;En una aplicación del mundo real, querrás utilizar un sistema para gestionar y almacenar tus usuarios, así como para autenticarlos. Para este ejemplo mínimo, sin embargo, sólo vas a crear un nuevo usuario cada vez que accedas a esta página. En su función render puedes comprobar si el estado del componente contiene una propiedad userId propiedad. Si es así, puedes publicar un mensaje confirmando que el usuario ha iniciado sesión. Si no, puedes mostrar un campo de texto y un botón para crear el nuevo usuario:
render() {
if (this.state.userId) {
return (
<div className="userinfo userconnected">
Connected as <span className="username">{this.state.username}</span>
</div>
);
} else {
return (
<div className="userinfo">
<input type="text" onChange={evt => this.setUsername(evt)} />
<button onClick={this.createUser}>Create user</button>
</div>
);
}
}
Crear nuevos usuarios
La creación del usuario es en realidad un proceso de dos partes que comienza con la escucha de los cambios en el texto de su campo de texto y el almacenamiento del valor actualizado. Si quisieras empezar a hacer esta aplicación más robusta, podrías empezar por comprobar ese valor con tus reglas de nombre de usuario y la lista de usuarios existentes y enviar mensajes de validez o problemas de duplicación al usuario a través de un cambio de estilo. Pero para este ejemplo, simplemente almacenaremos ingenuamente cualquier texto que el usuario haya escrito:
setUsername(evt) {
this.setState({
username: evt.target.value
});
}Una vez que el usuario haga clic en el botón "Crear usuario", puede enviar otra solicitud a su servidor Express. Enviarás el nombre de usuario almacenado en el estado por setUsernamey cuando el servidor responda, activará la función onUpdate proporcionada por el componente App cuando este componente fue instanciado:
createUser() {
fetch('/createUser', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: this.state.username})
})
.then(results => results.json())
.then(data => {
this.setState({
userId: data.id
}, () => this.props.onUpdate(this.state));
});
}
El endpoint createUser endpoint es la última parte de tu servidor Express que nos queda por proporcionar, así que volvamos a server.js y rellenemos esa lógica. Puedes llamar a users.create en tu objeto Nexmo, pasando el nombre de usuario del cliente y un nombre para mostrar opcional (que no hemos incluido en el código del cliente para esta aplicación, pero que podrías elegir proporcionar más adelante). Si eso tiene éxito, pasarás el ID del nuevo usuario de vuelta al cliente:
app.post('/createUser', function(req, res) {
nexmo.users.create({
name: req.body.name,
display_name: req.body.display_name || req.body.name
},(err, response) => {
if (err) {
res.sendStatus(500);
} else {
res.send({id: response.id});
}
});
});
Ahora toda la lógica que necesitas para crear un usuario tanto en tus aplicaciones React como Express está disponible, y así tu aplicación React podrá iniciar sesión y hacer cosas como crear una conversación.
Componente de conversación de React
El último archivo que debe crear es Conversation.jsen el mismo directorio que App.js y User.js. El esquema del componente es aún más pequeño que los dos que ya has creado, pero en una aplicación del mundo real probablemente sería el componente que contiene la mayor parte de la lógica y probablemente incluso varios componentes hijos:
import React from 'react';
class Conversation extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.createConversation = this.createConversation.bind(this);
}
createConversation() {}
render() {}
};
export default Conversation;La función render sólo necesita proporcionar un botón, pero puede hacerlo un poco mejor desactivando el botón hasta que el componente App notifique a este Conversation que ha hecho su trabajo de inicialización. A continuación, puede ocultar el botón una vez que la conversación se une y se almacena una referencia a ella en el estado del componente:
render() {
if (this.state.conversation) {
return (
<div className="conversation">Joined conversation!</div>
);
} else {
return (
<div className="conversation">
<button
onClick={this.createConversation}
disabled={!this.props.loggedIn}>Start conversation</button>
</div>
);
}
}
La mayor parte de la lógica createConversation proviene de los objetos Aplicación y Conversación de Nexmo. Cuando el usuario hace clic en el botón, puede crear una nueva conversación con una llamada a la propiedad app pasada a este componente. Eso devolverá una conversación, a la que puedes unirte, y luego guardarla como una propiedad de estado:
createConversation() {
this.props.app.newConversation().then(conv => {
conv.join().then(member => {
this.setState({
conversation: conv
});
});
});
}
Desde aquí, puedes invitar a otros usuarios a la conversación, empezar a proporcionar manejadores para los eventos de la conversación o abrir un flujo de audio para que los participantes hablen entre sí.
Iniciar las aplicaciones
Quieres ser capaz de iniciar tus aplicaciones Express y React como si fueran una sola, por lo que lo último que necesitas hacer es proporcionar el mecanismo para que se inicien juntas. Ya has editado React package.json para que sea consciente de la aplicación Express; ahora es el momento de añadir algunos scripts a Express's package.json para que npm start inicie todo.
En el directorio package.json en la raíz de su proyecto, añada o modifique tres scripts: start, clienty server:
"scripts": {
"client": "cd client && npm start",
"server": "node server.js",
"start": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\""
},
El paquete concurrently que instaló al principio de este tutorial iniciará el servidor Express al mismo tiempo que navega al directorio cliente (tenga en cuenta que debe cambiar "cliente" por el nombre de su subdirectorio React si lo llamó de otra forma) y ejecuta el script start proporcionado por create-react-app. Si ejecutas npm start ahora, deberías poder abrir un navegador a la aplicación React en http://localhost:3000 y ver tu aplicación ejecutándose.
¿Quiere ver en acción una versión algo más compleja de esta aplicación? Puedes ver el código extendido en Glitch y remezclarlo para seguir experimentando con Nexmo Conversations. Y ahora que tienes los fundamentos, puedes continuar para construir una aplicación de chat con React y Nexmo.
Compartir:
Soy desarrollador de JavaScript y educador de desarrolladores en Vonage. A lo largo de los años me han entusiasmado las plantillas, Node.js, las aplicaciones web progresivas y las estrategias offline-first, pero lo que siempre me ha encantado es una API útil y bien documentada. Mi objetivo es hacer que tu experiencia usando nuestras APIs sea la mejor posible.