3 puntos por GN⁺ 2023-07-03 | 1 comentarios | Compartir por WhatsApp
  • Un desarrollador de JavaScript con 10 años de experiencia convierte la escena de leer package.json en una prueba de dolor, mostrando cuánta complejidad acumulada del ecosistema cabe dentro de un solo archivo de configuración
  • Campos como main, browser y type: module evocan las viejas cicatrices de migración de JavaScript isomórfico, los bundles para navegador y la transición entre CommonJS y ESM
  • En scripts, dependencies y devDependencies se enredan variaciones de lint, watchman, gulp, left-pad, moment.js y problemas de gestión de paquetes como resolutions
  • eslint, postcss, jest y las herramientas de build y testing elevan el costo de mantener el entorno de desarrollo mediante reglas estrictas, errores de instalación según la plataforma y la dificultad de configurar ESM y TypeScript
  • Incluso al ver los engines de Node, la razón para no pasarse a Bun o Deno es la certeza de que el dolor no desaparecería, sino que sería peor; el desarrollador cierra el archivo y sobrevive por ahora

La prueba de leer package.json

  • La historia comienza con un desarrollador que ha usado JavaScript durante 10 años sentado frente a la computadora, obligado a abrir un archivo package.json y leerlo hasta el final
  • Este archivo no es un simple archivo de configuración, sino un objeto que le hace recordar de golpe memorias y dolor vividos en el ecosistema de JavaScript
  • version todavía no ha llegado a 1.0, y SemVer queda como un recuerdo desagradable de algo que aprendió a ignorar hace mucho tiempo
  • name muestra la situación de no poder usar el nombre deseado porque alguien lo ocupó hace 7 años y nunca volvió a actualizar el paquete

Viejas heridas de módulos y bundling

  • La coexistencia de los campos main y browser revela rastros de JavaScript isomórfico
  • Queda como una experiencia desagradable el recuerdo de haber intentado hacer require del módulo fs dentro de un bundle para navegador, junto con los hacks usados para hacerlo funcionar
  • type: module se conecta con la migración de require a import
  • La experiencia de intentar importar entre sí módulos CommonJS y ESM dejó un gran dolor

El caos de scripts y dependencias

  • scripts es el centro de un caos ardiente y doloroso
    • Hay variantes como lint, lintall, lintfast y lintdiff
    • Aparecen ejecución en paralelo, argumentos poco claros y doble escape de argumentos en formato JSON
    • Incluso después de migrar a yarn y pnpm, algunos subcomandos siguen invocando npm
  • Algunos scripts todavía usan watchman
    • Hay que recordar que no debe usarse porque no soporta symlinks
    • El issue relacionado sigue abierto desde 2015
  • También quedan scripts basados en gulp, y aunque quisieran cambiarlos por algo más moderno, nadie se atreve a reemplazarlos

El trauma que despierta la lista de paquetes

  • En dependencies hay muchísimos paquetes, y cada uno revive sus propias memorias traumáticas
  • left-pad es un paquete pequeño, pero quedó como el legendario paquete que “rompió todo internet”
  • Cada vez que se modifica la lista de dependencias, algunos paquetes imprimen largos pedidos de donación o advertencias de breaking changes en la consola
  • El desarrollador termina deseando solamente que ningún paquete malicioso robe secretos ni arruine la computadora
  • moment.js se recuerda como una librería con una buena API, pero internet decidió que era demasiado mutable, demasiado grande y que no soportaba treeshaking, así que ahora toca migrar a date-fns
  • Las versiones de los paquetes están muy atrasadas respecto a lo actual y necesitan actualización, pero por las experiencias pasadas se anticipa un gran sufrimiento
  • resolutions queda como otro dolor elegido para evitar actualizar paquetes

Otra complejidad creada por las herramientas de desarrollo

  • Al ver devDependencies, ya cuesta recordar la época en que solo hacían falta dependencias no-dev
  • La configuración de eslint se volvió tan estricta que hasta el más mínimo error aparece subrayado en rojo, y CI trata los problemas de lint como si fueran el fin del mundo
    • Eso da una falsa sensación de seguridad a los ingenieros junior del equipo
    • Hubo varias discusiones sobre qué reglas activar
    • El dolor crece en proporción a la cantidad de eslint-ignore repartidos por el codebase
  • postcss no se usa directamente, pero está ahí porque la dependencia de una dependencia lo exige
    • Cada intento de hacer npm install en una plataforma nueva provoca errores opacos de compilación en C++
  • jest empezó como un test runner rápido, pero ahora se volvió grande y pesado, y depende de algunos paquetes de Babel
    • El resto de la aplicación se transpila con una combinación de esbuild y swc
    • Configurarlo correctamente para ESM y TypeScript es tan difícil como un “proyecto científico de doctorado”
  • En el codebase intervienen muchas herramientas y parsers: TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup, terser y más
  • En engines aparece node, y se considera que aun si se migrara a Bun o Deno, el dolor no se detendría sino que empeoraría
  • Después de leer hasta la última llave de cierre, cierra la pestaña, respira hondo y por ahora sobrevive con las manos y el cerebro intactos

