3 पॉइंट द्वारा GN⁺ 2023-07-03 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • 10 साल के अनुभव वाला JavaScript डेवलपर package.json पढ़ने के दृश्य को दर्द की परीक्षा बनाकर दिखाता है कि एक config file में ecosystem की जमा हुई complexity कितनी भरी होती है
  • main, browser, type: module जैसे fields Isomorphic JavaScript, browser bundle, और CommonJS से ESM transition की पुरानी migration चोटों की याद दिलाते हैं
  • scripts, dependencies, devDependencies में lint variants, watchman, gulp, left-pad, moment.js, resolutions जैसे पुराने tools और package management समस्याएँ उलझी हुई हैं
  • eslint, postcss, jest और build/test tools सख्त rules, platform-specific install errors, और ESM/TypeScript configuration की कठिनाई के जरिए development environment maintenance cost बढ़ाते हैं
  • Node engines देखते हुए भी Bun या Deno पर न जाने की वजह यह यकीन है कि दर्द खत्म नहीं होगा, बल्कि और बढ़ेगा; डेवलपर file बंद करता है और फिलहाल बच निकलता है

package.json पढ़ने की परीक्षा

  • कहानी उस स्थिति से शुरू होती है जहाँ 10 साल से JavaScript इस्तेमाल कर रहा डेवलपर अपने कंप्यूटर के सामने package.json file खोलकर उसे अंत तक पढ़ने को मजबूर है
  • यह file कोई साधारण config file नहीं है, बल्कि JavaScript ecosystem में झेली गई यादों और दर्द को एक साथ वापस बुलाने वाली चीज है
  • version अभी भी 1.0 तक नहीं पहुँचा है, और SemVer बहुत पहले से अनदेखा करना सीख ली गई एक अप्रिय याद बनकर रह गया है
  • name दिखाता है कि 7 साल पहले किसी ने एक package name कब्जा कर लिया और फिर update नहीं किया, इसलिए मनचाहा नाम इस्तेमाल नहीं किया जा सकता

modules और bundling की पुरानी चोटें

  • main और browser fields साथ मौजूद हैं, जिससे Isomorphic JavaScript के निशान दिखते हैं
  • browser bundle में fs module को require करने की याद, और उसे चलाने के लिए किए गए hacks, अप्रिय अनुभव बनकर रह गए हैं
  • type: module का संबंध require से import की ओर migration से है
  • CommonJS और ESM modules को एक-दूसरे में import करने की कोशिश का अनुभव बड़ा दर्द बनकर रह गया है

scripts और dependencies की अव्यवस्था

  • scripts गर्म और दर्दनाक अव्यवस्था का केंद्र है
    • lint, lintall, lintfast, lintdiff जैसे variants हैं
    • parallel execution, अस्पष्ट arguments, और JSON-format arguments की double escaping सामने आती है
    • yarn और pnpm पर जाने के बाद भी कुछ subcommands अब भी npm को call करते हैं
  • कुछ scripts अभी भी watchman इस्तेमाल करते हैं
    • यह याद रखना पड़ता है कि symlink support न होने के कारण इसे इस्तेमाल नहीं करना चाहिए
    • संबंधित issue 2015 से खुला है
  • gulp-based scripts भी बचे हुए हैं; उन्हें किसी modern चीज से बदलना चाहते हैं, लेकिन कोई भी replacement की हिम्मत नहीं करता

package list से लौटता trauma

  • dependencies में बहुत सारे packages हैं, और हर package अपनी-अपनी trauma memory को फिर से जगा देता है
  • left-pad एक छोटा package है, लेकिन “पूरे internet को तोड़ देने वाला” legendary package बनकर रह गया है
  • dependency list में बदलाव करते ही कुछ packages console में donation requests या breaking change warnings लंबी-लंबी print करते हैं
  • डेवलपर बस यही उम्मीद करने की स्थिति में आ जाता है कि कोई malicious package secrets चोरी न करे या computer को खराब न कर दे
  • moment.js एक अच्छे API वाली library के रूप में याद है, लेकिन internet ने उसे बहुत mutable, बहुत बड़ा, और treeshaking support न करने वाला माना; अब date-fns पर migration करना है
  • package versions आज के standards से काफी पीछे हैं और upgrade की जरूरत है, लेकिन पुराने upgrade अनुभवों के कारण बड़े दर्द की आशंका है
  • resolutions package upgrades से बचने के लिए चुना गया एक और दर्द बनकर रह गया है

