A place to cache linked articles (think custom and personal wayback machine)
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

index.html 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang=fr>
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  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,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>A JS framework on every table (archive) — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <meta name="robots" content="noindex, nofollow">
  28. <meta content="origin-when-cross-origin" name="referrer">
  29. <!-- Canonical URL for SEO purposes -->
  30. <link rel="canonical" href="http://www.allenpike.com/2015/javascript-framework-fatigue/">
  31. <style>
  32. /* http://meyerweb.com/eric/tools/css/reset/ */
  33. html, body, div, span,
  34. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  35. a, abbr, address, big, cite, code,
  36. del, dfn, em, img, ins,
  37. small, strike, strong, tt, var,
  38. dl, dt, dd, ol, ul, li,
  39. fieldset, form, label, legend,
  40. table, caption, tbody, tfoot, thead, tr, th, td,
  41. article, aside, canvas, details, embed,
  42. figure, figcaption, footer, header, hgroup,
  43. menu, nav, output, ruby, section, summary,
  44. time, mark, audio, video {
  45. margin: 0;
  46. padding: 0;
  47. border: 0;
  48. font-size: 100%;
  49. font: inherit;
  50. vertical-align: baseline;
  51. }
  52. /* HTML5 display-role reset for older browsers */
  53. article, aside, details, figcaption, figure,
  54. footer, header, hgroup, menu, nav, section { display: block; }
  55. body { line-height: 1; }
  56. blockquote, q { quotes: none; }
  57. blockquote:before, blockquote:after,
  58. q:before, q:after {
  59. content: '';
  60. content: none;
  61. }
  62. table {
  63. border-collapse: collapse;
  64. border-spacing: 0;
  65. }
  66. /* http://practicaltypography.com/equity.html */
  67. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  68. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  69. @font-face {
  70. font-family: 'EquityTextB';
  71. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  72. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  73. font-weight: 300;
  74. font-style: normal;
  75. font-display: swap;
  76. }
  77. @font-face {
  78. font-family: 'EquityTextB';
  79. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  80. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  81. font-weight: 300;
  82. font-style: italic;
  83. font-display: swap;
  84. }
  85. @font-face {
  86. font-family: 'EquityTextB';
  87. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  88. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  89. font-weight: 700;
  90. font-style: normal;
  91. font-display: swap;
  92. }
  93. @font-face {
  94. font-family: 'ConcourseT3';
  95. src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
  96. url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
  97. font-weight: 300;
  98. font-style: normal;
  99. font-display: swap;
  100. }
  101. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  102. body {
  103. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  104. font-family: "EquityTextB", Palatino, serif;
  105. background-color: #f0f0ea;
  106. color: #07486c;
  107. font-kerning: normal;
  108. -moz-osx-font-smoothing: grayscale;
  109. -webkit-font-smoothing: subpixel-antialiased;
  110. text-rendering: optimizeLegibility;
  111. font-variant-ligatures: common-ligatures contextual;
  112. font-feature-settings: "kern", "liga", "clig", "calt";
  113. }
  114. pre, code, kbd, samp, var, tt {
  115. font-family: 'TriplicateT4c', monospace;
  116. }
  117. em {
  118. font-style: italic;
  119. color: #323a45;
  120. }
  121. strong {
  122. font-weight: bold;
  123. color: black;
  124. }
  125. nav {
  126. background-color: #323a45;
  127. color: #f0f0ea;
  128. display: flex;
  129. justify-content: space-around;
  130. padding: 1rem .5rem;
  131. }
  132. nav:last-child {
  133. border-bottom: 1vh solid #2d7474;
  134. }
  135. nav a {
  136. color: #f0f0ea;
  137. }
  138. nav abbr {
  139. border-bottom: 1px dotted white;
  140. }
  141. h1 {
  142. border-top: 1vh solid #2d7474;
  143. border-bottom: .2vh dotted #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 5rem 0 4rem 0;
  148. width: 100%;
  149. font-family: 'ConcourseT3';
  150. display: flex;
  151. flex-direction: column;
  152. }
  153. h1.single {
  154. padding-bottom: 10rem;
  155. }
  156. h1 span {
  157. position: absolute;
  158. top: 1vh;
  159. left: 20%;
  160. line-height: 0;
  161. }
  162. h1 span a {
  163. line-height: 1.7;
  164. padding: 1rem 1.2rem .6rem 1.2rem;
  165. border-radius: 0 0 6% 6%;
  166. background: #2d7474;
  167. font-size: 1.3rem;
  168. color: white;
  169. text-decoration: none;
  170. }
  171. h2 {
  172. margin: 4rem 0 1rem;
  173. border-top: .2vh solid #2d7474;
  174. padding-top: 1vh;
  175. }
  176. h3 {
  177. text-align: center;
  178. margin: 3rem 0 .75em;
  179. }
  180. hr {
  181. height: .4rem;
  182. width: .4rem;
  183. border-radius: .4rem;
  184. background: #07486c;
  185. margin: 2.5rem auto;
  186. }
  187. time {
  188. display: bloc;
  189. margin-left: 0 !important;
  190. }
  191. ul, ol {
  192. margin: 2rem;
  193. }
  194. ul {
  195. list-style-type: square;
  196. }
  197. a {
  198. text-decoration-skip-ink: auto;
  199. text-decoration-thickness: 0.05em;
  200. text-underline-offset: 0.09em;
  201. }
  202. article {
  203. max-width: 50rem;
  204. display: flex;
  205. flex-direction: column;
  206. margin: 2rem auto;
  207. }
  208. article.single {
  209. border-top: .2vh dotted #2d7474;
  210. margin: -6rem auto 1rem auto;
  211. background: #f0f0ea;
  212. padding: 2rem;
  213. }
  214. article p:last-child {
  215. margin-bottom: 1rem;
  216. }
  217. p {
  218. padding: 0 .5rem;
  219. margin-left: 3rem;
  220. }
  221. p + p,
  222. figure + p {
  223. margin-top: 2rem;
  224. }
  225. blockquote {
  226. background-color: #e3e1e1;
  227. border-left: .5vw solid #2d7474;
  228. display: flex;
  229. flex-direction: column;
  230. align-items: center;
  231. padding: 1rem;
  232. margin: 1.5rem;
  233. }
  234. blockquote cite {
  235. font-style: italic;
  236. }
  237. blockquote p {
  238. margin-left: 0;
  239. }
  240. figure {
  241. border-top: .2vh solid #2d7474;
  242. background-color: #e3e1e1;
  243. text-align: center;
  244. padding: 1.5rem 0;
  245. margin: 1rem 0 0;
  246. font-size: 1.5rem;
  247. width: 100%;
  248. }
  249. figure img {
  250. max-width: 250px;
  251. max-height: 250px;
  252. border: .5vw solid #323a45;
  253. padding: 1px;
  254. }
  255. figcaption {
  256. padding: 1rem;
  257. line-height: 1.4;
  258. }
  259. aside {
  260. display: flex;
  261. flex-direction: column;
  262. background-color: #e3e1e1;
  263. padding: 1rem 0;
  264. border-bottom: .2vh solid #07486c;
  265. }
  266. aside p {
  267. max-width: 50rem;
  268. margin: 0 auto;
  269. }
  270. /* https://fvsch.com/code/css-locks/ */
  271. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  272. font-size: 1rem;
  273. line-height: calc( 1.5em + 0.2 * 1rem );
  274. }
  275. h1 {
  276. font-size: 1.9rem;
  277. line-height: calc( 1.2em + 0.2 * 1rem );
  278. }
  279. h2 {
  280. font-size: 1.6rem;
  281. line-height: calc( 1.3em + 0.2 * 1rem );
  282. }
  283. h3 {
  284. font-size: 1.35rem;
  285. line-height: calc( 1.4em + 0.2 * 1rem );
  286. }
  287. @media (min-width: 20em) {
  288. /* The (100vw - 20rem) / (50 - 20) part
  289. resolves to 0-1rem, depending on the
  290. viewport width (between 20em and 50em). */
  291. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  292. font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
  293. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  294. margin-left: 0;
  295. }
  296. h1 {
  297. font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  298. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  299. }
  300. h2 {
  301. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  302. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  303. }
  304. h3 {
  305. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  306. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  307. }
  308. }
  309. @media (min-width: 50em) {
  310. /* The right part of the addition *must* be a
  311. rem value. In this example we *could* change
  312. the whole declaration to font-size:2.5rem,
  313. but if our baseline value was not expressed
  314. in rem we would have to use calc. */
  315. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  316. font-size: calc( 1rem + .6 * 1rem );
  317. line-height: 1.5em;
  318. }
  319. p, li, pre, details {
  320. margin-left: 3rem;
  321. }
  322. h1 {
  323. font-size: calc( 1.9rem + 1.5 * 1rem );
  324. line-height: 1.2em;
  325. }
  326. h2 {
  327. font-size: calc( 1.5rem + 1.5 * 1rem );
  328. line-height: 1.3em;
  329. }
  330. h3 {
  331. font-size: calc( 1.35rem + 1.5 * 1rem );
  332. line-height: 1.4em;
  333. }
  334. figure img {
  335. max-width: 500px;
  336. max-height: 500px;
  337. }
  338. }
  339. figure.unsquared {
  340. margin-bottom: 1.5rem;
  341. }
  342. figure.unsquared img {
  343. height: inherit;
  344. }
  345. @media print {
  346. body { font-size: 100%; }
  347. a:after { content: " (" attr(href) ")"; }
  348. a, a:link, a:visited, a:after {
  349. text-decoration: underline;
  350. text-shadow: none !important;
  351. background-image: none !important;
  352. background: white;
  353. color: black;
  354. }
  355. abbr[title] { border-bottom: 0; }
  356. abbr[title]:after { content: " (" attr(title) ")"; }
  357. img { page-break-inside: avoid; }
  358. @page { margin: 2cm .5cm; }
  359. h1, h2, h3 { page-break-after: avoid; }
  360. p3 { orphans: 3; widows: 3; }
  361. img {
  362. max-width: 250px !important;
  363. max-height: 250px !important;
  364. }
  365. nav, aside { display: none; }
  366. }
  367. ul.with_columns {
  368. column-count: 1;
  369. }
  370. @media (min-width: 20em) {
  371. ul.with_columns {
  372. column-count: 2;
  373. }
  374. }
  375. @media (min-width: 50em) {
  376. ul.with_columns {
  377. column-count: 3;
  378. }
  379. }
  380. ul.with_two_columns {
  381. column-count: 1;
  382. }
  383. @media (min-width: 20em) {
  384. ul.with_two_columns {
  385. column-count: 1;
  386. }
  387. }
  388. @media (min-width: 50em) {
  389. ul.with_two_columns {
  390. column-count: 2;
  391. }
  392. }
  393. .gallery {
  394. display: flex;
  395. flex-wrap: wrap;
  396. justify-content: space-around;
  397. }
  398. .gallery figure img {
  399. margin-left: 1rem;
  400. margin-right: 1rem;
  401. }
  402. .gallery figure figcaption {
  403. font-family: 'ConcourseT3'
  404. }
  405. footer {
  406. font-family: 'ConcourseT3';
  407. display: flex;
  408. flex-direction: column;
  409. border-top: 3px solid white;
  410. padding: 4rem 0;
  411. background-color: #07486c;
  412. color: white;
  413. }
  414. footer > * {
  415. max-width: 50rem;
  416. margin: 0 auto;
  417. }
  418. footer a {
  419. color: #f1c40f;
  420. }
  421. footer .avatar {
  422. width: 200px;
  423. height: 200px;
  424. border-radius: 50%;
  425. float: left;
  426. -webkit-shape-outside: circle();
  427. shape-outside: circle();
  428. margin-right: 2rem;
  429. padding: 2px 5px 5px 2px;
  430. background: white;
  431. border-left: 1px solid #f1c40f;
  432. border-top: 1px solid #f1c40f;
  433. border-right: 5px solid #f1c40f;
  434. border-bottom: 5px solid #f1c40f;
  435. }
  436. </style>
  437. <h1>
  438. <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
  439. A JS framework on every table (archive)
  440. <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
  441. </h1>
  442. <section>
  443. <article>
  444. <h3><a href="http://www.allenpike.com/2015/javascript-framework-fatigue/">Source originale du contenu</a></h3>
  445. <p>Most programming languages support a small number of popular, stable application frameworks. Objective-C and Swift apps use Apple’s excellent Cocoa framework. Ruby apps more often than not use Rails. Java has a handful of established web app frameworks, and they come and go relatively slowly.</p>
  446. <p>In the meantime, the latest and greatest JavaScript framework comes around every sixteen minutes.</p>
  447. <p>Studies show that a todo list is the most complex JavaScript app you can build before a newer, better framework is invented. Luckily, there’s an excellent site called <a href="http://todomvc.com/">TodoMVC</a> dedicated to comparing JavaScript frameworks by way of todo sample projects. There, you can see how 63 JavaScript app frameworks’ todo examples compare to just jQuery or vanilla JavaScript. If you think 63 frameworks are a lot, you ain’t seen nothing yet: the TodoMVC team <a href="http://blog.tastejs.com/yet-another-framework-syndrome-yafs">gets multiple pull requests weekly</a> from people flogging new JavaScript frameworks. </p>
  448. <p>For example, <a href="https://github.com/tastejs/todomvc/pull/1178">the most recent TodoMVC pull request</a>, as of this writing, wants to add Riot.js 2.0. What is Riot.js 2.0, you ask? Apparently, it’s the second version of something called Riot.js, an app framework that’s like React.js, but better in some ways that are definitely important. “But wait,” you may ask, “didn’t React like just come out and isn’t even 1.0 yet? How can a thing based on it be 2.0 already?!” The answer, my friend, is JavaScript.</p>
  449. <p><img src="http://www.allenpike.com/images/2015/javascript-guy.jpg" /></p>
  450. <p>Why is the JavaScript framework environment so unstable? What is driving this insanity? Why are Ruby developers using Rails 4.2 but client-side developers are hyping boron.js 0.2.1?</p>
  451. <p>The problem is, as always, the browser. The modern web browser is an incredible feat of engineering, especially considering its humble roots as a way to display simple documents. There is definitely a substantial amount of framework turnover in the node/io.js community, but it’s nothing compared to the zoo that is the browser app framework world. The wild instability of the client-side JavaScript landscape is a product of the browser: both its historical limitations and its incredible rate of improvement.</p>
  452. <p>The browser is most ubiquitous app runtime in history by a wide margin, and to write applications for it you need to write JavaScript. As a consequence, JavaScript is the least elective programming language in the world – most people who are writing client-side JavaScript applications are not doing so because they chose JavaScript, but because they chose client-side web development. These people come from a wide variety of backgrounds, and have a wide variety of goals. This constant inflow of new ideas and interests has made the JavaScript community unusually diverse.</p>
  453. <p>Meanwhile, the browser itself changes far more rapidly and unpredictably than the underlying languages on which other frameworks are built. The browser has changed more since Backbone.js debuted in 2010 than Objective-C has changed since Cocoa debuted all the way back in 1988. Browser improvements that inspire new generations of frameworks happen constantly.</p>
  454. <p>These inputs fuel an incredible amount of experimentation, excitement, and adaptation. Every day new frameworks, new approaches, and new tools <a href="https://github.com/trending?l=javascript">erupt from the geyser we call Github</a>. Every year there are more instant-classic JSConf talks about <a href="https://www.youtube.com/watch?v=ztspvPYybIY">crazy new ideas</a>, <a href="https://www.youtube.com/watch?v=GNO_CYUjMK8">impressive new browser features</a>, and <a href="https://www.youtube.com/watch?v=x7cQ3mrcKaY">rethinking best practices</a>. This beautiful chaos is exciting in a way that I’ve never seen in another developer community.</p>
  455. <p><a href="https://www.flickr.com/photos/aperezdc/9756603043/" title="Photo: Adrián Pérez"><img src="http://www.allenpike.com/images/2015/jsconf-eu-banner.jpg" alt="Photo: Adrián Pérez" /></a></p>
  456. <p>Unfortunately, while the community is busy driving new features and new frameworks, the browser is is busy killing them.</p>
  457. <p>Unlike the frameworks we use in C++ or Swift, the entirety of your app framework must be downloaded, parsed, and turned into machine code before users even see your app. Caching and offline access continue to improve, but the very real constraints on bandwidth, latency, memory, and loading time are a huge challenge for the kind of huge app frameworks that we take for granted in native app development.</p>
  458. <p>This is especially true on mobile, where the already problematic constraints of memory, CPU, and network bandwidth can be crippling. While JavaScript is now a remarkably fast language, the ubiquity of the web means that your code and framework can be downloaded and run in some incredibly hostile environments. Frameworks that can take advantage of Chrome Canary’s supernatural powers on a Mac Pro aren’t going to enjoy themselves on “Browser” on an old Acer EvoAMAZE Plus 3G E.</p>
  459. <p>The churning seas on which client-side frameworks sail are especially treacherous for large, ambitious frameworks that try to create a rich environment and UI library for building apps the way we do natively.</p>
  460. <p>When SproutCore and Cappuccino appeared in 2007, I was totally sold by <a href="https://vimeo.com/6930037">the amazing demos</a>. I’d thought Moore’s law had finally delivered stable, featureful JavaScript frameworks for building beautiful desktop-like apps in the browser. Then I spent two years <a href="http://ajaxian.com/archives/technical-details-behind-iworkcom">shipping stuff</a> with SproutCore, dealing with megabytes’ worth of somebody else’s JavaScript, wrestling with weird technical choices necessitated by horrible DOM performance on IE7, and somehow cramming the whole thing into the iPad’s 256MB of RAM. Meanwhile, the documentation never caught up to the pace of breaking changes, and performance was a constant battle. Before long, the dream felt more like an evolutionary dead end.</p>
  461. <p><a href="http://en.wikipedia.org/wiki/Sharovipteryx" title="&quot;Sharovipteryx BW&quot; by Nobu Tamura (http://spinops.blogspot.com). Yes, this was a thing."><img src="http://www.allenpike.com/images/2015/flying-dino.jpg" alt="&quot;Sharovipteryx BW&quot; by Nobu Tamura (http://spinops.blogspot.com). Yes, this was a thing." /></a></p>
  462. <p>While in many ways I still dream of a framework that could deliver on the promises that SproutCore and Cappuccino made, I now have much more respect for how hard such a thing is to build, especially in JavaScript. The same flexible, untyped nature that makes JavaScript fun to write a microframework in makes it kind of unpleasant to learn or maintain a large framework in. While the strong typing of native app frameworks can feel like a drag on tiny projects, it makes their often-massive APIs easy to explore and use effectively: just tab-complete your way to victory.</p>
  463. <p>A deprecated API in the Cocoa framework just means that a warning comes up when I open my project, and sometimes I can even right-click to replace the old way of doing things with the new way. Meanwhile in JavaScript, poking around in the Webkit REPL to find APIs you might make use of is a good way to find unsupported accidentally public APIs that will blow up your app at runtime after some point update of your framework.</p>
  464. <p>All these forces – the rapid changes, the diverse needs, the hostile environment, and the loose language features – make large, feature-rich JavaScript frameworks slow, lumbering prey. A horde of young, nimble <a href="http://microjs.com/">microframeworks</a> swarm them, take them down, and fight over the meal. Modularity and componentization reigns.</p>
  465. <p><a href="http://en.wikipedia.org/wiki/The_Mythical_Man-Month"><img src="http://www.allenpike.com/images/2015/tar-pit.jpg" alt="Evolution's a bitch." /></a></p>
  466. <p>A world dominated by endless tiny frameworks actually works okay for JavaScript experts and consultants. We become skilled at mixing and matching components, are able to spend time keeping up to date on the latest options and their relative strengths, and gain a lot of fodder for our conference talks. Yet for those who are new to JavaScript or who aren’t full-time client-side developers, any given tiny framework can’t possibly solve the wide range of problems that JavaScript developers struggle with. Product companies building large, long-lived client-side apps need to settle on some framework, and live with the consequences for years as they discover its limitations.</p>
  467. <p>The well-regarded <a href="http://lhorie.github.io/mithril/getting-started.html">Mithril.js framework is only 5kb</a>. That’s great for load and parse time, but it necessarily can’t solve a rich array of problems. Rails, by contrast, has more than 100x as much code. <em>Just ActiveRecord is 1274kb!</em> In the browser, you can’t sanely use a 1.2MB framework, and so the proliferation continues.</p>
  468. <p>Neck deep in frameworks, <a href="http://blog.andyet.com/2014/08/13/opinionated-rundown-of-js-frameworks">choosing one we’re actually happy with</a> becomes virtually impossible. The Paradox of Choice means that knowing you’re probably not using the right framework causes endless cognitive dissonance. Ironically, this dissatisfaction drives even more people to create their own frameworks.</p>
  469. <p><a href="http://cube-drone.com/2014_02_19-Cube_Drone_76_Many_Angular_Ones.html" title="Cube Drone by Curtis Lassam."><img src="http://www.allenpike.com/images/2015/cube-drone-angular.jpg" alt="Cube Drone by Curtis Lassam." /></a></p>
  470. <p><a href="http://blog.tastejs.com/yet-another-framework-syndrome-yafs">Framework</a> <a href="https://the-pastry-box-project.net/addy-osmani/2014-January-19">fatigue</a> has driven down the number of frameworks that JavaScript developers actually try. Who is going to actually build a non-trivial application with Dojo, YUI, ExtJS, jQuery UI, Backbone, Ember, Cappuccino, SproutCore, GWT – oh man remember GWT? – Angular, Sencha, jQuery Mobile, Knockout, Meteor, Ampersand, Flight, Mithril, Polymer, React and Flux? Seriously?</p>
  471. <p>Nobody can try all the popular options, but everybody wishes for consolidation and more wood behind fewer frameworks. As such, a lot of developers have fallen into a pattern: avoid learning a new framework until it seems like one is finally ascending to the throne as the widely popular, exceptionally capable, “won’t get you fired” choice for building JavaScript frameworks. While Google Trends is no double-blind study, it seems clear that interest in Angular has far surpassed that of any historical web app framework. After a decade of chaos, it finally looks like one we’ve found the chosen one!</p>
  472. <p><img src="http://www.allenpike.com/images/2015/rise-of-angular.jpg" alt="Composition of Google Trends searches of &quot;%s tutorial&quot; for 9 frameworks." /></p>
  473. <p>Yes, Angular,js, the framework that I initially described in 2009 as “unreasonably weird” seems to have achieved a level of popularity that no JS app framework ever has. Between serious support from Google, an easy ramp-up path, and a rich community, Angular looks poised to finally settle the…</p>
  474. <p>Wait, what’s that? The Angular team has decided that <a href="http://developer.telerik.com/featured/can-angularjs-maintain-dominance/">Angular 2 will not be compatible with Angular 1.x</a>, and there will be no easy upgrade path?</p>
  475. <blockquote>
  476. <p>Developers familiar with the Angular 1.X will encounter a drastically different looking framework and will need to learn a new architecture.</p>
  477. </blockquote>
  478. <p>Oof.</p>
  479. <h2 id="is-this-forever">Is this forever?</h2>
  480. <p>Perhaps we should just resign ourselves to it always being this way. While I’ve long argued that creating your own JavaScript framework out of a microframework and a DOM library is madness, maybe it’s the least bad option. Maybe the quirks of the language and the constraints of the browser make a sophisticated but bulletproof framework like Cocoa or Rails just kind of impossible.</p>
  481. <p>Maybe I should just call off the hunt. Though, people do seem pretty excited about React.js. They have some smart developers and exciting ideas, at least from what I’ve seen.</p>
  482. <p>You know, maybe I should build something new with it and see what it’s like. Maybe… maybe it’s the one.</p>
  483. </article>
  484. </section>
  485. <nav id="jumpto">
  486. <p>
  487. <a href="/david/blog/">Accueil du blog</a> |
  488. <a href="http://www.allenpike.com/2015/javascript-framework-fatigue/">Source originale</a> |
  489. <a href="/david/stream/2019/">Accueil du flux</a>
  490. </p>
  491. </nav>
  492. <footer>
  493. <div>
  494. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  495. <p>
  496. Bonjour/Hi!
  497. Je suis <a href="/david/" title="Profil public">David&nbsp;Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
  498. Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
  499. </p>
  500. <p>
  501. Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
  502. </p>
  503. <p>
  504. Voici quelques articles choisis :
  505. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  506. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  507. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  508. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  509. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  510. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  511. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  512. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  513. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  514. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  515. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  516. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  517. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  518. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  519. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  520. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  521. </p>
  522. <p>
  523. On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
  524. </p>
  525. <p>
  526. Je ne traque pas ta navigation mais mon
  527. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  528. conserve des logs d’accès.
  529. </p>
  530. </div>
  531. </footer>
  532. <script type="text/javascript">
  533. ;(_ => {
  534. const jumper = document.getElementById('jumper')
  535. jumper.addEventListener('click', e => {
  536. e.preventDefault()
  537. const anchor = e.target.getAttribute('href')
  538. const targetEl = document.getElementById(anchor.substring(1))
  539. targetEl.scrollIntoView({behavior: 'smooth'})
  540. })
  541. })()
  542. </script>