A place to cache linked articles (think custom and personal wayback machine)
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="en">
  4. <!-- Has to be within the first 1024 bytes, hence before the `title` element
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Disillusioned with Deno (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f7f7f7">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
  26. <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
  27. <!-- Is that even respected? Retrospectively? What a shAItshow…
  28. https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
  29. <meta name="robots" content="noai, noimageai">
  30. <!-- Documented, feel free to shoot an email. -->
  31. <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
  32. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  35. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  36. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  37. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  38. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  39. <script>
  40. function toggleTheme(themeName) {
  41. document.documentElement.classList.toggle(
  42. 'forced-dark',
  43. themeName === 'dark'
  44. )
  45. document.documentElement.classList.toggle(
  46. 'forced-light',
  47. themeName === 'light'
  48. )
  49. }
  50. const selectedTheme = localStorage.getItem('theme')
  51. if (selectedTheme !== 'undefined') {
  52. toggleTheme(selectedTheme)
  53. }
  54. </script>
  55. <meta name="robots" content="noindex, nofollow">
  56. <meta content="origin-when-cross-origin" name="referrer">
  57. <!-- Canonical URL for SEO purposes -->
  58. <link rel="canonical" href="https://www.baldurbjarnason.com/2024/disillusioned-with-deno/">
  59. <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
  60. <article>
  61. <header>
  62. <h1>Disillusioned with Deno</h1>
  63. </header>
  64. <nav>
  65. <p class="center">
  66. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  67. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  68. </svg> Accueil</a> •
  69. <a href="https://www.baldurbjarnason.com/2024/disillusioned-with-deno/" title="Lien vers le contenu original">Source originale</a>
  70. <br>
  71. Mis en cache le 2024-01-16
  72. </p>
  73. </nav>
  74. <hr>
  75. <p>It’s inevitable that once you decide to review your own business and media strategy, you start to rethink and review other decisions you’ve made in the past.</p>
  76. <p>One of those decisions is <a href="https://deno.com/">Deno</a>, which I’ve used to most of my personal projects and experiments over the past couple of years. Most of these projects have been on the simpler side – command-line scripts or small websites. I made the <a href="https://softwarecrisis.dev/">softwarecrisis.dev</a> newsletter landing page using <a href="https://lume.land/">Lume and Deno</a>, for example. I used Deno to make most of the prototypes for the research project that followed <a href="https://www.colophon.cards/">Colophon Cards</a>. It’s very useful.</p>
  77. <p>There’s a lot to like.</p>
  78. <p>Deno has:</p>
  79. <ul>
  80. <li>Overall much better support for standard browser APIs than node.</li>
  81. <li>APIs that aren’t based on standards hew a lot closer to browser conventions, making switching between the front and back end a lot less jarring.</li>
  82. <li>An excellent standard library.</li>
  83. <li>Much simpler installation. It comes in a single binary, making installation and deployment much simpler.</li>
  84. <li>Most of the tooling you need: linter, test runner, benchmarking, code formatting, type checker, and documentation generation.</li>
  85. <li>A sensible security model for running code.</li>
  86. </ul>
  87. <p>If you have a task that only requires the standard library or the standard tooling, using Deno is a dream – simplicity itself.</p>
  88. <p>If that task requires something <em>more</em> than that, you quickly find yourself in trouble.</p>
  89. <p>The company behind Deno has tried to conquer this problem with a two-pronged attack:</p>
  90. <ol>
  91. <li>Build Deno-specific versions of most of the common tools and projects that web projects might need.</li>
  92. <li>Hastily roll out node and npm compatibility for their runtime.</li>
  93. </ol>
  94. <p>This has meant that a single startup has taken on the responsibility of building their own <a href="https://deno.com/deploy">scalable hosting</a>, <a href="https://deno.com/kv">persistent storage product</a>, <a href="https://docs.deno.com/kv/manual/queue_overview">persistent execution queue</a>, <a href="https://docs.deno.com/kv/manual/#watching-for-updates-in-deno-kv">realtime notification</a>, <a href="https://docs.deno.com/kv/manual/cron">scheduled execution</a>, <a href="https://fresh.deno.dev/">front-end React framework</a>, and no doubt a few more by the time you read this post.</p>
  95. <p>They’re even planning to build their own full-featured package registry for <a href="https://www.reddit.com/r/Deno/comments/15nv8yv/deno_20_previewed_at_seattlejs_conf/">Deno 2.0.</a> (Also, it’s quite annoying how much information out there on the future of Deno is only available in video.)</p>
  96. <p>Add to that the attempt to implement full node and npm compatibility for their runtime.</p>
  97. <p>Basically:</p>
  98. <ol>
  99. <li>Your business model is hosting.</li>
  100. <li>But none of the tools and projects people commonly use are available for your new runtime and hosting environment, so you need to implement your own to fill in the gaps.</li>
  101. <li>Then you discover that the biggest demand for hosting is from clients with legacy code and legacy dependencies, so you kind of have to give them a way to bring them over. Compatibility it is.</li>
  102. <li>Turns out many of the annoying features of the “legacy” system existed for a reason, so you have to implement them yourself, but you obviously do so in newer, modern, more sensible (and less backwards-compatible) ways.</li>
  103. <li>This would be fine – great even – if it weren’t for the fact that you now have to maintain <strong><em>two</em></strong> versions of large parts of your runtime, either as a translation layer from the “legacy” system to your new one, or as two completely independent features that require maintenance.</li>
  104. </ol>
  105. <p>We’ve seen this strategy before. It’s basically <a href="https://www.cloudflare.com/">Cloudflare’s</a>, give or take a few details. Most of the differences in execution are because Cloudflare started on the opposite end of this particular chain of sausages: cloud hosting first, then <a href="https://blog.cloudflare.com/workers-open-source-announcement/">the open source runtime</a>, not the other way around as Deno did.</p>
  106. <p>I find Deno’s tooling to be better, and their runtime much, much easier to use, but the overall strategy for the two companies is the same.</p>
  107. <p><a href="https://bun.sh/">Bun</a> has the same playbook, with their only innovation being that, since they began later, they understood the need for node and npm compatibility from the very beginning.</p>
  108. <p>I don’t think this approach is going to work out that well for any of them.</p>
  109. <p>The “legacy” compatibility effectively removes any incentive to make packages for Deno (or Cloudflare, or Bun). Why use <a href="https://github.com/denoland/dnt"><code>dnt</code></a> to create packages that are compatible with both Deno and Node when you can just make a Node package? <strong><em>It’s still going to be compatible with both Deno and Node.</em></strong> Deno themselves have seen to that. You’re going to get cross-runtime compatibility either way.</p>
  110. <p>The risk is that Deno will effectively become a platform for running code and projects from the npm ecosystem. Except it will never be as good at “node” as node itself.</p>
  111. <p>There are always going to be gaps in the node and npm compatibility layer because <em>node is a moving target</em>. It’s a living project that’s still changing.</p>
  112. <hr>
  113. <p>If Deno were maintained by a foundation or open source community, I’d be less worried. It’d inevitably be smaller in scope, but that would be fine. You don’t need world domination to be a successful community-driven software project. It could find its niche, with time.</p>
  114. <p>But you do need to conquer a big chunk of the world to be a successful VC-funded startup.</p>
  115. <p>There is already a disconnect in the Deno ecosystem. Many of the third party modules seem to be stagnant and haven’t been updated in a while. The projects that do seem vibrant tend to be the ones that target browser-compatible platforms in general and so get Deno, Cloudflare, and Bun support almost for free through little specific effort of their own.</p>
  116. <p>Node hasn’t been standing still either. They’re adding support for many of the features that made Deno special, such as built-in tooling, a <a href="https://nodejs.org/docs/latest/api/test.html">test runner with coverage</a>, and <a href="https://nodejs.org/docs/latest/api/esm.html#https-and-http-imports">HTTP imports</a>. Even <a href="https://github.com/nodejs/loaders#milestone-3-usability-improvements">import maps</a> are on their roadmap.</p>
  117. <p>The fate of Node also doesn’t depend on the fate of a single startup or tech company.</p>
  118. <p>The npm ecosystem remains a strategic liability, but adding support for import maps and HTTP imports will go some way to mitigate that and in the meantime you can install node packages <a href="https://medium.com/pravin-lolage/how-to-use-your-own-package-from-git-repository-as-a-node-module-8b543c13957e">directly from git</a> or use an npm-compatible third party repository. <a href="https://docs.npmjs.com/cli/v10/commands/npm-install#:~:text=npm%20install%20%3Cgit%20remote%20url%3E">Any git remote URL should work with <code>npm install</code></a> – no GitHub required.</p>
  119. <p>Seeing money and talent drain out of the software ecosystem, companies switch en masse to inherently conservative LLMs for development, and a growing frustration among software developers in general, it’s hard to envision a future where Deno or Bun win out in a direct competition with Node.</p>
  120. <p>I’m not convinced I want to be using either of them once their VC-backed startups become desperate.</p>
  121. <p>For those of us who <em>do</em> like to work in JavaScript, this means that Node is our best bet for the back end in the long term.</p>
  122. <p>It’s probably time to try to recreate in node what has made Deno such a joy to work with.</p>
  123. <p>But Node’s improvements aren’t the only issue facing Deno.</p>
  124. <p>The big one is that the logical alternatives to Node – the “no Node” work environments developers are likely to reach for <em>aren’t going to be based on JavaScript</em>. Import maps mean that browsers effectively have an API surface that non-JS projects can use to build a dependency management system. Much of the tooling surrounding JavaScript is now implemented in <em>Rust</em>, not JS – much of it driven by Deno itself – and that makes it more easily accessible outside both the Node and Deno ecosystems. <a href="https://component-model.bytecodealliance.org/">The WASM component model</a> additionally promises to make many dependencies runtime-independent, with the Rust-based tooling around JS being logical initial targets.</p>
  125. <p>The “no Node” alternative for many won’t be another JavaScript runtime, but instead <em>something completely different.</em></p>
  126. </article>
  127. <hr>
  128. <footer>
  129. <p>
  130. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  131. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  132. </svg> Accueil</a> •
  133. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  134. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
  135. </svg> Suivre</a> •
  136. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  137. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
  138. </svg> Pro</a> •
  139. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  140. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
  141. </svg> Email</a> •
  142. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  143. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
  144. </svg> Légal</abbr>
  145. </p>
  146. <template id="theme-selector">
  147. <form>
  148. <fieldset>
  149. <legend><svg class="icon icon-brightness-contrast">
  150. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
  151. </svg> Thème</legend>
  152. <label>
  153. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  154. </label>
  155. <label>
  156. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  157. </label>
  158. <label>
  159. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  160. </label>
  161. </fieldset>
  162. </form>
  163. </template>
  164. </footer>
  165. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  166. <script>
  167. function loadThemeForm(templateName) {
  168. const themeSelectorTemplate = document.querySelector(templateName)
  169. const form = themeSelectorTemplate.content.firstElementChild
  170. themeSelectorTemplate.replaceWith(form)
  171. form.addEventListener('change', (e) => {
  172. const chosenColorScheme = e.target.value
  173. localStorage.setItem('theme', chosenColorScheme)
  174. toggleTheme(chosenColorScheme)
  175. })
  176. const selectedTheme = localStorage.getItem('theme')
  177. if (selectedTheme && selectedTheme !== 'undefined') {
  178. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  179. }
  180. }
  181. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  182. window.addEventListener('load', () => {
  183. let hasDarkRules = false
  184. for (const styleSheet of Array.from(document.styleSheets)) {
  185. let mediaRules = []
  186. for (const cssRule of styleSheet.cssRules) {
  187. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  188. continue
  189. }
  190. // WARNING: Safari does not have/supports `conditionText`.
  191. if (cssRule.conditionText) {
  192. if (cssRule.conditionText !== prefersColorSchemeDark) {
  193. continue
  194. }
  195. } else {
  196. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  197. continue
  198. }
  199. }
  200. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  201. }
  202. // WARNING: do not try to insert a Rule to a styleSheet you are
  203. // currently iterating on, otherwise the browser will be stuck
  204. // in a infinite loop…
  205. for (const mediaRule of mediaRules) {
  206. styleSheet.insertRule(mediaRule.cssText)
  207. hasDarkRules = true
  208. }
  209. }
  210. if (hasDarkRules) {
  211. loadThemeForm('#theme-selector')
  212. }
  213. })
  214. </script>
  215. </body>
  216. </html>