development tools से बनी एक और complexity

  • devDependencies देखते हुए वह दौर याद करना मुश्किल है जब सिर्फ non-dev dependency की जरूरत होती थी
  • eslint configuration इतना सख्त हो गया है कि छोटी गलती पर भी लाल underline आ जाती है, और CI lint issues को दुनिया के अंत जैसा मानता है
    • यह team के junior engineers को गलत तरह की सुरक्षा-भावना देता है
    • कौन-से rules enable किए जाएँ, इस पर कई बार बहस हुई है
    • codebase भर में मौजूद eslint-ignore की संख्या जितना ही दर्द बढ़ता है
  • postcss सीधे इस्तेमाल नहीं होता, लेकिन dependency की dependency के लिए जरूरी package के रूप में मौजूद है
    • हर बार नए platform पर npm install चलाने की कोशिश में अस्पष्ट C++ compile errors पैदा करता है
  • jest एक fast test runner के रूप में शुरू हुआ था, लेकिन अब बड़ा और भारी हो गया है, और कुछ Babel packages पर निर्भर है
    • application का बाकी हिस्सा esbuild और swc के combination से transpile होता है
    • ESM और TypeScript के लिए इसे सही ढंग से configure करना “PhD science project” जितना कठिन है
  • codebase में TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup, terser जैसे कई tools और parsers शामिल हैं
  • engines में node specified है, और माना जाता है कि Bun या Deno पर जाने से भी दर्द रुकेगा नहीं, बल्कि और खराब होगा
  • आखिरी closing brace तक पढ़ने के बाद वह tab बंद करता है, साँस सँभालता है, और हाथों व दिमाग के सलामत रहते फिलहाल बच निकलता है

