Prólogo
Para empezar, un día quería crear una aplicación. Este deseo surgió porque me encanta leer, pero simplemente no hay agregadores de libros normales en la vasta Internet rusa. En realidad, debido al dolor de buscar algo para leer e intentar recordar el nombre del libro que leí recientemente y en qué capítulo me detuve, nació el deseo de crear una aplicación web en la que todo esto fuera posible y conveniente. Vale la pena señalar que no hay experiencia en desarrollo, programación, etc. No tenía, mi trabajo no está relacionado con esto en absoluto. Sin embargo, el deseo venció la pereza y se convirtió en acciones concretas, una especie de pasatiempo.
No diré cómo estudié javascript, node.js, react, html, css, etc., pasaremos a lo que he llegado en este momento, lo que me gustaría compartir con ustedes y, por supuesto, escuchar las críticas constructivas de los especialistas.
Como muchos, me entrené en mi propia PC en localhost: 3000, creé front / back-ends, escribí, trabajé con api, etc., pero siempre me preocupaba la idea de cómo transferir todo esto al alojamiento más tarde. ¿Funcionará? ¿Será necesario reescribir el código debido a esto?
Y lo más importante, ¿es posible configurar todo para poder trabajar en la aplicación desde cualquier PC y transferir fácilmente todo al hosting en producción? Hablaré de esto.Elección de alojamiento
Para mi hobby, estaba listo para gastar $ 10 al mes, así que elegí el alojamiento con el que planeaba quedarme en el futuro. Como dije, antes de eso tenía 0 experiencia, incluso con alojamiento de sitios. Intenté y rechacé lo siguiente:
Jelastic : interfaz hermosa y fácil de usar, todo parece ser intuitivo, escalable y comprensible. Sin embargo, encontré dificultades para configurar (nginx por alguna razón no quería trabajar desde vps, solo con su módulo separado) y conectar SSL (y actualización automática) al dominio de habla rusa por medios estándar (prometieron corregir el error, pero no quiero esperar)
Cloud hosting REG.RU : También tengo un dominio allí, así que la solución parecía lógica, pero no tenían PostgreSQL configurado por separado, y como no quería contactar a la administración de la base de datos, comencé a buscar más.
AWS y Google clouds : lo intenté, todo parece estar bien, pero recordé nuestras leyes "maravillosas" y el requisito de poner los datos de los usuarios en los servidores de la Federación de Rusia. Desafortunadamente, estos tipos no tenían servidores en la Federación Rusa. No es un abogado, pero por el pecado decidió buscar nubes con servidores en la Federación Rusa.
Si es poco probable que su aplicación tenga problemas con la ley, entonces es una buena opción.Aunque había nubes con servidores en la Federación Rusa, todavía quería algo que me salvara de tener que sumergirme en la administración de PostgreSQL. El impulso surgió hace poco,
Yandex .
Intenté encontrar nubes que
estaban disponibles, parece que todo es simple y conveniente, así que me detuve en ellas por ahora. Vale la pena señalar que el alojamiento PostgreSQL viene de inmediato con 1core y 4GB de RAM, lo que cuesta alrededor de 2k rublos al mes, por lo que para el tiempo de desarrollo y baja carga, planeo ejecutar PostgreSQL en VPS durante ~ 300r, y transferir la base de datos con una mayor carga y dejar Yandex se dedica a la administración y actualización.
Configurando Yandex.Cloud
Nube privada virtual
1) Cree un directorio para su sitio:

2) Crear una nube privada virtual:
Lo principal que me da en la etapa actual es la IP para acceder al recurso creado desde el exterior. Me familiaricé con subredes, zonas, aislamiento y tolerancia a fallas superficialmente, si es necesario, me pondré al día.
3) Cree una subred y asígnele una IP interna (según tengo entendido, se trata como una red local)

4) Vaya a la pestaña IP y reserve una IP estática.
En él nos conectaremos desde casa y otros lugares. Probablemente pueda trabajar con dinámica, pero no entendí en qué casos cambia.

Computar nube
Aquí tendremos cálculos :) Es decir, crearemos una máquina virtual con Linux (elegí ubuntu 18.04), instalaremos aplicaciones node.js y postgreSQL.

Hacemos clic para crear una VM, desatornillamos todos los ajustes al mínimo, ya que no habrá carga durante el desarrollo (cuando se lance nuestra aplicación, luego gire un poco más, bueno, monitorearemos los gráficos).
Ssh
El punto problemático que encontré en esta etapa es SSH:

