Red de conocimiento informático - Material del sitio web - La biblioteca de direcciones ha cambiado. ¿Cómo actualizar el archivo de código de front-end?

La biblioteca de direcciones ha cambiado. ¿Cómo actualizar el archivo de código de front-end?

Esta es una herramienta de actualización en caliente desarrollada para el grupo por un compañero de clase a quien le resultó inconveniente depurar durante el desarrollo diario del grupo. Quedé muy impresionado. Resolví la implementación técnica del artículo después de comprender sus ideas de implementación específicas.

Código fuente de la herramienta EHU (esl-hot-update)

Qué es la actualización en caliente

Actualización en caliente significa que al modificar el código en el entorno de desarrollo, hay no es necesario actualizar. El efecto de la modificación se puede ver en toda la página.

Si utiliza webpack en su proyecto, con la ayuda del complemento webpack-dev-server, tendrá la oportunidad de actualizar el proyecto en caliente.

Problemas resueltos

Para proyectos a nivel de sistema a gran escala, existen las siguientes características

Uso extensivo del modo modular (AMD), una gran cantidad de A menudo hay cientos de archivos sueltos, e incluso miles si no se tiene cuidado.

El contenido de inicialización contiene una gran cantidad de bibliotecas subyacentes, bibliotecas de interfaz de usuario, etc.

Estas dos características conduce directamente a cada velocidad de actualización es muy lenta después de la depuración. Si el js inicializado alcanza el orden de miles, entonces cada actualización deberá esperar 5 segundos, 10 segundos o incluso 20 segundos.

El propósito de la actualización en caliente es minimizar esta pérdida de 5 segundos, 10 segundos o incluso 20 segundos.

Problemas encontrados

Utilizamos la herramienta de entorno de desarrollo edp de Baidu, que no admite actualizaciones en caliente

Usamos AMD para instalar la herramienta de entorno de desarrollo edp de Baidu. En la práctica de ESL, no hemos encontrado la estrategia de actualización en caliente de requirejs, por lo que si requirejs tiene una estrategia de actualización en caliente, no podemos usarla directamente.

Así que la conclusión final es que implementaremos uno basado en nuestro propio negocio. De esta manera, no tenemos que pensar en el problema de manera demasiado amplia y la solución está más enfocada y orientada hacia nuestro marco comercial existente. Lo más importante es que podemos intentar modificar el marco subyacente para que coincida con él.

Una vez despejado el camino, podremos plantearnos cuestiones universales.

Ideas de solución

Del archivo ehu/package.json, podemos ver algunas ideas específicas

Necesitamos una función de vigilancia, es decir, monitorear el archivo. cambios

socket.io notifica al navegador que procese los cambios de archivos

Modificar archivos esl Cuando vuelva a abrir el módulo o función, encontrará que el código recién cargado sobrescribirá el código anterior después ejecución.