1 टिप्पणियां

 
GN⁺ 2023-07-03
Hacker News की राय
  • काफ़ी मज़ेदार। मैंने लगभग 18 साल JavaScript लिखा और लगभग 3 साल पहले छोड़ दिया, लेकिन इस सूची की ज़्यादातर चिंताएँ पिछले 10 सालों की चीज़ें हैं
    ख़ास तौर पर यह ध्यान खींचता है कि इसमें polyfill नहीं है, जो 2013 में लिखा जाता तो ज़रूर होता। 2013 के JavaScript दुःस्वप्नों में से और क्या अब लगभग ग़ायब हो चुका है? बेशक उसकी जगह यह मज़ेदार सूची आ गई है
    मेरा पसंदीदा हिस्सा वह था जहाँ कोडबेस में काम करने वाले टूल और parser गिनते-गिनते TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup, terser याद आते हैं, और दर्द इतना बढ़ जाता है कि यह भी जानना नहीं चाहते कि कुछ और छूट तो नहीं गया

    • Grunt, Gulp, CoffeeScript, IIFE, ओवरराइड किया गया undefined, with, private fields की नकल के लिए closures, बदले हुए prototypes, default global variables, कॉल की जगह के हिसाब से बदलने वाला this, comparison के समय automatic type coercion…
      हाँ, JavaScript के 10 से ज़्यादा साल ऐसे ही गुज़रे
    • callback वाली बात से सहमत हूँ। लेकिन 10 साल पहले के मेरे JavaScript को देखूँ तो सबसे बड़ा दर्द SomeFunction.prototype को बदलकर बनाए गए fake classes थे
      उसे तुरंत चलने वाले anonymous function में लपेटकर object के रूप में लौटाते थे, ताकि SomeFunction को class की तरह दिखाया जा सके और new SomeFunction() या SomeFunction.actualFunction() कॉल किया जा सके। arrow functions नहीं थे, इसलिए event को scope में बाँधने के लिए Function.prototype तक बदल देते थे और .apply() इस्तेमाल करते थे, या हर event callback में अंतहीन .bind(this) नरक में फँस जाते थे
    • Firebug इस्तेमाल करने के लिए Firefox में development करते हुए ie6, ie7, ie8 को अलग-अलग support करना पड़ता था
    • एक समय ऐसा भी था जब users के install किए हुए fonts तक सीमित न रहने के लिए headers को छोटे Flash applet में बदल देते थे ताकि मनचाहा font इस्तेमाल कर सकें
    • callback hell और कुल मिलाकर types की कमी बहुत बड़ी समस्या थी
      आज भी मुझे एक ऐसी company के test assignment लिखने का दुर्भाग्य झेलना पड़ा जो अभी भी Promise या declaration files के बिना pure JavaScript इस्तेमाल करती है, और ऐसा लगा जैसे 2012 में पहली बार Node से मिला था। JavaScript इस्तेमाल करने की शर्त को मैंने JSDoc से किसी तरह संभाला, लेकिन यह मेरी याद से कहीं ज़्यादा बुरा था
  • जब भी नया JavaScript, या सही कहें तो TypeScript project, शुरू करता हूँ तो हमेशा वही प्रक्रिया दोहरानी पड़ती है
    आमतौर पर frontend होता है, इसलिए React चुनता हूँ, हालांकि Svelte भी आज़माना चाहता हूँ। bundler पहले create-react-app या Webpack wrapper हुआ करता था, लेकिन अब कम configuration और सभी बड़े frameworks के support की वजह से Vite सबसे अच्छा विकल्प है
    TypeScript compiler install और configure करता हूँ, अक्सर किसी template से copy-paste करके। target latest stable JavaScript और ESM modules पर रखता हूँ, eslint और prettier को साथ में configure करता हूँ, और TypeScript व React जैसे plugins भी जोड़ता हूँ। commit से पहले Prettier और eslint चलाने वाला hook भी डालता हूँ
    IDE extensions भी install करता हूँ और .devcontainer या recommended extensions की list भी बना देता हूँ। मुझे styling से ख़ास मतलब नहीं, code consistency और mistakes पकड़ना ज़्यादा ज़रूरी है, इसलिए eslint के लिए आमतौर पर तैयार config इस्तेमाल करता हूँ
    उसके बाद jest या vitest जैसे unit test setup करता हूँ, और फिर TypeScript से जुड़ी settings और eslint rules फिर साथ आते हैं। CSS framework के लिए tailwind पसंद है, इसलिए styled-components और twin.macro भी install करता हूँ ताकि React के साथ अच्छे से फिट हो, और Google Fonts plugin या font library भी जोड़ता हूँ
    इस सब में लगभग एक दिन निकल जाता है, तब जाकर programming शुरू कर पाता हूँ। इतना सारा काम क्यों है? Vite + TypeScript + React/Vue/Svelte + eslint/prettier + tailwind/bootstrap + jest/vitest का combo इस्तेमाल करने वाले इतने लोग हैं, फिर भी 90% use cases के लिए तैयार zero-config library क्यों नहीं है?

    • जिसे यह सब पहले से आता हो, उसे भी एक दिन लग जाता है। backend और ops तरफ़ के developer के रूप में मैंने कई बार ऐसे stack में घुसने की कोशिश की, लेकिन सच कहूँ तो कई बार बस नाकाम रहा
      toolchain को किसी तरह चालू कर भी लूँ तो कभी महसूस नहीं हुआ कि यह मेरे control में है, और लगता था कि हल्का-सा झटका लगे तो सब गिर जाएगा और मैं उसे ठीक भी नहीं कर पाऊँगा
      हाल में मैंने तय किया कि इस JavaScript stack का ज़्यादातर हिस्सा उस काम के लिए रुकावट है जो मैं करना चाहता हूँ, इसलिए पहले की तरह Flask और Jinja2 आधारित server-side rendered app बना लिया। यह modern या चमकदार नहीं है, और CSS भी नहीं है इसलिए अभी काफ़ी बदसूरत है, लेकिन मुझे pure modern CSS अपनाने की सलाह मिली। फिर भी यह चौंकाने वाला है कि उस stack में features कितनी जल्दी बना सकता हूँ
    • linter दो हैं। सिर्फ़ यही बात पागलपन है। बाक़ी चीज़ें और भी बदतर हैं, लेकिन JavaScript ecosystem में tools चुनने का सबसे छोटा हिस्सा भी दर्द से भरा है
    • TypeScript starter directory कॉपी कर लेता हूँ और package.json में सिर्फ़ नाम बदलता हूँ। हाँ, मैं ज़्यादातर backend ही करता हूँ, लेकिन क्या frontend के लिए भी ऐसा personal template नहीं बनाया जा सकता?
    • क्या npm create यह काम नहीं करता?
      npm create vue चलाने पर ज़्यादातर setup पहले से किया हुआ एक काफ़ी अच्छा और काम करने वाला Vue configuration मिल जाता है। मैं मानता हूँ कि boilerplate और इधर-उधर की चीज़ें बहुत हैं, लेकिन आजकल जो apps हम web पर बनाते हैं वे पहले से कहीं बड़े हो गए हैं। सिर्फ़ ESModules के सहारे बिना tools के JavaScript इस्तेमाल कर सकते हैं, लेकिन आमतौर पर ऐसा नहीं करते क्योंकि वे tools सच में कुछ काम के होते हैं। यह सबसे साफ़ तरीका नहीं है, लेकिन किसी न किसी तरह काम करता है
    • ऊपर अपनी पसंद का पूरा setup डालकर एक stub project बना कर GitHub पर रख दो
      नया project शुरू करते समय उसे clone करके बस कुछ जगह नाम बदलो, और काम शुरू करने के लिए तैयार हो जाओ
  • लोग इसे JavaScript कहते हैं, लेकिन असल में इसका मतलब “Node ecosystem का कबाड़” होता है
    शुरुआत से ही package.json फ़ाइल खोलकर पढ़ने को कहा जाता है, और आगे भी बात उसी दिशा में चलती रहती है। जिन चीज़ों का ज़िक्र है, उनमें JavaScript खुद से जुड़ी चीज़ें लगभग नहीं हैं

    • NodeJS का इस्तेमाल न करने वाले JavaScript डेवलपर्स का अनुपात कितना होगा?
      यह सही है कि JavaScript और NodeJS एक ही चीज़ नहीं हैं, लेकिन ज़्यादातर लोगों ने समझ लिया होगा कि लेखक का मतलब क्या था। और ज़्यादा सटीक लिखा जाता तो अच्छा होता, लेकिन इसे पूरी तरह ग़लत कहना भी मुश्किल है
    • सही, तो ecosystem भाषा की आलोचना का वैध लक्ष्य नहीं है
    • बिना package.json इस्तेमाल करने वाले bundler के JavaScript सच में एक बार लिखकर देखो। जब तक ECMA आधिकारिक spec में package manager या bundler नहीं डालता, package.json व्यावहारिक रूप से JavaScript का हिस्सा है
    • अगर यह इतना खटकता है, तो जब भी कोई JavaScript कहे, मान लो कि उसका मतलब ECMAscript है
    • सही। यह JavaScript ecosystem की आलोचना है
  • इसका मज़ाकिया लहजा अच्छा है। त्वचा और नसों के सिरे कई परतों तक जल जाने के बाद, दर्द के ऐसे बिंदुओं को फिर से याद करना फ़ायदेमंद होता है
    उल्टा कहें तो, किसी उत्साही junior डेवलपर को नई MacBook देकर गहरे पानी में फेंक दो, तो भी वह एक दिन के भीतर productive हो सकता है। उसे containers, .NET, nginx, या अक्सर इस्तेमाल होने वाले 100 command-line tools जानने की ज़रूरत नहीं, और समस्या आए तो बस search कर सकता है

    • सही। विडंबना यह है कि उसी tradeoff की वजह से, अगर 20 साल से browser में चलने वाली चीज़ें बना रहे किसी senior डेवलपर को भी इसमें डाल दो, तो वह एक दिन में तैयार नहीं होगा
      यह जानते हुए भी कि अगर सीधे हाथ लगाने दिया जाए तो कुछ दिनों में पूरा जहाज़ बना सकता है, उसे दिए गए घटिया tools के साथ बोतल के अंदर जहाज़ ठीक करने जैसा काम करना पड़ता है, और अनावश्यक जटिलता की परतों से लड़ना पड़ता है। सिर्फ JavaScript, HTML, CSS से कोई personal project तेज़ी से आगे बढ़ाने के बाद जब modern frontend के काम में झोंक दिया जाता है, तो बिल्कुल ऐसा ही लगता है
    • फिर आप एक से तीन दिन तक कुछ जोड़-तोड़ कर बना लेते हैं, अगले 10 साल पछताते हैं, और फिर ऐसी पोस्ट लिखते हैं। चक्र चलता रहता है
    • जिन juniors को मैं जानता हूँ, वे कहते हैं: “चलो इस complexity को संभालने के लिए एक framework बनाते हैं”
      उसे बनाने में कई महीने लगते हैं, और यह कि समस्या का एक हिस्सा framework की भरमार है, और वह अगले ही दिन पुराना पड़ जाएगा — यह उन्हें भोलेपन में समझ नहीं आता
    • अब लोग search नहीं करते, ChatGPT से पूछते हैं
  • “मैंने निर्देशों के मुताबिक किया, फिर उसने कहा कि grunt installed नहीं है। अब मैं बूढ़ा आदमी हूँ, इसलिए मुझे ठीक से पता नहीं था कि grunt क्या है, और मेरी grunt file में भी कुछ गड़बड़ थी। तो मैंने थोड़ा search किया और पता लगाया कि grunt क्या है। Grunt है… सच कहूँ तो अभी भी मुझे ठीक से नहीं पता।”
    --Joe Armstrong, https://www.youtube.com/watch?v=lKXe3HUG2l4
    कुछ दिन पहले मैंने gem install wayback_machine_downloader चलाया। Ruby नाम की भाषा मुझे कभी इतनी पसंद नहीं आई कि उसके ecosystem में उतर जाऊँ, लेकिन बाहर से देखने पर उसका ecosystem हैरान करने वाली हद तक स्थिर बना रहा है। gem अभी भी इस्तेमाल होने वाला tool है, और Rails भी अभी भी मौजूद है
    मैं उस नए प्रोजेक्ट का इंतज़ार कर रहा हूँ जिसमें complex frontend की ज़रूरत हो और JavaScript की 0~30 लाइनों से आगे जाना पड़े। तब शायद आजकल के सबसे लोकप्रिय विशाल framework की बजाय HTMX के साथ मैं ज़्यादा खुश रहूँगा

  • यह JavaScript के बारे में नहीं, npm के बारे में पोस्ट है
    ऐसी बकवास की वजह से मैं npm से नफ़रत करता हूँ और जितना हो सके उससे बचता हूँ। निजी तौर पर मैं Deno इस्तेमाल करता हूँ, और काम पर monorepo-आधारित bazel-जैसी किसी चीज़ का इस्तेमाल करता हूँ जो npm की ज़रूरत ही ख़त्म कर देती है
    लेकिन मुझे JavaScript/TypeScript प्रोग्रामिंग के लिए अच्छी भाषाएँ लगती हैं, और मैं कुछ भी बनाऊँ, सबसे पहले इन्हीं को चुनता हूँ। जब लोग कहते हैं “JavaScript बेकार है”, लेकिन असल में उनका मतलब होता है कि npm के साथ React app build करना बेकार है, तो दुख होता है। modern JavaScript/TypeScript coding सच में बहुत मज़ेदार है

    • सहमत। मैं एक video game बना रहा हूँ, और dependencies बिल्कुल न इस्तेमाल करने का फ़ैसला किया, तो coding सच में बहुत मज़ेदार हो गई
  • ऐसा लगता है कि JavaScript और उसके ecosystem ने हम सबको इतना PTSD दे दिया है कि हम इस पोस्ट की comedy का मज़ा ही नहीं ले पा रहे
    एक मज़ेदार पोस्ट पर “गंभीर” बहस कुछ ज़्यादा ही हो रही है। चाहो तो इसे खुलकर dissect करो, लेकिन यह याद रखना अच्छा होगा कि असली मंशा humor है

    • humor होने का मतलब यह नहीं कि वह गंभीर नहीं है
  • सच कहूँ तो, मेरा पहला ecosystem Node था, और बाद में जो चीज़ें सीखीं, उनमें भी हर एक के अपने पागलपन भरे मसले थे
    Haskell को कई मशीनों पर इस्तेमाल करना बहुत मुश्किल था, 2019 में उसे MacOS पर install करना भी दर्दनाक था, और ecosystem management भी कठिन था। macros और extensions काफ़ी उलझाऊ हैं, और भाषा की backward compatibility भी अच्छी नहीं है। इसके उलट, 2010 का JavaScript आम तौर पर 2023 में भी वैसे ही चलने की उम्मीद की जा सकती है
    Docker image या codespace/gitpod जैसे environment को ठीक से बनाना भी मुश्किल है, और GitHub की दी हुई default image भी बहुत अच्छी नहीं है और समस्याएँ रखती है
    C ज़्यादातर platforms पर आम तौर पर ठीक है, लेकिन भाषा खुद ईमानदारी से कहें तो जटिल है और पूरे system के बारे में बहुत व्यापक ज्ञान माँगती है। नतीजा यह होता है कि ऐसा कम portable code बनना आसान है जो सामान्य programming के ज़्यादातर उपयोगों के लिए उपयुक्त नहीं होता
    और भी कह सकता हूँ, लेकिन जिसने कई भाषाएँ इस्तेमाल की हैं, वह जानता है कि हर ecosystem में कई कमियाँ हैं और हम सब लगातार किसी न किसी रूप में पीड़ित रहते हैं। PHP में मैंने कभी कुछ दिनों के भीतर project setup पूरा नहीं किया, और Elm कम तकलीफ़देह है, लेकिन उसकी अपनी समस्याएँ हैं — benevolent dictator वाली स्थिति और development speed

    • इसलिए मैं लगभग हर काम के लिए Go इस्तेमाल करने की कोशिश करता हूँ। भले वह सबसे बेहतर विकल्प न हो, लेकिन झंझट सबसे कम है
    • C जटिल है? यह लगभग अकेली भाषा है जिसे इस्तेमाल की आवृत्ति चाहे जो हो, दिमाग़ में बनाए रखा जा सकता है। modern JavaScript syntax का कुछ हिस्सा तो मैं रोज़ इस्तेमाल करता हूँ, फिर भी याद से जल्दी उड़ जाता है
  • मैं एक polyglot developer हूँ, जिसे कई programming paradigms और languages के साथ-साथ frontend और backend दोनों में काम करना सहज लगता है
    जब भी package.json को 20 लाइनों से लंबा देखता हूँ, तो लगभग हर बार मेरी प्रतिक्रिया बिल्कुल ऐसी ही होती है

    • अभी जिस नए Angular frontend पर काम कर रहा हूँ, उसे घूर रहा हूँ; उसमें चार frontend components हैं और हर एक का package.json 200 लाइनों से भी लंबा है
      ज़ोर से ऐसे बोल रहा हूँ मानो किसी शैतान को दूर भगाने की कोशिश कर रहा हो। “डरना नहीं चाहिए। डर मन को मार देता है। डर वह छोटी मौत है जो पूर्ण विनाश लाती है। मैं अपने डर का सामना करूँगा। मैं उसे अपने ऊपर से गुज़र जाने दूँगा। और जब वह गुज़र जाएगा, तो मैं मन की आँख से उसका रास्ता देखूँगा। जहाँ डर गुज़र चुका होगा, वहाँ कुछ भी नहीं होगा। केवल मैं बचूँगा।”
      रो रहा हूँ
    • मैं भी ऐसा ही हूँ। बस विषय से हटकर कहूँ तो, प्रोफ़ाइल में दिया गया लिंक uBlock Origin द्वारा block हो जाता है और अजीब websites की rabbit hole में ले जाता है। मैंने कभी hackernewsers इस्तेमाल नहीं किया, इसलिए नहीं पता कि यह सामान्य व्यवहार है या नहीं
  • पुराने ज़माने का JavaScript developer इस लेख को पढ़ते हुए PTSD और flashbacks से जूझ रहा है
    डरना नहीं चाहिए। डर मन को मार देता है। डर वह छोटी मौत है जो पूर्ण विनाश लाती है
    मैं अपने डर का सामना करूँगा। मैं उसे अपने ऊपर से गुज़र जाने दूँगा। और जब वह गुज़र जाएगा, तो मैं मन की आँख से उसका रास्ता देखूँगा
    जहाँ डर गुज़र चुका होगा, वहाँ कुछ भी नहीं होगा। केवल मैं बचूँगा
    लेख पूरा पढ़कर एहसास होता है कि मैं बच गया, लेकिन तब तक मैं पसीने से लथपथ हो चुका हूँ