Presentamos Packem: un paquete experimental súper rápido escrito en Rust

Packem es un paquete de módulos de JavaScript precompilado experimental implementado principalmente en Rust. También puede manejar una variedad de otros tipos de archivos como YAML / TOML, archivos de sombreado de fragmentos y mucho más. Visite el sitio web o la página de GitHub para comenzar rápidamente.

Packem resuelve las dependencias de un módulo y las rehidrata en un gráfico de módulo, una lista plana que contiene interfaces de módulo que son esencialmente referencias a estructuras de datos mutables en memoria que contienen metadatos especiales de un módulo en el gráfico del módulo.

La mayor parte de la lógica empresarial se abstrae en Rust mediante enlaces FFI para permitir interacciones de bajo nivel entre ambos extremos. Los binarios de Rusty están disponibles como complementos precompilados de Node C / C ++ en el repositorio de Packem. Se usa un CI basado en la nube para ejecutar algunos scripts con instalaciones pre-gyp, lo que genera binarios específicos del sistema operativo con soporte para versiones posteriores de Node (8, 9, 10).

Esta capa del núcleo de Packem es lo que se conoce como contexto lógico (LC) . Todas las demás operaciones que no tienen prioridad explícita se regresan al tiempo de ejecución general de Node, que en términos de Packem es el contexto de tiempo de ejecución (RC) . Lea más sobre contextos aquí.

En teoría, el gráfico del módulo se mantiene plano para evitar errores comunes que llevarían a recorridos innecesarios si se usara un árbol en su lugar. Esto permite al RC realizar un seguimiento de casos como dependencias circulares profundas o importaciones dinámicas fuertemente anidadas (división de código), entre otros, de manera apropiada con las implicaciones de rendimiento mínimas o los efectos secundarios posibles.

Se pueden encontrar más detalles en README.md de Packem.

He tenido esta idea en mente, pero nunca planeé ejecutarla hasta que uní fuerzas con Saddam M. Realmente me ha interesado ver la agrupación de módulos como un concepto seguro para que cualquiera pueda aprender, comprender e implementar. Tener gente luchando con configuraciones, documentación y complementos fue extremadamente horrible y me gustaría aprovechar la oportunidad para cambiar eso. Con usted. Con Packem.

Historia rápida

Me tomé un tiempo para agotar la mayoría de los paquetes escritos en un entorno sin JavaScript. Descubrí que la mayoría de ellos olvidó que se supone que son un paquete y no una biblioteca C / C ++ de los oscuros años 19.

Lo que quería era un paquete que hiciera la mayor parte del trabajo pesado en un lenguaje cercano al metal para el usuario sin requerir ninguna interacción con sus componentes internos. Entonces encontré a Rust. ¡Un lenguaje de sistemas inteligente y conciso que muestra algunas características loables como un modelo de concurrencia intrépido, seguridad de tipos y más! Esperaría lo mismo del uso de C / C ++, pero prefiero seguir con Rust, ya que es bastante sencillo cuando se trata de la administración de memoria.

¿Por qué otro paquete?

Entonces, ¿cuál es el problema aquí? ¿Por qué necesitamos otra herramienta de compilación si ya tenemos algunas increíbles como webpack, Parcel, Rollup, etc.? Te acompañaré con algunas razones. Quizás tenga sus propios intereses en que se reduzcan considerablemente los tiempos de construcción de desarrollo y producción.

Es 2019, ya no necesitamos herramientas lentas

Aunque Packem es más rápido que webpack 4, es más del doble de rápido que Parcel (con compilación multinúcleo) . En una prueba de referencia, agrupamos Lodash v4.17.1 con Packem y Parcel y este fue el resultado:

Nunca tome ningún banco por su valor nominal. Puede probarlo usted mismo aquí.

La razón por la que no me molesté en comparar Parcel con webpack fue porque webpack 4 es profundamente más rápido que Parcel. Probé este hecho usando los propios bancos de Sean T. Larkin y se puede encontrar un hilo en Twitter aquí.