Así que mi primer instinto en ese momento fue repetir esl require. Si el último sobrescribe el anterior, entonces puedo probar la idea de sobrescribirlo simple, pero el resultado es que sí. no se puede sobrescribir. Después de la verificación, se descubrió que hay un mapeo de mantenimiento dentro de esl, que requiere que se almacene el módulo. Si desea actualizar este módulo, solo puede eliminar el nombre del módulo correspondiente en la asignación. (

Requisitos de herramientas

Tengo varios requisitos de herramientas

Esl debe modificarse, pero ¿cómo hacerlo transparente para los desarrolladores? En primer lugar, y Lo más importante es que no se puede permitir que todos realicen tales modificaciones.

El soporte de Socket.io también debe agregarse a la página, entonces, ¿cómo podemos agregar este soporte sin afectar el desarrollo de otros? p>Lo que estamos haciendo es una versión beta, entonces, ¿cómo podemos usar selectivamente la herramienta ehu y cambiar entre modos de desarrollo anteriores a voluntad?

¿Podemos instalarla fácilmente como herramienta? and-play sin una configuración tediosa

Cómo usar

npm install -g ehu (se requiere sudo para mac, se requieren derechos de administrador para Windows)

Ejecute ehu en la ruta del comando de inicio del servidor web edp original (ya no es necesario ejecutar el inicio del servidor web edp)

El número de puerto original 8848 es el número de puerto predeterminado.

p>Cambie el número de puerto original 8848 a 8844 (el 8848 original aún se puede usar, pero no se admiten actualizaciones en caliente)

El primer método de uso es muy simple. Para este propósito, la herramienta está especialmente diseñada. Empaquetado en npm, incluso si hay una actualización en el futuro, solo necesita actualizarla.

Además, desde una perspectiva de uso, está lo más integrado posible (una línea de comando es suficiente), por lo que no tienes que hacer mucho más al usar la herramienta.

Marco de dependencia "dependencies": { "async":"^1.5.0", "commander":"^2.9.0", "express":"^4.13.3", "express- mander: le facilita escribir sus propios comandos de nodo

Herramientas:

async y lodash

Ideas de marco

Primero , Veamos algunas solicitudes realizadas a la herramienta ayer

Esl definitivamente deberá modificarse, pero ¿cómo hacerlo transparente para los desarrolladores? En primer lugar, ¿no se pueden realizar dichas modificaciones para todos? . /p>

El soporte para Socket.io también debe agregarse a la página, entonces, ¿cómo agregamos ese soporte sin afectar el desarrollo de otras personas?

Estamos haciendo una versión beta, entonces, ¿cómo? ¿Para usar selectivamente la herramienta ehu y cambiar entre modos de desarrollo anteriores a voluntad?

Fácil de instalar, ¿podemos usarlo como una herramienta, plug and play, sin una configuración tediosa? 1 y 2, en realidad necesitamos modificar/agregar algo de código, pero nada de este código quiere enviarse al entorno de desarrollo del proyecto porque estos entornos de generación de código no son necesarios en absoluto.

Entonces, nuestra solución. es: interceptar, reescribir (robar)

Por ejemplo, cuando necesitamos hacer algunas modificaciones en esl, nuestro enfoque es: cuando la ruta apunta a esl.js, lo cambiamos a otro esl-ehu. js (esl-ehu.js es una modificación de esl.js) para volver a él, que es transparente para el código del entorno de desarrollo

Socket.io Lo mismo ocurre con el soporte, podemos reescribir el. código html para incorporar socket.io al devolver html

La idea anterior en realidad proviene de una compilación de proyecto anterior

Para 3 esperamos poder cambiar rápidamente al modo anterior mientras. Al usar la herramienta, el propósito de esta compatibilidad es hacer que la herramienta sea más competitiva y atractiva de usar.

Nuestra solución es implementar un subproceso internamente. El número de puerto sigue siendo el mismo que antes. la herramienta se omite al acceder a este puerto.

Para child_process, también encontramos un problema, es decir, el subproceso secundario a menudo se bloquea al ejecutar el sistema. Lo acabamos de encontrar hoy. en un artículo separado más adelante.

Para 4, en realidad es el método npm.

Detalles técnicos

No. 1. Paso: crear un nuevo servicio como. la capa inferior para alojar nuestro servicio edp actual. El nuevo servicio tiene configuración de enrutamiento y debemos interceptarlo.

Para el contenido que no necesita ser procesado, utilizaremos el proxy directamente a edp

Referencia de código

var mid = express(); mid.all('*', httpProxy(config). .function( req, res) { return !ruleRoute(req, res }, forwardPath: function(req, res) { return URL.parse(req.url).path }.})); por express- http- ruta administrada por proxy app.use('/', mid);

ruleRoute es un procesamiento de interceptación

Antes de esto, inicie el proceso secundario

var child = require('child_process'); var cli = child.exec( defaultServerCLI.on('data', function (log) { !isServerStarted && (cb(null, log)); isServerStarted && console. log (log); });

Aquí hay una trampa, que se presentará en otro artículo más adelante

Paso 2: desde que el archivo se devolvió después de la interceptación anterior. ya es compatible con socket .io, esl y se han realizado otras modificaciones subyacentes, por lo que el archivo debe monitorearse a continuación para notificar al navegador que lo procese en consecuencia.

//Iniciar el servicio socket.io io = require('socket.io')(server io.on('connection', function (socket) { socket.emit('hello') ; }); // Supervisar los cambios del archivo. initWatch();

Paso 3: Realizar un trabajo de integración

program .version('0.0.6') .usage('[options]') ..option(' - p, --port ','establecer puerto', setPort) .option('-n, --noServerCLI', '...' , noServerCLI) .parse(process.argv);

Integrado en los comandos del nodo

Paso 4: Configuración predeterminada

module.exports = { // Servidor predeterminado defaultServer: 'http://127.0.0.1:8848' , // Comando de inicio del servidor predeterminado defaultServerCLI: 'edp webserver start', //La ruta intermedia desde el directorio raíz del servidor a la carpeta a monitorear baseDir: 'nirvana-workspace', //La carpeta a monitorear para actualizaciones en caliente (excluyendo baseDir) watchDirs: 'src', // Archivo de entrada (excluyendo baseDir) indexHTML: 'main.html', // número de puerto de inicio de ehu (no debe entrar en conflicto con el número de puerto predeterminado del servidor) puerto: 8844 };

Hay mucha lógica para procesar configuraciones en el código fuente

Dependencias del navegador

Dependencias del navegador

Dependencias del navegador

Dependencias del navegador

Dependencias del navegador

Las dependencias del navegador son las más comunes.

io: el navegador depende completamente del socket para comunicarse con el servidor

Lógica de comunicación

//Establecer una conexión socket.on('hello', function () { log( getLogMsgPrefix () , '¡HotUpdate ha comenzado!) }); // Cambio de archivo detectado socket.on('hotUpdate', función (archivo) { // log( getLogMsgPrefix(), 'Cambio de archivo detectado', archivo); // ...Manejar cambios de archivos correspondientes a la lógica de actualización en caliente}); Manejar actualizaciones css/less

Este es un principio relativamente simple, la página escucha los cambios de estilo y recarga el estilo una vez, lo cual es simple. de cobertura.

Pero existe un problema potencial, porque el estilo es una simple anulación, por lo que si la modificación es para eliminar el estilo, entonces no tendrá efecto.

Ejemplo: antes de la modificación:

pantalla: ninguno; desbordamiento: oculto; posición: relativa; fondo: #FFFFFF; borde: 1px sólido #E8E8E8; /p>

Después de la modificación:

Pantalla: ninguna; desbordamiento: oculto; posición: relativa; fondo:

La eliminación del borde y el margen superior en realidad no tiene efecto

p>

Este también es un problema que debe resolverse en una etapa posterior.

Manejo de actualizaciones de plantillas

El proyecto actual utiliza el motor de plantillas tpl.

Ahora hay un problema en la actualización en caliente: el motor de plantillas en realidad está cargando la plantilla repetidamente, por lo que implica si la carga repetida sobrescribirá el problema anterior.

Al observar el código fuente de la plantilla de carga, encontramos que hay tres opciones según la configuración, a saber, anular, ignorar e informar errores. La configuración que utilizamos en nuestro negocio es informar errores cuando se duplica. se encuentran, por lo que necesitamos agregar algo de lógica sin modificar las propiedades comerciales predeterminadas.

//[esl-hot-update] La anulación necesita anular window.EHU_HOT_UPDATE_OPTIONS && window.EHU_HOT_UPDATE_OPTIONS.etpl.isOverride && (namingConflict = 'override'); inicio */ case 'override': motor.targets[nombre] = target contexto.targets .push(nombre case 'ignore': break /* jshint ignore:end */ default: throw new Error('El objetivo existe; : ' + nombre); }

window.OPTIONS.etpl.isOverride Modifíquelo para implementar su propia lógica para controlar los cambios de configuración.

Este archivo luego se agrega al enrutamiento del lado del servidor y se reemplaza cuando se recibe una solicitud.

Manejo de actualizaciones js

La lógica aquí es más complicada porque requiere cambiar la lógica de carga subyacente del módulo AMD.

Js no es tan simple como una plantilla, no es una anulación directa, porque en modo AMD, cada archivo es el resultado de la ejecución de la llamada de archivo anterior.

Entonces, la lógica con la que debemos lidiar es que no solo necesitamos recargar el archivo modificado, sino también recargar recursivamente todos los archivos que lo llaman directa o indirectamente.

Por lo tanto, de las características anteriores se puede ver que esta herramienta es principalmente adecuada para la etapa actual de desarrollo del módulo comercial, porque las dependencias comerciales no serán particularmente profundas para la modificación del archivo central. No es muy adecuado. Una vez que el archivo tenga un nivel relativamente bajo, habrá muchos módulos populares que deberán recargarse más adelante.

Además, existen muchos otros peligros ocultos, que aún se están optimizando.

Resumen

Esta práctica es en realidad resolver los problemas encontrados en el negocio (el sistema es demasiado grande, la depuración es demasiado problemática), cómo resolverlos y cómo resolverlos. en soluciones y compartirlas con el equipo.

Porque hay una gran diferencia entre resolver problemas por nosotros mismos y encontrar soluciones. Por ejemplo, en el proceso de encontrar soluciones, probamos muchas cosas nuevas y superamos muchos obstáculos.

Actualmente existe un problema al depurar el recurso de origen del navegador Chrome. Si un recurso se carga repetidamente, la memoria se actualizará, pero el recurso correspondiente no, lo que provocará puntos de interrupción y asignaciones incorrectos. (punto de interrupción no válido), la solución temporal es agregar una marca de tiempo a cada solicitud, de modo que la asignación del recurso de origen se vea obligada a actualizarse. Este puede ser un punto de interrupción normal, pero los puntos de interrupción no tienen función de memoria (un error, porque el archivo ha cambiado).