16 ms·
A whole website in a single JavaScript file
- kokanee 4y agoIf I publish my website to npm and then import and run it in an index.js file, does that also count as "a whole website in a single JavaScript file"?
- adriangrigore 4y agoI personally find it insane to use the monstrosity in terms of loc and complexity that the v8 engine is to generate a static HTML web site. I also disagree with other JS based static site generators because of the above reasons. I strongly believe it's a bad idea to have to locally install nodejs or deno and write JavaScript to generate a few HTML pages. Also, I disagree with plain HTML because of duplication. http://mkws.sh/ http://mkws.sh/ uses the standard UNIX tools to generate `HTML` pages featuring a powerful sh based templating engine https://adi.onl/pp.html https://adi.onl/pp.html. Dependencies and complexity are kept to a minimum. It does the minimum required, generate HTML pages and keep duplication low using aprox 400 SLOC.
- mark_and_sweep 4y agoGlad to hear that you prefer shell scripting, but please consider that there are many (web) devs out there who prefer JavaScript: "Many [devs] are more familiar with the Chrome DevTools console than they are with a Unix command-line prompt. More familiar with WebSockets than BSD sockets, MDN than man pages. (...) Many developers, we think, prefer web-first abstraction layers." -- https://deno.com/blog/the-deno-company https://deno.com/blog/the-deno-company
- adriangrigore 4y agoNot sure if matter of preference or matter of right tool for the job and industry agreed best practices regarding simple vs complex. In the sense that you may prefer the round peg, but it doesn't fit the square hole. I've been doing JavaScript myself for about 15 year, unfamiliar with the UNIX philosophy (to be doubted as any doctrine). Started doing web development using plain HTML the "old school" way, I personally dare to say the _normal_ way. Before the rise of SPAs I very much agreed with the idea of progressive enhancement which is coming again into attention with the likes of https://turbo.hotwired.dev/ https://turbo.hotwired.dev/. While doing SPAs I always felt that stuff constantly didn't fit, that we were constantly using unfit tech, doing hacks for benefits of using a single (unfit?) language both on the server and the client, partial loads (faster loading times) and having a single codebase for all OSes. Stuff felt hacky most of the times and we were hiding those complex hacks under what _seemed_ as elegant and simple abstractions. But I believe most experienced JavaScript developers agree that the elegance and simplicity is mostly on the surface. I constantly felt dissatisfied with the code I wrote. I refuse to go on a full rant regarding SPAs and JavaScript but that's the gist of it. While configuring my dev environment I stumbled up the https://suckless.org/ https://suckless.org/ guys. Their code embodies the UNIX philosophy well although some people, including me, might say that some stuff is too simple. Simplicity for the sake of simplicity is not a good idea (nothing for the sake of anything is a good idea to be honest) but rather as a consequence of you understanding of what's not really needed. While investigating more more the UNIX world, discovering OpenBSD and using it as a daily driver things started to fit and make sense. Now, regarding how mkws fits generating static sites, it mimics building a small C project except the Makefile is replaced by a shell script, so all the principles fit and are well established. pp is the compiler, .upphtml files are the sources, html files are the output binaries. Everything integrates and fits well. I feel satisfied about how everything works. Code is small and simple, abstractions are kept to a minimum. I, as a single person, am able to investigate, understand and change every part of the generating process. Can't say the same thing about a JavaScript static site generator, you don't really need the v8 engine to generate a few HTML files, that's complex, most of use agree simple is relatively good, complex relatively bad as an industry best practice. Regarding SPAs, I believe they were a quick solution until we properly solve the problems they solve via progressive enhancement.
- 5560675260 4y ago> a powerful sh based templating engine > it mimics building a small C project You're using practices from a language unrelated to webdev, scripting language unrelated to webdev and what looks to be a closed source generator built and (un)maintained by a single person. There probably is a context where this setup makes sense, but to me it's anything but simple or intuitive.
- 1vuio0pswjnm7 4y agoIf the the deno executable is roughly the same size as a popular "web browser"1 why not just distribute Javscript files and let users run them in deno. Or let users "import" them into their own scripts. 1 The one I downloaded weighs in at 85MB. That is smaller than some popular smartphone apps. As I understand it, deno is designed to be somewhat safer than nodejs. I can edit and compile deno much easier than I can compile a popular web browser. Some popular web browsers are not meant to be edited or compiled by users. If there are things that users dislike about these programs they are powerless to change them. The "web browser" is created and controlled by companies in the business of user data/metadata collection and advertising. AFAIK, the people behind deno are not engaged in such practices. The "modern" web browser has become a Trojan Horse of sorts. Instead of a program for displaying and reading HTML, it has become a vehicle by which users indiscriminantly/involuntarily run other peoples' programs, often written in Javascript, in a context where a third party, the commercially-oriented browser vendor, can quietly collect user data/metadata, mediate and manipulate user interaction. Deno takes the Javascript interpreter out of the browser.
- hyuuu 4y agodoes Deno have a solid web framework? Next.js is somewhat being worked on / forked for, like Aleph.js
- o_m 4y agoRemix is working on making their framework work with Deno. You can already try it out.
- lucacasonato 4y agoAlso check out https://fresh.deno.dev https://fresh.deno.dev
- sebringj 4y agoSeemed pretty simple to add a bagel route https://dash.deno.com/playground/cold-parrot-17 https://dash.deno.com/playground/cold-parrot-17 with page not found handling. Love the minimalistic nature of this.
- pkrumins 4y agoAll apps should be written as a single, stand-alone, self-contained file.
- deleted 4y ago[deleted]
- didip 4y agoI fucking love what Ryan is trying to do with Deno. The entire JS landscape is unnecessarily complicated and NPM is making it even worse. Deno is making JS development fun again. Major props. I hope Deno Deploy is a commercial success for the team.
- abdellah123 4y agoWait a sec, how does Deno knows these classes are actually tailwind css classes? How can I disable that or use an alternative?
- lucacasonato 4y agoThe `ssr` function uses the twind module to extract the classes and generate plain CSS.
- gorgoiler 4y agoAlas, I wanted to believe, but I pretty much immediately uncovered a bug with the way my browser’s back button works. In iOS Safari, click the “CLI” link at the top, then swipe the page to the right to go back. If you do it slowly it works, but the first time I tried I did a regular flick-swipe from about the height of the page where the version number is. I was trapped in deno.land and couldn’t go back. (Maybe that’s a bug in deno.land though, not deno.com?)
- mcintyre1994 4y agoWhere’s Tailwind coming from in this example? It doesn’t seem to be imported, and I can’t see anything about it in their playground link either: https://dash.deno.com/playground/website-in-a-single-js https://dash.deno.com/playground/website-in-a-single-js
- wink 4y agoI've been looking at Deno very briefly recently (overall a good impression) and I was very much surprised that just getting the visitor's IP address took like a dozen lines of code. My test case was, basically reproducing something like <?php echo $_REQUEST . "\n" . $_SERVER; ?> and I was a little surprised how much convenience was baked into it and how you wouldn't have access to all that in other libs. That someone created an issue[1] makes me think I am not just not looking good enough and it's actually tedious. [1]: https://github.com/denoland/deno_std/issues/1884 https://github.com/denoland/deno_std/issues/1884
- zzbn00 4y agoTiddlyWiki is a whole wiki in a single file, been around a while, great system: https://tiddlywiki.com/ https://tiddlywiki.com/
- seanstrom 4y agoI keep seeing comments about static html vs generated html. So I have a question (please respond): Why can’t we just run the example Deno program to generate snapshots of html? It seems like some of us think pure static html is a good goal for some things, so why not use this Deno program to create the same html responses in generated files? It’s probably the same amount of code because instead of writing a http response you write a file. Of course you lose some functionality this way, but your app you rules imo
- egberts1 4y agoWarning: Mocking-JS plug Meanwhile, I just created a JavaScript-free website. Never have to worry about broken NPM, cookies, trackings, API, or JS-based malware. And I use my iPhone/Android to edit/create web pages in Markdown, then my CI will build it and post it for me. Look at the snazzy 3-D CSS, also JS-free. Did I mention that I have a no-nonsense Privacy Policy? 3-D web page. https://egbert.net/blog/index.html https://egbert.net/blog/index.html
- edent 4y ago> rendered dynamically, just in time, at the edge, close to the user. HTML. You're serving HTML. Doesn't really matter that the server-side language is JS, PHP, or BASIC.
- AaronO 4y agoAaron from Deno here. Of course it's producing HTML as an output, but the point is that you can use JSX and familiar technologies like tailwind to dynamically generate that HTML at edge vs client side. And unlike a pure static site, you can add API or form routes
- kokanee 4y agoWow, a lot of misunderstanding of what Deno is and how it works in these comments! Must be frustrating for you. I'm a huge fan of runtimes that reduce boilerplate and configuration, so that's what makes me most interested in Deno. What I'm most concerned about is that we're pushing the idea that Deno's approach to third party imports solves all the problems of npm et al. If we teach developers to think of third party and native libraries as equivalent, I think we're hiding a lot of problems rather than solving them, which could be even worse.
- brundolf 4y agoI can appreciate what's being done here, but I think a more compelling demo would have had a bit of dynamic rendering just to emphasize the point (since in the real world, a fully-static site like this would be better served by a static-only hosting service with no custom server running at all, even one on the edge). Even something as simple as grabbing the current timestamp and displaying it in the returned HTML, just to show that logic is running on every request.
- smm11 4y ago
- donohoe 4y agoOh. So you've reinvented PHP. Nice.
- dmitrygr 4y ago"time to interactive: 1.0s / first content paint 1.0s" My man, let me introduce you to ... HTML. It has "time to interactive" at 0.0 seconds and content paints instantly!
- lucacasonato 4y agoI think you might have misunderstood the blog post. It is server-side rendering on the edge, shipping nothing more than plain HTML/CSS to the browser. There is no client side JS *at all* here.
- dmitrygr 4y agoThe shown page could be served on 0.01 seconds if it was...html. Or, if you MUST lob complexity at it, use a static site generator... that generates...HTML
- suprfsat 4y agoThe demo is literally a static site generator that generates HTML
- cxr 4y agoIt's not, unless "static site generator" is one of those terms (like "literally" or "REST"[0]) that has morphed to mean the opposite of what it was supposed to mean. (Not to be confused with "serverless", which never meant what the word suggests.) This application is generating HTML on the server, but so does PHP. A Web site backed by a PHP application is the antithesis of a static site. 0. https://news.ycombinator.com/item?id=23672561 https://news.ycombinator.com/item?id=23672561
- andruc 4y agoYou can see for yourself with the provided Pagespeed metrics that the root document was served in around 30ms (corresponding to TTFB). If you can elaborate on how statically-served HTML would render orders of magnitude faster than server-sider-rendered HTML with a similar response time, I'd love to hear it.
- jack_riminton 4y agoI don’t think a simple, static site is a great example for an entire framework
- AaronO 4y agoWhat other kinds of examples would you like to see ? The goal was to showcase simple yet intuitive JSX + tailwind at edge, we didn't elaborate on more advanced use-cases like authenticated pages, API endpoints/forms, dynamic pages (location, etc...) or parametric routes.
- solitus 4y agoI'd love an example where the user updates some piece of data. The update should be displayed right away to the user and in a DB.
- lucacasonato 4y agoThere is another blog post coming up in a couple of weeks (hopefully) that will demo this.
- tmp_anon_22 4y agoThis starts to make sense when you consider the self-flagellation of a full server-side-rendering production setup that has existed over the past decade, to the point many SPA products completely give up on SSR - or nowadays throw themselves at the walled garden of Vercel/Next.js etc to solve it for them.
- rglover 4y agoThe truth I learned building my own SSR JavaScript framework is that it's not that complicated, it's just made complicated. 1. Get some data from a database/source. 2. Pass that data to a template/component. 3. Convert that template/component to HTML (using the given framework's version of renderToHTML()). 4. Return the HTML to your HTTP request. For example, here's the SSR for my framework: https://github.com/cheatcode/joystick/blob/development/node/src/ssr/index.js https://github.com/cheatcode/joystick/blob/development/node/.... It blew my mind when I wrote it because I was under the impression it would be more difficult.
- n42 4y agoI am not a fan of Vercel's strategy, but exactly how is the open source and MIT licensed Next.js a walled garden?
- colejohnson66 4y agoIt's not. Next.js works on any platform supporting Node, and Vercel supports more than just Next.js. They support dozens of other frameworks.[0] They do promote Next.js on Vercel, but they don't stop you from using other systems. [0]: https://vercel.com/new/templates https://vercel.com/new/templates
- o_m 4y agoHosting next.js on Vercel and Azure is like night and day. A lot of smaller things start breaking, like `NEXT_PUBLIC_` environment variables. For me coming from Vercel, using Azure has been an uphill battle.
- 4y ago
- thunderbong 4y agoI don't think most of the people commenting here realize that the entire site loads just fine with Javascript disabled. Essentially this is HTML getting generated on the server. The fact that it is in Deno rather than PHP, Ruby or Python is the point of the article.
- bachmeier 4y ago> Essentially this is HTML getting generated on the server. Not a web developer. How is this different from CGI or a regular web server? This an honest question - I don't understand the significance.
- DangitBobby 4y agoIt's written in js/React so you can share frontend and backend code and write the entire site in one language or even using the exact same components for server side and client side rendering. This is a boon for development. Ignore the nay-sayers.
- brundolf 4y agoThe demo doesn't use React, only JSX
- deleted 4y ago[deleted]
- DangitBobby 4y agoThe import { h } made me think it was preact, but I guess it's not even that.
- xcambar 4y agoit is not different. CGI is replaced by JS Apache/nginx is replaced by CDN web server is replaced by edge nodes (aka, glorified runtimes automagically spread across many endpoints)
- 4y ago
- Dangeranger 4y agoSince a bunch of people are setting up a straw-man to criticize this post for "not just serving plain HTML" I'll share my opinions on this. Almost nobody is going to use Deno to serve a basic HTML site with less than a dozen pages, they are going to use it to build a monolith application to get content from a database, or a service, then generate server-rendered pages, and also host an API from the same codebase, or something similar. Setting up a monolith application means using something like Ruby-on-Rails, Django, Spring, ASP.net, or rolling your own with a Node.js backend serving a SSR front-end, or hydrating React views. If you haven't experienced this already, you will come away with one of two conclusions. 1. Wow, this is so much fun, as long as I stay on the happy path of ... Rails ... Django ... ASP.net. 2. Wow, setting up all these moving parts really sucks' I'm mostly writing configuration files, and then Googling the error messages when I inevitably screw something up. What I think Deno is trying to do is make the process of getting a server side rendered application with modern tooling running with minimal ceremony, while still enabling the developer to customize the system and build things that are not covered by the documentation guides. In addition, their solution is one that can be more easily hosted on edge servers than most other options out there. I'm glad they are doing it, because it's a sorely lacking area of modern web development. They only other people who are taking this on in a meaningful way that I am aware of are Remix. I would be happy for there to be more entrants into this field. Best of luck to everyone out there.
- rglover 4y ago> Setting up a monolith application means using something like Ruby-on-Rails, Django, Spring, ASP.net, or rolling your own with a Node.js backend serving a SSR front-end, or hydrating React views. https://github.com/cheatcode/joystick https://github.com/cheatcode/joystick
- colordrops 4y agoYou can use a service worker proxy to cache and serve files to an application, which keeps things both fast and also with raw uncompiled html and JS file.
- dodyg 4y agoASP.NET Core is pretty minimal in ceremony nowadays. You can easily do single file web development. https://github.com/dodyg/practical-aspnetcore/blob/net6.0/projects/sfa/wiki/Program.cs https://github.com/dodyg/practical-aspnetcore/blob/net6.0/pr...
- neogodless 4y agoIn Firefox 98.0.2 / Windows 10, at the playground, the URL does not reflect the route, and refreshing will display the hidden but currently selected route, rather than the URL route. https://imgur.com/a/ZP95YcD https://imgur.com/a/ZP95YcD
- lucacasonato 4y agoYup, this is very unfortunate, but sadly a browser cross origin privacy protection. We can not fix it without injecting some third party code into your site automatically (which we don’t want to do).
- gtirloni 4y ago> These are served using the serve function from the standard library. I guess Node.js could learn a lesson here.
- binarymax 4y agoDemo was started by the original author of Node, and they took lessons learned to this new platform. Also note that Deno is an anagram of node :)
- zamadatix 4y agoIs there a particular advantage to how this is done here with Deno or is this just an example of server side rendering being possible in Deno? The latter is fine as I'm a fan of Deno :) just missing why it's such a popular post (maybe more Deno fans?)
- dustymcp 4y agoYou mean you are a user ? Fans are for music :)
- zamadatix 4y agoI'm actually still a Node user! I really like how Deno has been innovating this space though and it's come a long way in the last couple of years so I'm looking forward to making the switch at some point. Even if I never do for some reason (most likely node API specific libraries) it has really given Node some reasons to innovate in a few places and I love Deno for that as well.
- AaronO 4y agoIt was mainly intended to be a "cute" example of the latter. Technically if you were doing this in Node, you would need at least a package.json and would have to configure your TS/JSX transpile, etc...
- lhorie 4y agoI mean, this is a "single file website" in the sense that `<iframe src="https://google.com"></iframe> https://google.com"></iframe>` is a "search engine implementation in one line of code". The only semi-interesting thing here is that this demo pulls dependencies from 3rd party registries via HTTP without an explicit install step. It's really not that different than doing regular Node.js development with a committed node_modules (hi, Google), except that if node.land or crux.land go down, you've lost your reproducibility. The thing about "familiar/modern techonologies" seem like superficial vanity. A vanilla Node.js equivalent might look something like this import {createServer} from 'http' import {parse} from 'url' const route = path => { switch (path) { case '/': return home() case '/about': return about() default: return error() } } const home = () => `Hello world` // etc... createServer((req, res) => { res.write(route(parse(req.url))) res.end() }).listen(80) Which is really not anything to write home about, nor an intimidating monstrosity by any measure. Serving cacheable HTML is really not rocket science, it simply does not require "the latest and greatest" anything.
- krapp 4y ago>The only semi-interesting thing here is that this demo pulls dependencies from 3rd party registries via HTTP without an explicit install step. We used to call those script tags back in the olden days...
- hamandcheese 4y ago> except that if node.land or crux.land go down, you've lost your reproducibility. I wouldn’t say you lost it, I’d say you never had it in the first place.
- CreepGin 4y agoNow, add jsx and ssr to your example, deploy it, then compare with the deno version in terms of performance, code length, and dev time.
- lhorie 4y agoWhy? Just so you can tell another developer that there's a compiler transpiling non-standard syntax into function calls that concatenate strings at runtime? While the output HTML that the user sees is exactly the same? That's exactly why I'm calling out to be library vanity. My example is SSR, that's literally the default baseline. It doesn't make a very strong argument to imply my 5 min thing will somehow be worse if only you get to decide what random garbage to add to it to make the alternative look better. E.g. Make hegel types work in the original and then let's talk loss of productivity from arbitrary decisions. Deployment for a vanilla node.js thing is as simple as adding `node index` as the entry point in your favorite provider (because they all have node.js images these days), I've had such a thing humming along for years. Again, it's really not rocket science.
- gherkinnn 4y agoThis is great. I've been dabbling in Deno for a while now. Standard lib is there. Testing is there. All the packages I'd ever want are there. Linting, a strong style guide, and a documentation generator too. And unlike other beasts, it feels so minimal and out of the way.
- onion2k 4y agoTons of big websites use something quite similar to this for their maintenance pages - pop a page of HTML in a JS function, upload it to a Cloudflare worker, and attach that worker to a wildcard route to catch everything on your domain temporarily when you want users to see your maintenance page. It's a common strategy that works well.
- mavbo 4y agoThis is great, I'm not sure why this is being misinterpreted so much. Serving generated HTML from Node using Express many years ago was also great at the time. You can still do that, but in my experience the tooling is quite dated/fragmented and the ecosystem+language has evolved significantly since then. Nowadays, SSR+Node generally refers to front-end frameworks with SSR capabilities (Next, Nuxt, SvelteKit, etc.) or generation of static files. Building a dynamically server side rendered site using TypeScript+JSX but without the issues of client side frameworks, hydration, SPA routing, etc. sounds revolutionary, even though it shouldn't(?)
- yawnxyz 4y agoWow that's cool. Would love to see a more "interactive" to-do or "guestbook" site that shows how that side of things work. Also wondering if this can be done serverless-ly or requires something always on?
- lucacasonato 4y agoDeno Deploy is serverless, and Deno CLI is always on, so you can do either with the same code
- ovao 4y ago> /// <reference no-default-lib="true"/>: Deno comes with various TypeScript libraries enabled by default; with this comment, we tell it to not use those, but instead only the ones we specify manually. Interesting. I checked the docs on this and it’s not quite clear to me why this is needed in this case, or what the benefit is in taking this approach. Is this strictly a build time optimization, or is it necessary in this example?
- lucacasonato 4y agoIt’s actually not needed at all for runtime. It’s purely for editor experience and type checking.
- infiniteL0Op 4y ago
- togaen 4y agowhy