Porque podemos. Cualquiera puede, ¿verdad?

Por supuesto, lo que tendrá más sentido es porque podemos . Teníamos la idea de tener tiempos de agrupación más rápidos con una interfaz Rusty, ya sea con FFI o WASM (todavía no estaba seguro). FFI era más razonable en cuanto a velocidad y DX se refería, así que decidimos implementar Packem en los enlaces Rust FFI.

Experimentamos algunos problemas relacionados con los subprocesos, por lo que no hicimos mucho uso de los recursos disponibles. Como resultado, usamos múltiples procesos secundarios de nodos (con node-worker-farm ) , la misma técnica que Parcel usa para la compilación de múltiples núcleos, pero para gráficos de módulos más grandes, ya que agrega un tiempo de inicio significativo además del tiempo de actividad de Node cuando se usa con gráficos de módulos más pequeños. .

Estilo de configuración

Esta fue una parte complicada. Había muchas preguntas que necesitaban una buena respuesta para compensar la elección del estilo de configuración correcto. ¿Estático o dinámico? JSON / YAML / TOML? Nuestra elección se basó completamente en si necesitábamos que Packem:

  1. Tener un estilo de configuración más ordenado y
  2. Sea independiente de otras configuraciones de usuario personalizadas como .babelrc o package.json .

En pocas palabras, procedimos con un estilo de configuración estática ya que encontramos que era exactamente lo que necesitábamos. Algo que podría decirle de manera declarativa a Packem cómo administrar el ciclo del paquete . Se aclararon todos los límites de tener una configuración estática.

