JavaScript Gom Jabbar
(frantic.im)- นักพัฒนา JavaScript ที่มีประสบการณ์ 10 ปีใช้ฉากการอ่าน
package.jsonเป็น บททดสอบแห่งความเจ็บปวด เพื่อแสดงให้เห็นว่าไฟล์ตั้งค่าเพียงไฟล์เดียวบรรจุความซับซ้อนสะสมของ ecosystem ไว้มากเพียงใด - ฟิลด์อย่าง
main,browser,type: moduleทำให้นึกถึงบาดแผลจาก migration เก่า ๆ ของ Isomorphic JavaScript, browser bundle และการเปลี่ยนผ่านระหว่าง CommonJS กับ ESM - ใน
scripts,dependencies,devDependenciesมีเครื่องมือเก่าและปัญหาการจัดการแพ็กเกจพันกันอยู่ เช่น lint หลายรูปแบบ,watchman, gulp,left-pad, moment.js,resolutions eslint,postcss,jestรวมถึงเครื่องมือ build/test ต่าง ๆ เพิ่ม ต้นทุนการดูแลรักษา development environment ผ่านกฎที่เข้มงวด, ข้อผิดพลาดการติดตั้งเฉพาะแพลตฟอร์ม และความยากในการตั้งค่า ESM/TypeScript- แม้จะเห็น Node
enginesก็ยังไม่ย้ายไป Bun หรือ Deno เพราะเชื่อว่าความเจ็บปวดจะไม่หายไป แต่จะยิ่งมากขึ้น นักพัฒนาจึงปิดไฟล์และเอาตัวรอดไปก่อน
บททดสอบการอ่าน package.json
- เรื่องเริ่มจากสถานการณ์ที่นักพัฒนาซึ่งใช้ JavaScript มา 10 ปีนั่งอยู่หน้าคอมพิวเตอร์ เปิดไฟล์
package.jsonและต้องอ่านจนจบ - ไฟล์นี้ไม่ใช่แค่ไฟล์ตั้งค่าธรรมดา แต่เป็นสิ่งที่ทำให้นึกถึง ความทรงจำและความเจ็บปวด ที่เคยเผชิญใน ecosystem ของ JavaScript ขึ้นมาพร้อมกัน
versionยังไม่ถึง1.0และ SemVer ยังคงเป็นความทรงจำอันไม่น่าพึงใจที่เรียนรู้มานานแล้วว่าควรละเลยอย่างไรnameแสดงให้เห็นสถานการณ์ที่ไม่สามารถใช้ชื่อที่ต้องการได้ เพราะมีแพ็กเกจที่ใครบางคนครอบครองไว้ตั้งแต่ 7 ปีก่อนและไม่เคยอัปเดตอีกเลย
บาดแผลเก่าของโมดูลและการ bundling
- การมีฟิลด์
mainและbrowserอยู่ร่วมกันเผยให้เห็นร่องรอยของ Isomorphic JavaScript - ความทรงจำเกี่ยวกับการพยายาม
requireโมดูลfsใน browser bundle และแฮ็กที่เคยใช้เพื่อทำให้มันทำงานได้ กลายเป็นประสบการณ์ที่ไม่น่าพึงใจ type: moduleเชื่อมโยงกับ migration จากrequireไปสู่import- ประสบการณ์การพยายาม import โมดูล CommonJS และ ESM เข้าหากันยังคงเป็นความเจ็บปวดครั้งใหญ่
ความสับสนของสคริปต์และ dependency
scriptsคือศูนย์กลางของความสับสนที่ร้อนระอุและเจ็บปวด- มีรูปแบบแยกย่อยอย่าง
lint,lintall,lintfast,lintdiff - มีการรันแบบขนาน, argument ที่ไม่ชัดเจน และการ escape ซ้ำสองครั้งสำหรับ argument รูปแบบ JSON
- แม้จะย้ายไปใช้ yarn และ pnpm แล้ว แต่คำสั่งย่อยบางส่วนก็ยังเรียก npm อยู่
- มีรูปแบบแยกย่อยอย่าง
- สคริปต์บางส่วนยังคงใช้
watchman- ต้องจำไว้ว่ามันไม่ควรถูกใช้ เพราะไม่รองรับ symlink
- issue ที่เกี่ยวข้องเปิดค้างมาตั้งแต่ปี 2015
- ยังมีสคริปต์ที่ใช้ gulp เหลืออยู่ และแม้อยากเปลี่ยนไปใช้สิ่งที่ทันสมัยกว่า แต่ก็ไม่มีใครกล้าพอที่จะเปลี่ยน
บาดแผลทางใจที่รายชื่อแพ็กเกจปลุกขึ้นมา
dependenciesมีแพ็กเกจจำนวนมาก และแต่ละแพ็กเกจก็ปลุก ความทรงจำที่เป็นบาดแผล ของตัวเองขึ้นมาleft-padเป็นแพ็กเกจเล็ก ๆ แต่ยังคงถูกจดจำในฐานะแพ็กเกจระดับตำนานที่ “ทำให้อินเทอร์เน็ตทั้งโลกพัง”- ทุกครั้งที่แก้รายชื่อ dependency บางแพ็กเกจจะพิมพ์คำขอบริจาคหรือคำเตือน breaking change ยาว ๆ ลงในคอนโซล
- นักพัฒนาอยู่ในสภาพที่ได้แต่หวังว่าแพ็กเกจอันตรายจะไม่ขโมยความลับหรือทำให้คอมพิวเตอร์พัง
- moment.js ถูกจดจำในฐานะไลบรารีที่มี API ดี แต่โลกอินเทอร์เน็ตตัดสินว่ามัน mutable เกินไป ใหญ่เกินไป และไม่รองรับ treeshaking ตอนนี้จึงอยู่ในสถานการณ์ที่ต้อง migration ไปยัง date-fns
- เวอร์ชันแพ็กเกจล้าหลังจากมาตรฐานปัจจุบันไปมากและจำเป็นต้องอัปเกรด แต่จากประสบการณ์การอัปเกรดในอดีต จึงคาดว่าจะเกิดความเจ็บปวดอย่างหนัก
resolutionsยังคงเป็นความเจ็บปวดอีกแบบหนึ่งที่เลือกใช้เพื่อหลีกเลี่ยงการอัปเกรดแพ็กเกจ
ความซับซ้อนอีกชั้นที่เครื่องมือพัฒนาสร้างขึ้น
- เมื่อดู
devDependenciesก็ยากที่จะนึกถึงยุคที่ต้องการเพียง non-dev dependency - การตั้งค่า
eslintเข้มงวดเกินไปจนความผิดพลาดเล็กน้อยก็มีขีดเส้นใต้สีแดง และ CI ปฏิบัติต่อปัญหา lint ราวกับเป็นวันสิ้นโลก- มันให้ความรู้สึกมั่นคงปลอม ๆ แก่วิศวกร junior ในทีม
- เคยมีการถกเถียงหลายครั้งว่าจะเปิดกฎใดบ้าง
- ความเจ็บปวดเพิ่มขึ้นตามจำนวน
eslint-ignoreที่กระจายอยู่ทั่ว codebase
postcssไม่ได้ถูกใช้โดยตรง แต่มีอยู่ในฐานะแพ็กเกจที่ dependency ของ dependency ต้องการ- ทุกครั้งที่พยายาม
npm installบนแพลตฟอร์มใหม่ มันทำให้เกิดข้อผิดพลาดการคอมไพล์ C++ ที่ไม่ชัดเจน
- ทุกครั้งที่พยายาม
jestเริ่มต้นในฐานะ test runner ที่รวดเร็ว แต่ตอนนี้ใหญ่และหนักขึ้น และพึ่งพาแพ็กเกจ Babel บางส่วน- ส่วนที่เหลือของแอปพลิเคชันถูก transpile ด้วยการผสมผสานระหว่าง esbuild และ swc
- การตั้งค่าให้ถูกต้องสำหรับ ESM และ TypeScript นั้นยากเหมือน “โปรเจกต์วิทยาศาสตร์ระดับ PhD”
- ใน codebase มีเครื่องมือและ parser จำนวนมากเข้ามาเกี่ยวข้อง เช่น TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup, terser
- ใน
enginesมีการระบุnodeไว้ และมองว่าแม้จะย้ายไป Bun หรือ Deno ความเจ็บปวดก็จะไม่หยุด แต่จะแย่ลงกว่าเดิม - หลังจากอ่านจนถึงวงเล็บปีกกาปิดตัวสุดท้าย ก็ปิดแท็บ สูดหายใจตั้งสติ และเอาตัวรอดมาได้ชั่วคราวโดยที่มือและสมองยังสมบูรณ์
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
ตลกดีนะ ผมเขียน JavaScript มาเกือบ 18 ปีแล้วและเลิกไปเมื่อราว 3 ปีก่อน แต่เรื่องน่าปวดหัวในลิสต์นี้ส่วนใหญ่เป็นสิ่งที่เกิดขึ้นในช่วง 10 ปีหลังนี่เอง
ที่สะดุดตาเป็นพิเศษคือไม่มี polyfill ซึ่งถ้าเขียนในปี 2013 ยังไงก็ต้องมีแน่ ๆ แล้วฝันร้ายของ JavaScript ในปี 2013 ที่ตอนนี้แทบหายไปแล้วมีอะไรอีกบ้างนะ? แน่นอนว่ามันถูกแทนที่ด้วยลิสต์ตลกอันนี้แทน
ช่วงที่ชอบที่สุดคือส่วนที่นับเครื่องมือและ parser ที่ใช้งานได้ในโค้ดเบส แล้วนึกถึง TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup, terser ก่อนจะเจ็บปวดจนไม่อยากรู้แล้วว่ามีอะไรตกหล่นไปอีกบ้าง
undefined,with, การเลียนแบบ private field ด้วย closure, prototype ที่ถูกแก้ไข, global ตัวแปรตั้งต้น,thisที่เปลี่ยนไปตามตำแหน่งที่เรียก, การแปลงชนิดอัตโนมัติตอนเปรียบเทียบ…ใช่เลย JavaScript ผ่านอะไรแบบนี้มาเกิน 10 ปีจริง ๆ
SomeFunction.prototypeทั้งหมดแล้วก็ห่อมันด้วย anonymous function ที่รันทันทีเพื่อคืนค่าเป็น object ทำให้เรียก
new SomeFunction()หรือSomeFunction.actualFunction()ราวกับว่าSomeFunctionเป็นคลาสจริง ๆ อีกเรื่องใหญ่คือยังไม่มี arrow function เลยต้องแก้Function.prototypeเองเพื่อผูก event เข้ากับ scope ด้วย.apply()หรือไม่ก็จมอยู่ในนรก.bind(this)ที่ไม่มีวันจบในทุก event callbackวันนี้ผมยังดันโชคร้ายต้องเขียนงานทดสอบให้บริษัทที่ยังใช้ JavaScript ล้วน ๆ ไม่มีทั้ง Promise หรือไฟล์ประกาศชนิดข้อมูลอยู่เลย รู้สึกเหมือนย้อนกลับไปตอนเจอ Node ครั้งแรกในปี 2012 ข้อกำหนดที่ว่าต้องใช้ JavaScript ผมพอเลี่ยงด้วย JSDoc ได้ แต่ประสบการณ์มันแย่กว่าที่จำได้มาก
ทุกครั้งที่เริ่มโปรเจกต์ JavaScript ใหม่ หรือพูดให้ตรงคือ โปรเจกต์ TypeScript ผมจะผ่านขั้นตอนเดิมเสมอ
ปกติมักเป็นงานฝั่งฟรอนต์เอนด์ก็เลยเลือก React แม้จะอยากลอง Svelte ด้วยก็ตาม ตัว bundler เมื่อก่อนเคยใช้ create-react-app หรือ wrapper ของ Webpack แต่ตอนนี้ Vite ดีที่สุดเพราะตั้งค่าน้อยและรองรับเฟรมเวิร์กหลักครบ
จากนั้นก็ติดตั้งและตั้งค่า TypeScript compiler ซึ่งส่วนใหญ่ก็อปปี้จากเทมเพลต ตั้งเป้าเป็น JavaScript เสถียรล่าสุดและโมดูล ESM แล้วจัด eslint กับ prettier ให้เข้ากัน พร้อมเพิ่มปลั๊กอินอย่าง TypeScript และ React ใส่ hook ให้รัน Prettier กับ eslint ก่อน commit ด้วย
ยังต้องติดตั้งส่วนขยาย IDE และทำ
.devcontainerหรือรายการส่วนขยายที่แนะนำไว้อีก ผมไม่ค่อยสนใจสไตล์เท่าไร แต่ให้ความสำคัญกับความสม่ำเสมอของโค้ดและการจับความผิดพลาด ดังนั้น eslint ก็มักใช้ชุดคอนฟิกสำเร็จรูปจากนั้นก็ตั้งค่า unit test อย่าง jest หรือ vitest แล้วค่าตั้งที่เกี่ยวกับ TypeScript กับกฎ eslint ก็พ่วงตามมาอีก ส่วน CSS framework ผมชอบ tailwind เลยยังติดตั้ง styled-components กับ twin.macro เพื่อให้เข้ากับ React ได้ดี รวมถึงปลั๊กอิน Google Fonts หรือไลบรารีฟอนต์ด้วย
ผ่านไปประมาณหนึ่งวันถึงจะเริ่มเขียนโปรแกรมได้ ทำไมมันต้องมีงานเยอะขนาดนี้นะ? ทั้งที่มีคนใช้ชุด Vite + TypeScript + React/Vue/Svelte + eslint/prettier + tailwind/bootstrap + jest/vitest กันเยอะมาก ทำไมถึงไม่มี ไลบรารีแบบไม่ต้องตั้งค่า ที่พร้อมใช้กับ 90% ของกรณีใช้งานกัน?
ต่อให้พอทำให้ toolchain รันขึ้นมาได้ ก็ไม่เคยรู้สึกว่าตัวเองควบคุมมันได้เลย เหมือนแค่สั่นนิดเดียวทุกอย่างก็จะพัง และก็ดูเหมือนจะซ่อมเองไม่ได้ด้วย
ช่วงหลังผมเลยมองสแตก JavaScript ส่วนใหญ่นี้ว่าเป็น อุปสรรค ต่อสิ่งที่ผมอยากทำ แล้วกลับไปสร้างแอปแบบ server-side rendering ด้วย Flask และ Jinja2 เหมือนสมัยก่อน มันไม่ได้ล้ำหรือดูแวววาว และตอนนี้ก็ยังค่อนข้างน่าเกลียดเพราะไม่มี CSS แต่ก็มีคนแนะนำให้ลองใช้ CSS สมัยใหม่ล้วน ๆ ดู ถึงอย่างนั้นก็ยังน่าทึ่งว่าทำฟีเจอร์ได้เร็วแค่ไหนบนสแตกนั้น
package.jsonเท่านั้นเอง แน่นอนว่าผมทำแต่แบ็กเอนด์ แต่สำหรับฟรอนต์เอนด์ก็น่าจะทำ เทมเพลตส่วนตัว แบบนั้นได้เหมือนกันไม่ใช่เหรอ?npm createไม่ช่วยทำให้เหรอ?ถ้าสั่ง
npm create vueก็จะได้ชุด Vue ที่ค่อนข้างดี ใช้งานได้จริง และตั้งค่าส่วนใหญ่ไว้ให้แล้ว ผมเห็นด้วยว่ามีทั้ง boilerplate และของจุกจิกเยอะ แต่แอปที่เราสร้างบนเว็บทุกวันนี้ก็ใหญ่กว่าเมื่อก่อนมากเหมือนกัน จะใช้ JavaScript ผ่าน ESModules แบบไม่พึ่งเครื่องมือเลยก็ได้ แต่คนไม่ค่อยทำกันเพราะเครื่องมือเหล่านั้นมันช่วยทำอะไรบางอย่างได้จริง อาจไม่ใช่วิธีที่สะอาดที่สุด แต่ยังไงมันก็ใช้ได้เวลาเริ่มโปรเจกต์ใหม่ก็แค่ clone มาแล้วเปลี่ยนชื่อไม่กี่จุดก็น่าจะพร้อมใช้งาน
นี่เป็นอีกกรณีที่คนพูดว่า JavaScript แต่จริง ๆ หมายถึง “สารพัดของจุกจิกใน ecosystem ของ Node”
เปิดมาก็บอกว่าต้องเปิดอ่านไฟล์
package.jsonแล้วหลังจากนั้นก็ยังวนอยู่กับเรื่องนั้นต่อไป แทบไม่มีอะไรที่เกี่ยวกับตัว JavaScript เองในสิ่งที่ยกมาพูดจริงอยู่ว่า JavaScript กับ NodeJS ไม่ใช่สิ่งเดียวกัน แต่คนส่วนใหญ่ก็คงเข้าใจว่าผู้เขียนหมายถึงอะไร ถ้าเขียนให้แม่นกว่านี้ก็คงดีกว่า แต่จะบอกว่าผิดไปเลยก็คงไม่ถึงขนาดนั้น
package.jsonดูสิ จนกว่า ECMA จะใส่ package manager หรือ bundler เข้าไปในสเปกอย่างเป็นทางการpackage.jsonก็ถือเป็น ส่วนหนึ่งของ JavaScript โดยพฤตินัยชอบโทนล้อเล่นแบบนี้ดี หลังจากผิวหนังกับปลายประสาทถูกเผาไหม้ไปหลายชั้นแล้ว การย้อนนึกถึงจุดเจ็บพวกนี้ก็มีประโยชน์อยู่
อีกมุมหนึ่งก็คือ คุณสามารถยื่น MacBook ใหม่ให้ junior developer ที่มีไฟ แล้วโยนลงน้ำลึกได้เลย เขาก็ยังทำงานได้ภายในวันเดียว ไม่ต้องรู้เรื่อง container, .NET, nginx หรือเครื่องมือ command line ที่ใช้บ่อยอีกเป็นร้อยตัว และถ้ามีปัญหาก็แค่ค้นหาเอา
ทั้งที่รู้ว่าถ้าได้จับต้องเองจริง ๆ ก็สร้างเรือทั้งลำได้ในไม่กี่วัน แต่กลับต้องมาซ่อมเรือในขวดด้วยเครื่องมือหยาบ ๆ ที่มีให้ พร้อมต่อสู้กับชั้นของความซับซ้อนที่ไม่จำเป็น ความรู้สึกนี้แหละเวลาทำโปรเจกต์ส่วนตัวด้วย JavaScript, HTML, CSS ล้วน ๆ ได้อย่างคล่อง แล้วถูกโยนเข้าไปทำงานฟรอนต์เอนด์สมัยใหม่
แล้วก็ไร้เดียงสาว่าการสร้างมันใช้เวลาหลายเดือน ทั้งที่ปัญหาส่วนหนึ่งก็คือ framework มีมากเกินไป และพอถึงวันถัดไปมันก็อาจล้าสมัยแล้ว
“ฉันทำตามคำอธิบายแล้วมันบอกว่าไม่ได้ติดตั้ง grunt ตอนนั้นฉันก็เป็นคนแก่แล้ว เลยไม่ค่อยรู้ว่า grunt คืออะไร แล้วไฟล์ grunt ของฉันก็ดูเหมือนจะมีอะไรไม่ถูกต้อง ก็เลยไปค้นมาหน่อยจนพอรู้ว่า grunt คืออะไร Grunt คือ… จริง ๆ แล้วฉันก็ยังไม่ค่อยรู้ว่ามันคืออะไรอยู่ดี”
--Joe Armstrong, https://www.youtube.com/watch?v=lKXe3HUG2l4
เมื่อไม่กี่วันก่อนฉันรัน
gem install wayback_machine_downloaderฉันไม่เคยชอบภาษา Ruby มากพอจะเข้าไปคลุกใน ecosystem ของมัน แต่จากคนนอกมองเข้าไป ecosystem นี้ดูคงเส้นคงวาอย่างน่าทึ่ง gem ก็ยังเป็นเครื่องมือที่ยังใช้อยู่ และ Rails ก็ยังอยู่เหมือนเดิมฉันกำลังรอโปรเจกต์ใหม่ที่ต้องใช้ฟรอนต์เอนด์ซับซ้อนพอจะเกิน JavaScript 0~30 บรรทัด ตอนนั้นแทนที่จะใช้ framework ยักษ์ที่กำลังฮิตที่สุดในยุคนี้ ฉันน่าจะมีความสุขกว่าถ้าใช้ HTMX
นี่ไม่ใช่บทความเกี่ยวกับ JavaScript แต่เป็นเรื่องของ npm
ฉันเกลียด npm เพราะสารพัดเรื่องจุกจิกแบบนี้ และพยายามหลีกเลี่ยงมันให้มากที่สุด ส่วนตัวฉันใช้ Deno และที่ทำงานก็ใช้ของคล้าย bazel บน monorepo ที่ช่วยให้ไม่ต้องพึ่ง npm
แต่ฉันรู้สึกว่า JavaScript/TypeScript เป็นภาษาที่เขียนโปรแกรมได้สนุก และเป็นภาษาที่หยิบมาใช้เป็นอันดับแรกไม่ว่าจะสร้างอะไร มันน่าเศร้าที่เวลาคนพูดว่า “JavaScript ห่วย” เขามักหมายถึงการ build แอป React ด้วย npm มันห่วยต่างหาก การเขียนโค้ด JavaScript/TypeScript สมัยใหม่นั้นสนุกจริง ๆ
รู้สึกว่า JavaScript กับ ecosystem ของมันได้ทิ้ง PTSD ไว้ให้พวกเราทุกคน จนทำให้สนุกกับความตลกของบทความนี้ไม่ได้
มีการถกกันแบบ “จริงจัง” มากเกินไปกับบทความขำ ๆ แบบนี้ จะชำแหละกันเต็มที่ก็ได้ แต่ก็น่าจะจำไว้ว่าความตั้งใจที่แท้จริงคืออารมณ์ขัน
พูดตรง ๆ ก็คือ ecosystem แรกที่ฉันเริ่มต้นคือ Node และสิ่งอื่นที่ไปเรียนรู้ทีหลังก็ล้วนมีปัญหาบ้าบอของตัวเองมากพอ ๆ กัน
Haskell ใช้งานข้ามหลายเครื่องได้ยากมาก การติดตั้งบน MacOS ในปี 2019 ก็ทรมาน และการจัดการ ecosystem ก็ลำบาก macro กับ extension ก็ชวนสับสนมาก และความเข้ากันได้ย้อนหลังของภาษาก็ไม่ได้ดีนัก ในทางกลับกัน JavaScript ปี 2010 โดยทั่วไปยังคาดหวังได้ว่าจะรันได้เหมือนเดิมในปี 2023
แม้แต่การทำ Docker image หรือ environment อย่าง codespace/gitpod ให้ดีจริง ๆ ก็ยังยาก และ image พื้นฐานที่ GitHub ให้มาก็ไม่ค่อยดีและมีปัญหา
C นั้นโดยมากก็พอใช้ได้บนแทบทุกแพลตฟอร์ม แต่ตัวภาษาเองก็ซับซ้อนเอาเรื่อง และต้องอาศัยความรู้มหาศาลเกี่ยวกับระบบโดยรวม ผลคือมันทำให้ได้โค้ดที่พกพาได้น้อยและไม่เหมาะกับงานเขียนโปรแกรมทั่วไปส่วนใหญ่ได้ง่าย
จะพูดต่อก็ยังได้ แต่ใครที่เคยใช้หลายภาษามาบ้างก็คงรู้ว่า ecosystem ทุกแห่งล้วนมีข้อบกพร่องหลายอย่าง และเราทุกคนก็ยังต้องทนทุกข์กันต่อไป ฉันไม่เคยเซ็ตอัปโปรเจกต์ PHP เสร็จภายในไม่กี่วันเลย ส่วน Elm แม้จะเจ็บปวดน้อยกว่า แต่ก็มีปัญหาเฉพาะตัวเรื่องสถานะแบบ benevolent dictator กับความเร็วในการพัฒนา
เป็นนักพัฒนาหลายภาษาที่คิดว่าตัวเองถนัดทั้งหลายกระบวนทัศน์การเขียนโปรแกรม หลายภาษา รวมถึงทั้งฝั่งฟรอนต์เอนด์และแบ็กเอนด์
ทุกครั้งที่เห็น
package.jsonยาวเกิน 20 บรรทัด ก็แทบจะตอบสนองแบบนี้อย่างแม่นยำpackage.jsonยาวเกิน 200 บรรทัดพูดออกเสียงราวกับพยายามขับไล่ปีศาจว่า “อย่าหวาดกลัว ความกลัวคือสิ่งที่สังหารจิตใจ ความกลัวคือความตายเล็ก ๆ ที่นำมาซึ่งการสูญสิ้นโดยสมบูรณ์ ข้าจะเผชิญหน้ากับความกลัวของตนเอง ข้าจะยอมให้มันผ่านเข้ามาและผ่านพ้นไป และเมื่อมันผ่านไปแล้ว ข้าจะใช้ดวงตาแห่งจิตมองดูเส้นทางของมัน ตรงที่ความกลัวผ่านไปจะไม่เหลือสิ่งใด มีเพียงข้าเท่านั้นที่ยังคงอยู่”
กำลังร้องไห้อยู่
ฉากที่นักพัฒนา JavaScript สายเก่าอ่านบทความนี้พร้อมทุกข์ทรมานจาก PTSD และภาพย้อนอดีต
อย่าหวาดกลัว ความกลัวคือสิ่งที่สังหารจิตใจ ความกลัวคือความตายเล็ก ๆ ที่นำมาซึ่งการสูญสิ้นโดยสมบูรณ์
ข้าจะเผชิญหน้ากับความกลัวของตนเอง ข้าจะยอมให้มันผ่านเข้ามาและผ่านพ้นไป และเมื่อมันผ่านไปแล้ว ข้าจะใช้ดวงตาแห่งจิตมองดูเส้นทางของมัน
ตรงที่ความกลัวผ่านไปจะไม่เหลือสิ่งใด มีเพียงข้าเท่านั้นที่ยังคงอยู่
อ่านบทความจนจบและตระหนักว่าตัวเองรอดมาได้ แต่ก็ชุ่มไปด้วยเหงื่อเสียแล้ว