JavaScript Gom Jabbar
(frantic.im)- Un desarrollador de JavaScript con 10 años de experiencia convierte la escena de leer
package.jsonen una prueba de dolor, mostrando cuánta complejidad acumulada del ecosistema cabe dentro de un solo archivo de configuración - Campos como
main,browserytype: moduleevocan las viejas cicatrices de migración de JavaScript isomórfico, los bundles para navegador y la transición entre CommonJS y ESM - En
scripts,dependenciesydevDependenciesse enredan variaciones de lint,watchman, gulp,left-pad, moment.js y problemas de gestión de paquetes comoresolutions eslint,postcss,jesty 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
enginesde 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.jsony 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
versiontodavía no ha llegado a1.0, y SemVer queda como un recuerdo desagradable de algo que aprendió a ignorar hace mucho tiemponamemuestra 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
mainybrowserrevela rastros de JavaScript isomórfico - Queda como una experiencia desagradable el recuerdo de haber intentado hacer
requiredel módulofsdentro de un bundle para navegador, junto con los hacks usados para hacerlo funcionar type: modulese conecta con la migración derequireaimport- La experiencia de intentar importar entre sí módulos CommonJS y ESM dejó un gran dolor
El caos de scripts y dependencias
scriptses el centro de un caos ardiente y doloroso- Hay variantes como
lint,lintall,lintfastylintdiff - 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
- Hay variantes como
- 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
dependencieshay muchísimos paquetes, y cada uno revive sus propias memorias traumáticas left-pades 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
resolutionsqueda 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
eslintse 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-ignorerepartidos por el codebase
postcssno se usa directamente, pero está ahí porque la dependencia de una dependencia lo exige- Cada intento de hacer
npm installen una plataforma nueva provoca errores opacos de compilación en C++
- Cada intento de hacer
jestempezó 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
enginesaparecenode, 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
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
undefinedsobrescrito,with, cierres para simular campos privados, prototipos modificados, variables globales por defecto,thisque 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
SomeFunction.prototypeLuego lo envolvían en una función anónima autoejecutable para devolverlo como objeto, haciendo que
SomeFunctionpareciera una clase, para poder llamarnew SomeFunction()oSomeFunction.actualFunction(). También era terrible no tener funciones flecha, así que para ligar eventos al scope se modificabaFunction.prototypey se usaba.apply(), o se caía en un infierno interminable de.bind(this)en cada callback de eventoHoy 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
.devcontainero 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 eslintDespué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 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
package.json. Claro, yo hago puro backend, pero ¿no se podría también hacer una plantilla personal así para frontend?npm createno 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 funcionaEste 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í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
package.json. Hasta que ECMA meta un gestor de paquetes o un bundler en la especificación oficial,package.jsones en la práctica parte de JavaScriptMe 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
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
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
“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
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
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
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.jsonpasa de 20 líneaspackage.jsonde más de 200 líneasLo 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
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