Qué era y por qué no tenía idea, así que fui a estudiar. Resultó: este es solo un método de acceso, pero no por contraseña, sino por la clave SSH generada. Para generarlo realmente, descargue e instale
Putty como se nos recomienda.
Ejecute C: \ Archivos de programa \ PuTTY \ puttygen.exe

Presionamos el botón Generar y movemos el mouse para aleatorizar la clave generada (según tengo entendido). Luego, copie la línea que aparece comenzando con ssh-rsa en algún lugar del archivo de texto y haga clic en Guardar clave privada, Guardar clave pública. La clave copiada en el archivo de texto se inserta en el campo SSH de la clave de la página Yandex Yandex. Especificamos root como root, de lo contrario no tendrá acceso cuando trabaje con el sistema de archivos gráficos de la aplicación mediante el cual se conectará a la nube desde su hogar / trabajo (tal vez haya una forma, pero no lo entendí).
Como señaló andreymal, es mejor no usar root para que los bots chinos no recojan la contraseña de su nube, pero como Yandex.cloud solo tiene acceso SSH, puede vivir así.
Una aplicación en un hosting debe ser lanzada exclusivamente por un usuario no root, para no permitir que los atacantes ejecuten código malicioso a través de posibles vulnerabilidades en su aplicación.
Nos conectamos a la nube desde una PC y seleccionamos un cliente SSH gratuito
La masilla estándar le permite trabajar solo en la línea de comandos, y como no estoy familiarizado con el usuario de Windows, comencé a buscar un cliente con un pseudo-explorador. Al principio probé Mobaxterm, pero después de un tiempo de inactividad se apaga, el explorador se congela por completo, así que ahora estoy trabajando con
bitvise ssh y hasta ahora no veo problemas como Mobaxterm.
Configurar bitvise ssh

Aquí, en el campo Servidor> Host, indique nuestra nube IP externa. Puerto 22. Haga clic en administrador de claves del cliente> importar y especifique la clave privada generada previamente en él. Es posible que aún necesite una frase clave, elija algo que no olvidará. Cierre esta ventana y especifique el nombre de usuario en el campo de autenticación: raíz, clave de método de publicación, clave de cliente: seleccione la previamente importada. Haga clic en iniciar sesión y si hicimos todo correctamente, luego conéctese a la nube:

Instalar Node.js
Aquí recomiendo usar las instrucciones de digitalocean.com, son muy detalladas y muchas están en ruso. Por lo general, busco en Google "digitalocean ubuntu 18.04 node.js" o lo que sea que quiera instalar o configurar allí.
Cómo instalar Node.js se puede leer
aquí .
En resumen, vamos a
nodeource (aquí se pueden instalar las últimas versiones de node.js), hojee aquí:

Copie y ejecute los comandos a su vez:
curl -sL https:
Verificamos cómo fue establecido por el equipo
nodejs -v
Veremos la versión de node.js
npm -v
Se nos mostrará la versión del administrador de paquetes para node.js.
A continuación, vaya a la carpeta / opt / mysuperapp (my_super_app_name; debe crear esta carpeta). El directorio opt se eligió como la ubicación de la aplicación después de buscar en Google "donde es apropiado poner los archivos node.js de la aplicación en ubuntu".
Finalmente, cree el archivo server.js, que será el punto de entrada de la aplicación, y pegue el código simple del servidor en node.js allí:
const http = require('http'); const hostname = 'localhost'; const port = 80; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World!\n'); }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
El puerto 80 es para solicitudes http, 443 es para https. Si bien tenemos un servidor en http.
Guardamos todo y ejecutamos el comando:
node server.js
La consola debería mostrar la línea 'Servidor que se ejecuta en
localhost : 80 /'
Ahora puede abrir un navegador, ingresar una IP externa (la que está en la nube Yandex de su máquina virtual ubuntu) y veremos "¡Hola Mundo!"
Hacemos todo convenientemente o el ciclo de desarrollo con git
Todo parece funcionar, pero no trabajaremos todo el tiempo conectándonos a la nube. Además, de repente no estaremos trabajando solos en el futuro.
Github
Github es el lugar donde se ubicará el código de nuestra aplicación. En resumen, el principio de trabajo para una persona es el siguiente:
- Estamos desarrollando nuestra aplicación en una PC hogareña.
- Guardamos y descargamos el código en Github con un solo clic.
- En el hosting o en otra PC, descargue nuestra aplicación desde github, reinicie el servidor (si es el hosting) y la nueva versión de nuestra aplicación web está disponible en la World Wide Web.
Todo es rápido, simple y conveniente.
Realmente regístrese en Github y cree un repositorio privado para nuestra aplicación (estará disponible solo para nosotros):

