S05E11 1h 16mSeason 5

Episode Transcription
Hello everyone and welcome to THE .NET Core Podcast. An award-winning podcast where we reach into the core of the .NET technology stack and, with the help of the .NET community, present you with the information that you need in order to grok the many moving parts of one of the biggest cross-platform, multi-application frameworks on the planet.
I am your host, Jamie “GaProgMan” Taylor. In this episode, I talked with Dave Glick about Statiq which is a static site generator - although calling it static site generator, as we’ll see, is quite reductive. We also talk about the JAM Stack, static sites, and how most websites don’t actually need something like ASP .NET Core or WordPress generating pages at request time. We also talk about a very small selection of some of the things that you can use Statiq to generate - why not check it out today?
Along the way, Dave dispels some of the common misconceptions of statically generated vs completely dynamically generated websites (i.e. pages generated ahead of time vs pages generated at request time), and I talk about how the website for the show is generated ahead of time, and some of the benefits that the community of listeners get from that. This is a conversation that both Dave and I could have kept going with for hours, but we’ve agreed to come back to it another day in order to explore further.
So let’s sit back, open up a terminal, type in dotnet new podcast and let the show begin.
Jamie
Dave
Jamie
Dave
Jamie
Dave
Jamie
Dave
Jamie
But yeah, so yeah, I reached out to you because there’s this wonderful open source project that you’ve been working on. And just saying “open source project” is doing it a disservice, because there’s a whole bunch of stuff that he does, I know of it as a static site generator. And this is this is your, your, your project Statiq, right. And I… for the listeners, you’ve all been browsing a static website, a statically generated website, if you’ve gone to the website for the for the podast, because it’s statically generated. That doesn’t mean that it doesn’t change, it just means that my definition of it is that the HTML is generated ahead of time. And so you don’t have a server sitting there receiving a request, generating a page, building that on the server whilst we’re waiting, and then sending that back over the wire. And that was purely from a - I hate to say, but a security standpoint, that’s why I chose a statically generated website. Because there’s no server you can’t… or there is a server but there’s no there’s no like server infrastructure.
Dave
Yeah, I mean, security is certainly one very good reason why people lean towards static websites. There are, yeah, there are others: performance is another good one. A lot of times because the resources and the content have been pre generated. You can push it out to very low resource servers like edge servers or content delivery networks. And it can get to the users a little bit faster, since there’s no processing that needs to be done.
But let’s back up just a minute and talk about what a statically generated website actually is. Yeah, cuz that’s a, so we’ll rewind, kind of back to the very beginning here. And a statically generated website is a website where all of the things that come down to the web browser, to the client, have been prebuilt. That could be HTML. But it could also be JavaScript, it could be images, it could be other resources. Essentially, you take the webserver out of the picture, and you do the work that the webserver would normally do beforehand.
Now, there’s some challenges and tricks to that it’s kind of a different way of looking at things. For one, it means that you have to do the work that the webserver would do, for every possible endpoint and combination of query strings and requests, which is certainly doable. I think people would be surprised how many websites you visit on the modern web that are either wholly or partially statically generated. There are a number of very large scale sites that have lots of dynamic content that are being delivered to you as static resources, kind of in their initial form. Stack Overflow is one that comes to mind. They do a lot of what’s called edge caching, which is a form of static generation where you generate things once and then save it. Amazon statically, generates a lot of their product pages, and then augments those during a request.
Another thing to keep in mind is that a statically generated website does not mean static content, or static user interface. What a lot of people do is statically, generate the web resources, and then create a dynamic API that can be called to populate that. That model is often what’s called the JAM Stack, which you may or may not have heard, and is kind of gaining traction as a term for this sort of statically generated website. The JAM Stack is a stack with the three letters standing for JavaScript, API’s, and markup. And it’s kind of the bare minimum that you would need to create a statically generated site that has dynamic content on it through the use of API’s and JavaScript; essentially moving the processing from what was traditionally on a webserver to the user’s web browser, which solves a lot of problems, right? It’s coming full circle, security being one of them. If you don’t have a webserver, sitting there executing things. There’s there’s no attack surface.
Jamie
Dave
Yeah, and I think, you know, I think I touched on it earlier. You know, blogs, like you said, that kind of thing is kind of a perfect candidate for static generation. But you know, you can go bigger than that to: really any site where the number of views that a user might look at is well defined and well bounded. could in theory be statically generated. Even if that number is, you know, in the 10s of 1000s, due to, you know, like, factorial style combinations. As long as you can define those combinations, and figure out exactly what the page should look like. You can statically generate it and stick it on a static host. And then augment with JavaScript and API’s as needed.
A pattern I’ve seen is, folks statically, generating JSON files, and then serving those as a static resource, as an API, so to speak. And that then creates all kinds of possibilities. If you’re a statically generated site with statically generated JavaScript, loads your statically generated JSON, and can do things like grids with filtering and paging and you know, the world’s the limit there in terms of your imagination, how you can use that. So there are very few sites that really aren’t possible with static generation. Now, of course, there’s always a trade off to there’s a, how hard is this going to be to statically generate? How many resources will I need to output? When that number gets into like the millions. you start to say, “well, okay, maybe this isn’t practical for this model.” You know, every tool in the toolbox has a use.
Jamie
Dave
Jamie
Dave
Jamie
Dave
Jamie
Dave
Jamie
Dave
Jamie
Dave
Jamie
Dave
Yeah, so Blazor kind of operates in a few different modes, right? I mean, there’s the server side Blazor mode, where it creates this open pipe, and sends DOM updates and rendering commands to the client from a server; that is absolutely not static or JAM Stack, or anything, right. You need a heavy server that is kind of almost mirroring the clients browser in this stateful manner that knows what that browsers seeing, and can compute the differences in the DOM descend down to light it up and make it change the way you want to. Nothing wrong with that mode. And I think it’s just brilliant, the way it works, and the ideas and architecture behind it. But that’s not what we’re here to talk about. Right? We’re here to talk about statically generated things and JAM S and BAM Stack.
So when we talk about Blazor, in static generation contexts, what we’re talking about is the client side Blazor mode. And that’s the mode where the .NET Blazor compiler will take your blazer application and create a[n] assembly from it. And then also create and output a bunch of bootstrapping stuff. That includes some JavaScript files that help initialize web assembly that load up the .NET runtime. And then that load your Blazor assembly into memory on the browser. And I just said a bunch of like really buzzwordy buzzwords there. So if anyone’s not familiar with it, what’s happening here, kind of less buzzworthy sense is that: there’s this technology that exists inside browsers now that can run kind of arbitrary computer code, right? We’ve always been able to run JavaScript in the browser kind of as far back as ever browsers. And JavaScript is a specific language, and you write it and it shows up in text that get sent as text, usually down to the browser. The browser reads it, compiles it, and runs it, right. And that’s kind of the model we’ve always had.
But now there’s this thing called WebAssembly. And the idea is that we’re gonna swap out that piece of JavaScript that does the work and replace it with - or add alongside it - a little virtual machine that can read and understand machine code; almost like assembly code, that’s why they call it WebAssembly. And so when we do that, the idea is essentially the same: I want to send some kind of logic, some kind of programming code, to the browser; but instead of that code having to be JavaScript, I can now send it code that came from any language that is at a kind of a lower level and this WebAssembly thing that lives inside the user’s browser knows what to do with it and can run it.
So kind of coming back to Blazor, in this client side mode of Blazor, the .NET compiler takes your your Blazor app, compiles it all into a standard .NET assembly, and then rigs up the extra stuff, so that a client’s web browser using this WebAssembly bit that’s in there, can load up the .NET runtime, and then load up your Blazor app from its assembly and run that directly in the browser. So in a lot of ways, it’s not all that different conceptually, from sending down a JavaScript file to the browser, right? You’ve got maApp.js, that’s pretty typical in SPA applications, for example. This is kinda like that. It’s just instead of .js, it’s a bunch of .wasm, and .dll files.
And so when you start thinking about it that way, your Blazor app becomes your statically generated application. So I think it’s you know, it’s funny, we talked about how - and we’ll talk about Statiq in a few minutes, and how that’s a static generator for .NET - but it’s easy to forget that .NET now already has a static generator. It just happens that the static generator that’s built into the platform is built around this sort of WebAssembly technology.
Jamie
Dave
Jamie
Dave
Jamie
Dave
Jamie
Dave
Jamie
Dave
A Request To You All
If you’re enjoying this show, would you mind sharing it with a colleague? Check your podcatcher for a link to show notes, which has an embedded player within it and a transcription and all that stuff, and share that link with them. I’d really appreciate it if you could indeed share the show.
But if you’d like other ways to support it, you could:
- Leave a rating or review on your podcatcher of choice
- Head over to dotnetcore.show/review for ways to do that
- Consider buying the show a coffee
- The BuyMeACoffee link is available on each episode’s show notes page
- This is a one-off financial support option
- Become a patron
- This is a monthly subscription-based financial support option
- And a link to that is included on each episode’s show notes page as well
I would love it if you would share the show with a friend or colleague or leave a rating or review. The other options are completely up to you, and are not required at all to continue enjoying the show.
Anyway, let’s get back to it.
Jamie
Dave
So why you know, why this project? Why does it exist in the world? And the answer is really twofold. And both reasons are kind of equally important. The first is that I know razor and I like razor. And when I build a website, I want to use razor. But I also really, really like static generation and have way before Statiq was even a glimmer in my eye. I just I really liked the concept. I like how much it removes off my plate, right? You get to a point when you have just too much to do, you know, we can’t build all the things we want to build. And so any tool or any concept that eliminates things from my “stuff I need to worry about” bucket is kind of vastly interesting to me. And so static site generation like immediately fills that kind of thought process, because it removes this entire class of web app problem in terms of setting up a web server, deploying it and all that, that you just don’t even think about anymore.
So and you know, uptime making sure it doesn’t go down. The number of times, before I really got into statically generated websites that, you know, I would get an alert that like 9pm at night, or 10pm. You know, as I’m trying to enjoy my evening, that my web server is suddenly offline, I haven’t seen one of those in six years. So yeah, that was kind of the first pitch. I liked static generation as a concept. But I like .NET and in particular, razor is a templating language. And at the time, there was no way to marry the two. So I set out to make a way of turning razor templates, and particularly razor layouts, into websites without having a web server involved.
But the kind of second reason, that probably would not have been enough alone to keep me going, as long as the project has been going. What really kind of turns into a bit more than just turning razor into HTML is, I looked around and did not see the kind of static generator in any language that I would want to use. And what I mean by that is, most static generators are, in particular, static website generators, and their entire purpose is to take a set of markdown files, along with a layout written in whatever language du jour that particular platform supports. Sometimes it’s handlebars, sometimes it’s moustache. Sometimes it’s liquid, which I really like. But it’s to take markdown files, and these layouts and turn them into HTML. And maybe do some other stuff to your resources like minify, your JavaScript, or nowadays, they’ve gotten a little more sophisticated and can do things like making JavaScript bundles, and calling out to Webpack and yarn and things like that. But they’re entirely focused around this single concept of turning web stuff into static web stuff. Which is fine, and Statiq can do that, too.
But what I did not see was a way to sort of easily introduce or augment that process with other processes that can get data from different places and produce data in different ways. What I mean by that is, let’s say you have, as an example, a set of content sitting in a SQL database somewhere, maybe that’s got your blog posts in the database, or maybe it’s got a database of products and prices. With most of the existing static generators, at least at the time, pulling from those kinds of resources and using that data in the pursuit of building your statically generated web app was difficult. I mean, you could do it by writing a lot of code. But they weren’t really designed to do that. So static is kind of my answer to that problem. It’s how do you build a static site generator, that that can do, you know, the happy path is easy. It can do the same stuff that your Jekyll or your Hugo can do without really any effort on the part of the developer. But now, we’re .NET developers, so we want to tinker, right. That’s kind of Microsoft’s whole ethos. And we kind of inherited as .NET developers, right. So as a .NET developer, I want to tinker with this, I want to introduce things, I want to use this as a toolkit to build my own static generator that can pull data from wherever it needs to pull data from; that can mix and match data, however it needs to; that can splice data up and mix it together; and do all those things in a way that is kind of easy to think about and visualize.
So that is really the sort of ideas are in marketing because I’m not marketing to anyone. But that’s the marketing pitch, right? That’s the elevator pitch. Is it’s a static generator that is designed mostly for developers, as a toolkit to build your own static generation capabilities that do whatever you need them to do. That’s turned out to be pretty powerful, right? I mean, bloggers use Statiq, we’ve got a lot of people using it for their blogs. And they don’t really tweak it at all, they add the five or six lines of boilerplate code to their app, and they’re ready to go. And they never touched the app again, and they just use it to generate a blog from their markdown. And that’s totally fine. But when you want to go beyond that, it’s designed to be familiar, and robust enough to do so.
Jamie
Dave
But in this case, it’s a little bit different flavor, because we’re reading the API’s at generation time, as opposed to at runtime using JavaScript from the client. In this case, we’re going to go out and our static generator is going to go talk to these API’s while it’s generating the site. And when it’s talking to these API’s, it can pull down that content that was written inside of that headless CMS. So there’s already, like I said, there’s two really great proof of concepts out there that are in use today. Kentico has kind of really done a fantastic job going down that road. They even have their own little microsite that we’ll add to the show notes, that sort of demonstrates how to mix a headless CMS with Statiq; Contentful also has some some work out there doing the same.
And because you know, kind of coming back to the original question, because Statiq is designed for this kind of thing, mixing in your own headless CMS, whatever service you’re using with Statiq by making those API calls within your Statiq app is relatively straightforward. You make the calls, maybe using that company’s .NET API, maybe just using normal RESTful web calls through an HTTP client. You make those calls, you get the data, you tell Statiq to use this data going forward, and then downstream bits can pick that up and run with it. So maybe you feed that data into a razor layout. And now all of a sudden, the pages you made inside your headless CMS, get spit out by static as HTML files wrapped in your razor layout.
So that’s a fantastic kind of case in point there. But there’s others, for example, the speaker directory of the .NET Foundation website uses Statiq, and in that case, speakers create their profiles as yml files inside the .NET Foundation GitHub repo. And the yml file defines the speaker’s name, their web links and some detail information, their image if they want one. And then every time something new gets committed to that repo, GitHub actions goes out, runs statiq, rebuilds the .NET Foundation website, and updates all of these statically generated resources that power the speaker directory. So when you’re browsing the speaker directory, on the .NET Foundation website, you’re looking at a set of statically generated resources, including a JavaScript file in the back end that’s powering the display and filtering. That was all generated on every commit by GitHub actions and immediately updated each time the site is updated automatically.
So yeah, there’s a lot that you can do, when you kind of unshackle what the static generator is capable of. And in keeping in mind with the fact that .NET developers and we’re probably all familiar with ASP. NET as a platform, Statiq tries to follow the same patterns. The fluent configuration should be familiar to anyone who’s ever worked with a, you know, ASP, .NET Core startup file. The dependency injection uses the, you know, the inbox .NET. Dependency Injection container, logging uses the built in .NET logging stuff. So it’s designed to feel familiar. And to… I always try and keep in mind, “what would a static generator look like if the ASP .NET team were to build one”? And that’s kind of what the user experience I’m going after is.
Jamie
Dave
So you make a console app, you import the Statiq NuGet packages, depending on whether you want the kind of lower level framework, or you want some additional capabilities layered on top of that for things like websites, or even API documentation. You bring in those packages. And then you you write, at a minimum, I think it’s down to like two or three lines of code in the entry point to your console app. And those two or three lines of code, bootstrap the whole thing. So in that sense, it’s not unlike creating a ASP .NET Core website, right? You you create the console app. And there’s a little bit of bootstrapping code in there to rig up the web host and get it going. This is kind of similar.
But what that does for you, is even though the kind of basic level Statiq app is… are… those are all gonna look exactly the same. They’re gonna have this exact same three lines of code. But because you’ve got those three lines of code, and you’ve got that app. Now, it kind of encourages, and makes it easy to add more to do more. You want to change settings, maybe you want to change the title of the site. You can do that using configuration files, but you can also do it straight in your code. There’s all kinds of stuff that you can do now that you’ve got that kind of fluent bootstrapper in your startup method.
Jamie
Dave
You can even use it to do things that are completely unrelated to web apps. ’ve seen it used as a like a build tool, or an orchestration tool. Because at its core, Static operates on this concept of pipelines and pipeline dependencies. And it helps with like ordering and concurrency and concerns like that. So that’s Static Framework
Now, if you want it to do some stuff out of the box without writing code, now we’re into a layer sitting on top called Static Web. And Static Web takes all those Lego bricks, and assembles them for you into a set of… I think there’s eight or nine pipelines that are in there and do different things. What do some of those do? Well, some of them convert your markdown to HTML. Some of them create archives like that tag listings, or by date archives, that kind of thing. Some of them, go through and read yml and JSON files and make that available to your pages as they’re being generated. Some of them minify your resources. You know, so there’s this set of kind of pre built features and pipelines that come along with Static Web. So if you want to write a blog, for example, you can import the Static Web NuGet package, write your three lines of bootstrapping code. And now, instead of having nothing to start with, you’ve got a entire static generator that is not dissimilar from Hugo, or Gatsby, or Jekyll, or Eleventy, or whichever ready to go. And it’s now kind of in your app. And you can still augment that, change it, modify it with your own code and pipelines, just like you could with framework, but the groundwork is done for you if you’re working on websites.
And then even the layer on top of that is a project called Static Docks, which does everything Static Web does an add support for reading C# source files or assemblies, and creating API documentation from those. Think kind of like Sandcastle. So you know, there’s different flavors of Static that layer on additional functionality depending on how much you want done for you versus how much you want to do yourself.
Jamie
Dave
Jamie
Dave
You know, you see a Sandcastle site, which looks fantastic. But most of the time, when you see that kind of generated document, there’s there’s a few other tools that that work similarly, you know, you’re on the site, and then you hit the API link in the nav bar, and whoa, all of a sudden, you’re on like a completely different site. And there’s no continuity between the two. So I didn’t love that. And that was one of the reasons I wanted to kind of get API documentation generation in here. Because I felt like that was a missed opportunity to have your guidance, your plain language documentation, and API documentation living in the same sort of universe.
And now, we also have DocFX, which is a fantastic project. And I think those folks are doing great work. But it - as a project - it’s tailored towards powering the Microsoft documentation. And so there’s trade offs there. I mean, that is the team’s focus. So powering arbitrary .NET projects is not really their core focus and constituency. And it shows a little bit in the onramp. So you know, it’s it’s very similar DocFx is very similar to Static Docks, in terms of conceptual, the way that they go about things and the thinking there. The experience, though, is a little bit different. And that’s not to say one is better than the other. And they both have strengths and weaknesses. But you know, I… looking around, it was like, “well, shoot, I have all these open source projects, and I really want to easily generate API documentation for them. And I’ve got this static generator I’ve been working on, you know, what’s an open source developer to do?” And the answer is, you know, always, “I’ll make a new open source project,” until you’ve got, you know, 10 of those on the backburner that you’re never going to get to. Thankfully, I got to this one, and now it’s available for your use.
Jamie
Dave
Jamie
Dave
So Statiq has modules that help with that, too. There’s one particularly powerful module, whose entire job is to shell out and start a new process. And then either let it run, or watch it, or wait for it to send information back. That acts as kind of a glue between what’s going on inside your .NET app that’s running Statiq, and the rest of the universe. So we have users who, for example, use that to launch webpack when they start to build their website, or launch tailwind the tailwind compiler, or you can launch whatever arbitrary stuff you want to launch with that.
So with that piece as glue, you could see a world where you go off and launch some semantic analysis tool, and maybe you even find one in the .NET world; maybe there’s an assembly out there on NuGet that knows how to read and parse, say, Ruby code and can spit out a semantic model for you to use. However you get it, the first step is getting that semantic model, right? So Statiq helps in that sense by kind of providing the the framework in which you can make that work happen in the right order.
And so once you’ve got that semantic model, now, the second part of that problem is, “how do I spit HTML out from that?” So the theme that Statiq Docks ships with is sort of heavily dependent on Roslyn’s view of the world. It essentially has a bunch of razor files that take the static representation of the symbols that Roslyn produces for .NET code, and turns them into bits on the page. So that you have this beautiful API documentation that lists your symbols and your methods and your properties and the documentation for that. So any effort to document some other language would need to have a different set of layout files that are kind of appropriate for the kind of information that that semantic analysis piece produces.
So that’s how you would glue things together. Now, the good news is that doing that kind of gluing together and making those kinds of completely arbitrary, “we never would have thought of it ourselves,” sorts of things happen within your static generator, is exactly what Statiq was built to enable. So I would venture to say that to do that would take some work, but the work you’re doing would be almost entirely focused on that specific problem: parsing and analyzing JavaScript code and producing a good theme and output from it. And not at all on the problem of, “how do I fit this into my static generation process?” Which if you were to do it in pretty much any other static generator, that second part, which Statiq kind of removes from you, by making it easy, would be a good chunk of your effort trying to figure out well, “how do I get Eleventy to go out and run this arbitrary code that reads JavaScript and analyzes it and produces output that I can then use in my layout? " You know, I would have no idea where to begin with that. I’m sure there’s some Eleventy wizards who could figure it out. But Sadek is designed specifically to answer those kinds of questions.
Jamie
Dave
A great example of this kind of thing: there are several open issues that I just haven’t gotten to yet to do something similar for Swagger - or I guess now, it’s Open API documentation - to look through a set of endpoints or a Open API spec, and produce statically generate a nice web site that that documents that Open API spec. That’s a perfect example of where Statiq kind of comes in and is ideal for that job. And once that work happens, once that the code is written to create a module that can read an Open API spec and produce appropriate Statiq documents for that, and a theme is written that can take those documents and turn them into nice looking HTML, that then becomes available for everyone. So that yeah, that’s the dream. That’s the hope. So yeah, I mean, having Statiq document other kinds of programmatic artifacts is definitely sort of in the realm of things we think about.
Jamie
Dave
Jamie
But yeah, that’s that’s whet the listeners appetite and come back to that as another conversation if you’re interested.
Dave
Jamie
Dave
Jamie
Dave
Jamie
Dave
Jamie
Well, thank you ever so much for being on the show, Dave. It’s been a real pleasure to talk to you. And I know, I’ve learned a whole bunch of stuff. I’m sure the listeners will do. So. Thank you very much.
Dave
Jamie
Wrapping Up
That was my interview with Dave Glick. Be sure to check out the show notes for a bunch of links to some of the stuff that we covered, and full transcription of the interview. The show notes, as always, can be found at dotnetcore.show, and there will be a link directly to them in your podcatcher.
And don’t forget to spread the word, leave a rating or review on your podcatcher of choice - head over to dotnetcore.show/review for ways to do that - reach out via our contact page, and to come back next time for more .NET goodness.
I will see you again real soon. See you later folks.
Useful Links
- Statiq
- JAM Stack
- Cake Build
- BAM Stack
- Headless CMSs:
- Examples of statically generated websites:
- Connecting with Dave:
- @DaveAGlick on Twitter
- DaveAGlick on GitHub