1 comentarios

 
GN⁺ 2023-07-03
Comentarios en Hacker News
  • Bastante gracioso. Programé en JavaScript unos 18 años y dejé de hacerlo hace como 3; la mayoría de las preocupaciones de esta lista son cosas de los últimos 10 años
    En particular se nota la ausencia de los polyfills, que sin falta habrían estado si esto se hubiera escrito en 2013. ¿Qué otras pesadillas de JavaScript de 2013 casi han desaparecido ahora? Aunque claro, fueron reemplazadas por esta lista chistosa
    Mi parte favorita fue cuando empieza a contar las herramientas y parsers que funcionan en la base de código y se acuerda de TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup, terser, y el dolor ya es tan grande que ni quiere saber si se le olvidó alguno más

    • Grunt, Gulp, CoffeeScript, IIFE, undefined sobrescrito, with, cierres para simular campos privados, prototipos modificados, variables globales por defecto, this que cambia según el lugar de invocación, coerción automática de tipos en las comparaciones…
      Sí, así fue JavaScript por más de 10 años
    • Estoy de acuerdo con lo de los callbacks. Pero si veo mi JavaScript de hace 10 años, el mayor dolor eran todas esas clases falsas hechas modificando SomeFunction.prototype
      Luego lo envolvían en una función anónima autoejecutable para devolverlo como objeto, haciendo que SomeFunction pareciera una clase, para poder llamar new SomeFunction() o SomeFunction.actualFunction(). También era terrible no tener funciones flecha, así que para ligar eventos al scope se modificaba Function.prototype y se usaba .apply(), o se caía en un infierno interminable de .bind(this) en cada callback de evento
    • Desarrollaba en Firefox para poder usar Firebug, pero igual había que dar soporte por separado a ie6, ie7, ie8
    • También hubo una época en la que se convertían los encabezados en pequeños applets de Flash para poder usar la tipografía que uno quisiera, sin quedar limitado a las fuentes instaladas por el usuario
    • El infierno de callbacks y la falta general de tipos eran enormes
      Hoy mismo tuve la mala suerte de escribir una tarea de prueba para una empresa que todavía usa JavaScript puro, sin Promise ni archivos de declaraciones, y se sintió como volver a cuando conocí Node por primera vez en 2012. El requisito de usar JavaScript lo esquivé con JSDoc, pero fue mucho peor de lo que recordaba
  • Cada vez que empiezo un proyecto nuevo de JavaScript, o más exactamente un proyecto TypeScript, siempre paso por el mismo proceso
    Normalmente es frontend, así que elijo React, aunque también me gustaría probar Svelte. Antes el bundler solía ser create-react-app o algún wrapper de Webpack, pero ahora la mejor opción es Vite porque requiere poca configuración y soporta todos los frameworks principales
    Instalo y configuro el compilador de TypeScript, aunque casi siempre lo copio y pego de una plantilla. Lo dejo apuntando a JavaScript estable reciente y módulos ESM, configuro eslint y prettier para que encajen bien, y también agrego plugins para TypeScript y React
    También instalo extensiones del IDE y dejo preparado un .devcontainer o una lista de extensiones recomendadas. No me importa tanto el estilo en sí; me importa más la consistencia del código y detectar errores, así que normalmente uso una configuración prehecha de eslint
    Después configuro pruebas unitarias con jest o vitest, y detrás vienen más ajustes relacionados con TypeScript y reglas de eslint. Como me gusta tailwind como framework de CSS, también instalo styled-components y twin.macro para que encajen bien con React, además de un plugin de Google Fonts o alguna librería de tipografías
    Así se va más o menos un día antes de poder empezar a programar. ¿Por qué hay tanto trabajo? Hay tantísima gente usando la combinación Vite + TypeScript + React/Vue/Svelte + eslint/prettier + tailwind/bootstrap + jest/vitest, ¿por qué no existe una librería sin configuración que sirva de entrada para el 90% de los casos de uso?

    • Incluso a alguien que ya sabe todo esto le toma un día. Como desarrollador más del lado de backend y operaciones, he intentado entrarle varias veces a este stack, pero sinceramente muchas veces simplemente fracasé
      Incluso cuando lograba levantar la cadena de herramientas, nunca sentía que la tuviera bajo control; parecía que cualquier mínima sacudida la podía hacer colapsar y que además no iba a poder arreglarla
      Últimamente decidí ver la mayor parte de este stack de JavaScript como un obstáculo para lo que quiero hacer, y volví a hacer una app con renderizado del lado del servidor al estilo antiguo usando Flask y Jinja2. No es moderna ni brillante, y ahora mismo ni siquiera tiene CSS, así que se ve bastante fea, pero me recomendaron intentar con CSS moderno puro. Aun así, es sorprendente qué tan rápido se pueden crear funcionalidades con ese stack
    • Hay dos linters. Solo eso ya está demente. Lo demás es peor, pero hasta la pieza más pequeña de elegir herramientas en el ecosistema de JavaScript está llena de dolor
    • Copio mi directorio starter de TypeScript y solo cambio el nombre en package.json. Claro, yo hago puro backend, pero ¿no se podría también hacer una plantilla personal así para frontend?
    • ¿npm create no hace eso?
      Si haces npm create vue, sale una configuración de Vue bastante decente y funcional con casi todo ya preparado. Estoy de acuerdo en que hay mucho boilerplate y mucha cosa extraña, pero las apps que construimos hoy para la web también son muchísimo más grandes que antes. También podrías usar JavaScript sin herramientas, solo con ESModules, pero casi nadie lo hace porque esas herramientas sí resuelven cosas reales. No es la forma más limpia, pero funciona
    • Supongo que podrías hacer un proyecto base con toda la configuración que te gusta, subirlo a GitHub, y cuando vayas a empezar algo nuevo lo clonas y solo cambias algunos nombres para dejarlo listo
  • Este es otro caso en el que la gente dice JavaScript, pero en realidad quiere decir “el revoltijo del ecosistema de Node”
    Desde el principio te dicen que tienes que abrir y leer un archivo package.json, y luego todo sigue por esa misma línea. De las cosas mencionadas, casi nada tiene que ver con JavaScript en sí

    • ¿Qué porcentaje de desarrolladores de NodeJS no usa JavaScript?
      Es cierto que JavaScript y NodeJS no son lo mismo, pero la mayoría probablemente entendió a qué se refería el autor. Habría sido mejor escribirlo con más precisión, pero tampoco diría que está completamente mal
    • Claro, entonces el ecosistema no es un blanco válido de crítica para un lenguaje
    • Intenta escribir JavaScript de verdad una vez sin un bundler que use package.json. Hasta que ECMA meta un gestor de paquetes o un bundler en la especificación oficial, package.json es en la práctica parte de JavaScript
    • Si eso te molesta tanto, cada vez que alguien diga JavaScript solo piensa que en realidad quiere decir ECMAscript
    • Sí. Esta es una crítica al ecosistema de JavaScript
  • Me gusta el tono juguetón. Después de que se te han quemado varias capas de piel y terminaciones nerviosas, sirve volver a recordar estos puntos de dolor
    Dicho al revés: puedes darle una MacBook nueva a un desarrollador junior con ganas y aventarlo al agua profunda, y aun así va a ser productivo en menos de un día. No necesita saber de contenedores, .NET, nginx ni de 100 herramientas de línea de comandos de uso frecuente; si algo falla, solo lo busca

    • Sí. Lo irónico es que, por ese compromiso, si avientas ahí a un desarrollador senior que lleva 20 años haciendo cosas que corren en el navegador, no queda listo en un día
      Aunque sabe que podría construir el barco completo en unos días si pudiera tocarlo con las manos, termina atrapado arreglando un barco dentro de una botella con las herramientas chafas que le dieron, peleando con capas de complejidad innecesaria. Así se siente cuando avanzas rápido en un proyecto personal usando solo JavaScript, HTML y CSS, y luego te meten a trabajo moderno de frontend
    • Y luego te pasas de uno a tres días armando algo pegado con cinta, te arrepientes durante los siguientes 10 años y terminas escribiendo un texto así. El ciclo continúa
    • Los juniors que conozco dicen: “hagamos un framework para manejar esta complejidad”
      No saben, con toda inocencia, que tardarán meses en hacerlo y que parte del problema es justamente el exceso de frameworks, así que al día siguiente ya estará obsoleto
    • Ahora ya no lo buscan, se lo preguntan a ChatGPT
  • “Seguí las instrucciones y me salió que grunt no estaba instalado. Como ya soy una persona mayor, no sabía muy bien qué era grunt, y mi archivo grunt tampoco parecía correcto. Así que busqué un poco y averigüé qué era grunt. Grunt es… la verdad es que todavía no sé bien qué es.”
    --Joe Armstrong, https://www.youtube.com/watch?v=lKXe3HUG2l4
    Hace unos días ejecuté gem install wayback_machine_downloader. Nunca me ha gustado Ruby lo suficiente como para meterme en su ecosistema, pero visto desde fuera, ese ecosistema parece haberse mantenido sorprendentemente estable. gem sigue siendo una herramienta que la gente usa, y Rails sigue ahí
    Estoy esperando un proyecto nuevo que sí necesite un frontend complejo y amerite pasar de 0 a 30 líneas de JavaScript. Cuando llegue ese momento, creo que podría ser más feliz con HTMX que con el framework gigante de moda

  • Este es un texto sobre npm, no sobre JavaScript
    Odio npm por este tipo de revoltijos y lo evito todo lo posible. En lo personal uso Deno, y en el trabajo usamos una cosa estilo bazel basada en monorepo que hace que npm no sea necesario
    Pero JavaScript/TypeScript me parece un lenguaje muy agradable para programar, y es el primero que elijo para casi cualquier cosa que vaya a construir. Me pone triste cuando la gente dice “JavaScript apesta” pero en realidad quiere decir que apesta construir una app de React con npm. Programar en JavaScript/TypeScript moderno es de verdad muy disfrutable

    • De acuerdo. Estoy haciendo un videojuego y decidí no usar ninguna dependencia, y programar se volvió realmente placentero
  • Se siente como si JavaScript y su ecosistema nos hubieran dejado a todos con PTSD, al punto de no poder disfrutar la comedia de este texto
    Hay demasiada discusión “seria” sobre un texto gracioso. Está bien diseccionarlo todo lo que quieran, pero estaría bueno recordar que la intención real es el humor

    • Que sea humor no significa que no sea serio
  • La verdad, el primer ecosistema con el que empecé fue Node, y después vi que las otras cosas que aprendí también tenían sus propios problemas igual de locos
    Haskell era muy difícil de usar en varias máquinas, instalarlo en MacOS en 2019 también era doloroso, y además era complicado manejar su ecosistema. Los macros y las extensiones son bastante confusos, y la compatibilidad hacia atrás del lenguaje tampoco es buena. En cambio, normalmente puedes esperar que un JavaScript de 2010 siga funcionando igual en 2023
    Incluso armar bien un entorno con imágenes de Docker o algo como codespace/gitpod ya es difícil, y las imágenes base que da GitHub tampoco son muy buenas y traen problemas
    C está más o menos bien en la mayoría de las plataformas, pero el lenguaje en sí, siendo sinceros, es complejo y exige un conocimiento enorme de todo el sistema. Como resultado, es fácil terminar con código poco portable que no sirve bien para la mayoría de los usos de la programación general
    Podría seguir, pero cualquiera que haya usado varios lenguajes sabe que todos los ecosistemas tienen varios defectos y que todos seguimos sufriendo. Con PHP nunca he logrado dejar lista la configuración de un proyecto en menos de varios días, y Elm duele menos, pero tiene sus propios problemas con el estado de dictador benevolente y la velocidad de desarrollo

    • Por eso trato de usar Go para casi todo. Aunque no sea la opción óptima, es la que menos tareas tediosas trae
    • ¿C es complejo? Es casi el único lenguaje que puedo mantener en la cabeza sin importar con qué frecuencia lo use. Parte de la sintaxis de JavaScript moderno la uso todos los días y aun así se me evapora de la memoria fácilmente
  • Soy un desarrollador políglota que se siente cómodo con varios paradigmas y lenguajes de programación, tanto en frontend como en backend
    Casi siempre reacciono exactamente así cada vez que veo que un package.json pasa de 20 líneas

    • Ahora mismo estoy mirando fijamente el nuevo frontend en Angular que estamos desarrollando; tiene cuatro componentes de frontend y cada uno tiene un package.json de más de 200 líneas
      Lo digo en voz alta, como si estuviera tratando de alejar al demonio. “No debo temer. El temor mata la mente. El temor es la pequeña muerte que conduce a la destrucción total. Afrontaré mi temor. Permitiré que pase sobre mí y a través de mí. Y cuando haya pasado, volveré el ojo interior para ver su camino. Allí donde haya pasado el temor no quedará nada. Solo quedaré yo.”
      Estoy llorando
    • Igual yo. Aunque, saliéndome del tema, el enlace del perfil me lo bloquea uBlock Origin y me lleva a una madriguera de sitios web raros. Nunca he usado hackernewsers, así que no sé si eso es lo normal
  • Es la escena de un desarrollador de JavaScript a la antigua leyendo el artículo y sufriendo PTSD y flashbacks
    No debo temer. El temor mata la mente. El temor es la pequeña muerte que conduce a la destrucción total
    Afrontaré mi temor. Permitiré que pase sobre mí y a través de mí. Y cuando haya pasado, volveré el ojo interior para ver su camino
    Allí donde haya pasado el temor no quedará nada. Solo quedaré yo
    Termina de leer el artículo y se da cuenta de que sobrevivió, pero ya está empapado en sudor