Copie la línea
github.com/ReTWi/mysuperapp.git para descargar la aplicación.

- Volvemos a la línea de comandos de bitvise, paramos la aplicación presionando ctrl + c (si aún funciona).
- Vaya al directorio / opt y elimine la carpeta con la aplicación que creamos
Git es lo que usaremos para subir nuestra aplicación a github, y desde allí a un hosting u otra PC. Git es un tema de discusión por separado, así que hablemos de esto por ahora.
Instala
git en el hosting con los siguientes comandos:
sudo apt update sudo apt install git
Compruebe si todo está bien establecido:
git --version
La versión de git debería aparecer.
Completamos los datos de git (no entendí por qué, pero aparentemente puede haber algunas advertencias aburridas).
git config --global user.name "Your Name" git config --global user.email "youremail@domain.com"
Finalmente, cargamos nuestra aplicación al hosting con el comando:
(debe haber un enlace a su aplicación)
git clone https:
Aparecerá un nuevo mysuperapp en el directorio / opt, donde se ubicarán nuestros archivos de aplicación descargados de github.
Ahora es el momento de repetir lo mismo para PC y cerrar la cadena de PC (diferente) -> Github -> Hosting
Instale
node.js en la PC .
Código de estudio visual
Para comenzar, seleccione el editor de código fuente donde trabajaremos. Elegí el código de Visual Studio, por lo que es simple, conveniente, tiene muchos complementos y puedes configurar la sincronización de configuraciones si trabajas con múltiples dispositivos. En realidad, descargamos, instalamos, iniciamos, seleccionamos la carpeta de la aplicación compartida, ya que git clone creará la suya para nosotros.
Los complementos que uso son los siguientes:
Instala git para PC .
Abra una consola en VScode usando ctrl + shift + `o terminal> nueva terminal
Retiro
En la consola de Windows, es malo con los caracteres rusos, por lo que no hay grietas que necesita para abrir el archivo> preferencias> configuración, ingrese terminal.integrated.shellArgs.windows en el campo, haga clic

Y agregue la línea "terminal.integrated.shellArgs.windows": ["-NoExit", "/ c", "chcp 65001"],

Repita el comando para descargar archivos de github:
git clone https:
En VScode, haga clic en Archivo> Abrir carpeta y abra la carpeta de nuestra aplicación.
Cree el archivo server.js con el mismo código de servidor simple:
const http = require('http'); const hostname = 'localhost'; const port = 80; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World!\n'); }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
Instale nodemon para reiniciar automáticamente el servidor cuando se realicen cambios en el código:
npm i nodemon -g
i - abreviatura de instalación
g: instalación global (que estará disponible en la consola), y no solo para nuestra aplicación.
Ejecute el comando:
nodemon server.js
Abra
localhost : 80 / en el navegador o simplemente localhost: 80 y vea Hello World.
Ahora es el momento de revisar nuestra cadena de PC> Github> Hosting.
Descargue el escritorio de Github para mayor conveniencia, conecte su cuenta de github, luego haga clic en el archivo Agregar repositorio local y especifique el directorio de nuestra aplicación.
En la aplicación, vemos los cambios que hicimos en comparación con la versión descargada de Github (agregamos server.js):

Haga clic en "commit to master"> "push origin", descargando así los archivos de la PC a Github.

Vamos a nuestra cuenta de github en el navegador y vemos el archivo server.js descargado:

Practiquemos un poco más, en VScode reemplazamos la línea "res.end ('Hello World! \ N');" a "res.end ('OmNomNom');". Veremos que el servidor se reinicia:

Comprobaremos en el navegador y veremos los cambios realizados por nosotros "OmNomNom" allí.
Desktop github también nos mostrará que cambiamos la línea:

Nuevamente, haga clic en comprometerse con master> push origin para enviar archivos a github.
Cambie a la línea de comando de hosting.
Paramos nuestra aplicación si aún se está ejecutando (ctrl + c).
Descargue nuestra aplicación actualizada con los siguientes comandos:
git config credential.helper store git pull
El primero guardará nuestros datos para que no tenga que ingresar su nombre de usuario y contraseña constantemente. En el futuro, git pull será suficiente para nosotros.
Instale pm2, algo similar a nodemon, solo para hosting:
npm i pm2 -g
Comencemos la aplicación usando pm2, que reiniciará nuestro servidor en el siguiente git pull en el hosting:
pm2 start server.js --watch
Abra el navegador en nuestra nube IP externa y vea nuestro "OmNomNom".
Por lo tanto, cerramos la cadena de trabajo con la aplicación y su rápida implementación en el alojamiento.
Creamos certificados SSL temporales para HTTPS en localhost y hosting
Vamos al sitio
zerossl.com
En el campo dominios, ip ..., primero ingrese localhost, haga clic en generar y descargue 2 archivos por botón:

Los guardamos en nuestro proyecto en la carpeta ssl / localhost.
Repita el procedimiento para la nube IP externa y guárdela en ssl / myapp.
Inicie un servidor https más complejo node.js
Estructura de la aplicación:

- cliente: aquí estará nuestro front-end. He reaccionado
- registros: los registros de alojamiento se colocarán aquí
- node_modules - módulos node.js
- privado: sus archivos privados, guardo el acceso SSH a la nube allí
- el servidor es tu backend
- ssl - certificados ssl para trabajar https en localhost y hosting
- .babelrc: configuración de compilación de reacción de la aplicación webpack'om (le permite utilizar JS más modernos al desarrollar frontend)
- .gitignore: archivos que no se moverán a github (git no parece verlos)
- client.js: punto de entrada para generar el ensamblaje de reacción
- package.json: los node_modeles que está utilizando y varios fragmentos de comandos.
- package-lock.json: cambios en los módulos (según tengo entendido, el archivo verificará si los mismos módulos están instalados en su hosting y en su PC).
- pm2-watch.json: configuración de inicio de pm2 para hosting
- README.md - cubierta para github
- server.js: el punto de partida de nuestro servidor backend Node.js
- webpack.config.js - reaccionar configuración de compilación
.gitignore
Aquí indicamos aquellos archivos / carpetas que no queremos subir a github. Solo estarán en este dispositivo y git no rastreará / mostrará sus cambios. Abrir e insertar:
/node_modules/ /logs/* # exception to the rule !logs/.gitkeep /public/react_bundle.js /public/isProd.js
Como github no descarga carpetas vacías, puede poner algo dentro, por ejemplo, un archivo .gitkeep vacío. Guarde el archivo y cierre.
package.json
Abra y pegue lo siguiente (después de // comentarios agregados)
{ "name": "myapp",
Me centraré en dos marcos / bibliotecas principales seleccionados para la aplicación:
Fastify fue elegido como una alternativa a express.js, ya que el primero ya tiene soporte experimental para htpp2, se está desarrollando activamente y me parece que tiene más futuro que express.js, que se ha vuelto muy lento y de alguna manera en desarrollo. Por otro lado, express.js ha estado trabajando durante mucho tiempo y le será más fácil encontrar información sobre él.
Se eligió React porque era más fácil para mí trabajar con él, comprenderlo y probarlo todo con mis propias manos. Vue: parecía algo con sus propias reglas, dirección. Aunque en Vue puede ser necesario escribir algo menos con sus propias manos, pero dado que se da prioridad al entrenamiento y para una persona que no ha programado previamente, la reacción fue de alguna manera más fácil.
Guardamos el archivo package.json e instalamos todos los módulos especificados en dependencias con el comando:
npm i
Tendremos una carpeta node_modules, en la que habrá todos los módulos para nuestra aplicación.
cliente - mientras que la carpeta vacía
registros: dentro del archivo .gitkeep se encuentra, de modo que la carpeta migra al alojamiento y los registros caen con éxito allí. Durante el desarrollo, enviaremos todo a la consola.
publico
Aquí estarán los archivos estáticos de nuestro sitio, imágenes allí, favicons, etc.
Detengámonos en dos archivos:
index.html:
<!DOCTYPE html> <html> <head> <base href="/" /> <meta charset="UTF-8" /> <title>MyApp</title> </head> <body> <div id="cookies"> react_bundle </div> <noscript >: Javscript</noscript > <script src="react_bundle.js"></script> </body> </html>
- aquí tenemos un front-end de reacción cargado y procesado en una etiqueta por su id.
isProd.js contiene una sola línea "module.exports = false"
Como está en excepciones .gitignore, no es portátil. En consecuencia, lo configuramos como falso en la PC y verdadero en el alojamiento. Luego usamos este archivo para comprender en qué entorno estamos actualmente (desarrollo / producción). Me pareció lo más conveniente, además, puede cambiar parcialmente el código durante el desarrollo y verificar el funcionamiento de los módulos en producción.
ssl: hay certificados previamente guardados en las carpetas localhost y myapp
.babelrc
{ "presets": [ [ "@babel/preset-env", { "targets": { "browsers": [">0.25%", "not ie 11", "not op_mini all"] } } ], "@babel/preset-react" ], "plugins": [ "babel-plugin-styled-components", "@babel/plugin-transform-runtime" ] }
Configuración para crear nuestro react_bundle con soporte de navegador utilizado por más del 0.25% de los usuarios.
client.js
import React from 'react' import { render } from 'react-dom' render(<div>!!</div>, document.getElementById('cookies'))
Representa nuestra interfaz en un div con una etiqueta de cookie.
pm2-watch.json: le permite ejecutar el servidor con el comando "npm run server" en el hosting con seguimiento de cambios en el código y reinicio automático.
webpack.config.js
Generador de aplicaciones de reactores:
const webpack = require('webpack'), path = require('path'), BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin module.exports = (env, argv) => { let prod = argv.mode == 'production' let config = { entry: './client.js', output: { path: path.resolve('./public'), filename: 'react_bundle.js' }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, loader: 'babel-loader' }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, resolve: { alias: { client: path.resolve('./client/shared'), public: path.resolve('./public') } }, plugins: [ argv.analyze ? new BundleAnalyzerPlugin() : false, prod ? new webpack.optimize.AggressiveMergingPlugin() : false, new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /ru/) ].filter(Boolean), optimization: { minimize: prod ? true : false }, performance: { hints: false } } return config }
En resumen, abre el archivo client.js y todo lo que está dentro de él, recolecta react_bundle y lo coloca en la carpeta pública, desde donde se cargará a través del index.html abierto.
server.js
const isProd = require('./public/isProd'), fs = require('fs'), log = require('./server/logger'), path = require('path')
Carpeta del servidor
Aquí yace el backend y todos los caminos.
logger.js: según el entorno, isProd se registra en la consola o en errors.log
'use strict' const pino = require('pino'), isProd = require('../public/isProd') let logOptions = isProd ? { level: 'warn',
servidor / api /
open.js: agrega nuestros caminos aquí.
'use strict' module.exports = function(fastify, options, next) { fastify.route({ method: 'GET', url: '/', handler: async (req, res) => { res.send('api / route') } }) fastify.route({ method: 'GET', url: '/hi', handler: async (req, res) => { res.send('api / route hi') } }) next() }
Después de configurar y verificar todo en Localhost, simplemente cargamos todo a github, y desde allí git pull al alojamiento. Todo lo que debe hacerse en el alojamiento es instalar los módulos node.js con el comando "npm i" y crear el archivo isProd.js
SSL actualizado automáticamente
Cuando compra un dominio y lo vincula a la nube de IP, un ejemplo de
instrucciones para REG.RU , puede instalar en el servidor SSL gratuito actualizado automáticamente para que el sitio funcione a través de https.
Nuestro servidor funciona sin nginx. Es posible que lo necesitemos en el futuro como un equilibrador de carga o un servidor HTTP más rápido para distribuir archivos estáticos, pero hasta ahora no veo la necesidad de hacerlo. Todavía no necesitamos equilibrio de carga, pero no he encontrado comparaciones con respecto a la velocidad de distribución de las estadísticas.
Antes de instalar en la carpeta ssl, cree la carpeta .well-known, y acme-challenge. Resulta /opt/myapp/ssl/.well-known/acme-challenge
Para instalar SSL actualizado automáticamente en un servidor con node.js sin nginx
, haga clic en el enlace . A su vez, ejecute los comandos en la consola de hosting:
sudo apt-get update sudo apt-get install software-properties-common sudo add-apt-repository universe sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install certbot sudo certbot certonly
Seleccionamos el segundo método de verificación, que colocará un archivo específico en la carpeta /opt/myapp/ssl/.well-known/acme-challenge, y después de confirmar el propietario del servidor, se eliminará.
Indicamos nuestro dominio a pedido, por ejemplo: "example.com" y la ruta a la carpeta ssl de nuestra aplicación (el servidor está configurado para que proporcione el archivo creado por el bot) "/ opt / myapp / ssl".
El bot configurará la tarea cron para renovar el certificado antes de su vencimiento dentro de los 90 días.
No pensé que tomaría tanto tiempo escribirlo todo, a las 4 de la mañana ya podía perder algo:
Interesante es la opinión de los habitantes de Habrach y especialistas que dominaron este lienzo o leyeron algunos puntos individuales. ¿Cómo se organiza su ciclo de desarrollo? ¿Hay algún punto en el que me equivoque o haga algo incorrecto?