Otro aspecto de interés fue el tipo de archivo que deberíamos utilizar para la configuración. JSON que es más común para una abrumadora mayoría de desarrolladores de JavaScript o estilo YAML / TOML / XML, que son menos comunes pero tienen sus propias ventajas. Todavía se hizo una sugerencia para el soporte JSON (# 5).

JSON simplemente no se cortó debido a todas las comillas de cadena innecesarias, las llaves y las llaves, lo cual tiene sentido ya que es un formato de intercambio de datos . Un enfoque similar a XML no merece respeto con respecto a su uso como formato de configuración, ya que empeora las cosas que JSON en lo que respecta a los caracteres innecesarios. TOML introdujo muchas líneas nuevas, y la depuración de opciones anidadas no pareció ser atractiva a la vista, ya que sabíamos que los complementos de Packem podrían volverse realmente nítidos.

¡El ganador final fue YAML! Fue capaz de pasar por todos los aspectos de ser un formato de configuración adecuado (al menos para Packem). Eso:

  1. Hace que la configuración sea indolora.
  2. Utiliza un enfoque elegante.
  3. Todavía es familiar para el ojo de JavaScript
  4. Fue diseñado específicamente para este caso de uso (configuraciones) .

Aquí hay un ejemplo de una configuración típica de Packem ( packem.config.yml) . Compruébelo usted mismo y piense en escribir el mismo contenido en un estilo JSON / TOML / XML.

Para su información, ¡solo las dos primeras opciones son necesarias! ?

Ampliando Packem

Esta función aún no está implementada.

A veces, es posible que necesitemos usar una función que aún no existe , que no esté implementada en Packem o que sea muy específica de nuestro proyecto . En ese caso, tendría dos formas de resolver sus necesidades:

  1. Cree un complemento de Packem para su caso de uso (que es la opción recomendada).
  2. Construya un RC personalizado sobre los binarios de Packem.

El uso de Rust nos da la oportunidad de reformar el LC en otros formatos binarios, como WebAssembly, que permitirá a Packem exhibir múltiples objetivos de compilación:

  1. Un complemento C / C ++ basado en NAPI con binarios específicos de la plataforma requeridos por el RC predeterminado de Packem.
  2. Un binario basado en WebAssembly que es multiplataforma y se inyecta en el RC.
  3. Independiente por defecto de Packem que usa WebAssembly con una implementación compatible con el navegador del RC.
Los dos últimos aún no están en el radar ya que aún se están resolviendo las refactorizaciones internas.

Se espera que la guía avanzada pronto le muestre cómo crear una herramienta de compilación personalizada utilizando los binarios de Packem para satisfacer sus propias necesidades en caso de que necesite utilizar Packem fuera del navegador y los entornos de nodo. Estos binarios completan toda la generación de gráficos y duplican el filtrado y otros aspectos relacionados con los gráficos. Esto significa que puede usar su serializador personalizado, monitor de archivos, sistema de complementos, etc. Es muy parecido a cómo puede construir su renderizador personalizado sobre OpenGL.

  1. Aún puede adoptar el sistema de complementos de Packem, ya que le permitirá integrar el ecosistema de complementos de Packem con su paquete personalizado.
  2. Si no está seguro de si necesitaría o no crear un paquete personalizado, sepa que no siempre será necesario. Primero intente presentar un problema.
  3. Es una garantía de que estos binarios acelerarán su flujo de trabajo en función de sus casos de uso específicos.

Estado actual

  • ✂ División de código para modos de desarrollo y producción.
  • ? CLI mejorado (`- verbose`) para obtener mejor información sobre el ciclo de agrupación.
  • ? Interfaces de módulo para permitir una fácil manipulación del gráfico del módulo.
  • ✔ Prioridad adecuada. Las funcionalidades nativas encajan perfectamente en el LC. Esto significa que hay mayores posibilidades de compilaciones rápidas.
  • ? Exportar N ativeUtils para uso externo de funcionalidades nativas, incluido g, enerateModuleGraph que vuelve a ejecutar el proceso de generación de un gráfico de módulo. Es pesado pero útil en los casos en que necesite un clon del gráfico del módulo activo actual. Usarlo significa duplicar el tiempo de construcción, así que úselo con cuidado.

¿Que sigue?

Estas son las características que esperamos tener pronto en los próximos lanzamientos. Con sus esfuerzos, podríamos hacer la agrupación de la manera correcta . Cuando Packem esté en 1.0 , esperamos tener soporte completo para todas las funciones enumeradas a continuación y las otras mencionadas en la hoja de ruta de Packem.

  • Un paquete independiente compatible con el navegador con el LC en WebAssembly para una integración más cercana con el sistema subyacente. Axel Rauschmayer ya hizo una solicitud de función para tener una versión compatible con Node en WASM. Para que conste, estaremos trabajando en ambos pronto.
  • Tembloroso, pero avanzado. Resolver importaciones con nombre / sin nombre y eliminar el código muerto debería ser muy sencillo. Esto significa que puede usar bibliotecas como lodash en lugar de lodash-es sin preocuparse de si su código se eliminará o no.
  • Auto Config. Como Zero Config, pero orientado a valores predeterminados para mayor flexibilidad.
  • Opciones avanzadas de CLI para que el desarrollo con Packem sea una segunda naturaleza.
  • Mejor informe de errores.
  • Más objetivos medioambientales. Packem solo puede agruparse para el navegador a partir de ahora. Con el tiempo, esperamos admitir Node CJS y también otros formatos.
  • Más complementos. ¡Necesitamos más complementos! Packem tiene un conjunto de complementos comunes para que pueda comenzar más rápido. Pero para hacer crecer una comunidad, necesitaremos un gran ecosistema de complementos. Consulte los complementos comunes disponibles o la sección de complementos en el sitio para comenzar a desarrollar un complemento de inmediato.
  • Y mucho más…

Recursos

  • Packem en GitHub
  • Solicitudes de hoja de ruta y funciones
  • Sitio oficial de Packem
  • Crear complementos con Packem
  • División de código con Packem
  • El gráfico del módulo

Packem no ha llegar a 1.0 todavía . Si ha encontrado que Packem es interesante para usted, intente contribuir con Packem creando complementos, actualizando la documentación, apoyándonos financieramente, representando a Packem en conferencias o por cualquier otro medio. ¡Agradecemos sus esfuerzos!

¡Feliz empaquetado! ???