452: JavaScript and Bundlers, Dave and Vite, Stale Tab Reloading, and Consultants Who Can’t Deliver

JavaScript and next gen bundlers, Dave's experience using Vite, what are your expectations with stale browser tabs, and what can you do when consultants don't seem to be able to deliver on a project?

Tags

, ,

Guests

Chris Coyier and Dave Rupert in silly sunglasses and a sign that says Shawp Tawlkk Shough DOT COM

Chris Coyier and Dave Rupert

This episode is with just Chris & Dave, ShopTalk Show's hosts. Chris is the co-founder of CodePen and creator of CSS-Tricks, and Dave is lead developer at Paravel.

Time Jump Links

  • 01:53 JavaScript in 2021 - next gen bundlers
  • 15:55 Sponsor: Deque
  • 19:35 Does Vite combine files?
  • 31:45 Sponsor: WooCommerce
  • 34:27 Dave + Vite experience
  • 47:15 Does a stale tab reloading suck?
  • 52:26 Consultants not being able to deliver

Episode Sponsors ๐Ÿงก

Transcript

[Banjo music]

MANTRA: Just Build Websites!

Dave Rupert: Hey there, Shop-o-maniacs. You're listening to another episode of the ShopTalk Show. I'm Dave--in the shed. I had power all week--Rupert and with me is Chris--in the booth--Coyier.

Chris Coyier: Yeah.

Dave: Hey, Chris.

Chris: I feel good for you. You went through some garbage times there in Austin for a minute and it's nice. Is it 60 degrees yet?

Dave: It's like 80. It's ridiculous. It went from 7 degrees to 77 degrees in a few days.

Chris: That's unprecedented.

Dave: Yeah.

Chris: Crazy times.

Dave: Crazy times but, hey, I'm in the shed. I got ethernet wired up now.

Chris: You do?!

Dave: Yeah, so I'm cooking at 800 megabits up and down. It feels pretty good. Latency solved for the rest of my adult life, hopefully.

Chris: Yeah. If you asked me 10 years, 20 years ago (probably even less), "Are we still going to be wiring up our Internet?" I'd be like, "No way. Definitely, wi-fi will beat ethernet.

Dave: Yeah. However--

Chris: Nope.

Dave: However, no. Unless you can physically see the router, you're in danger. That's what I've learned in my adult life. Unless you could see that thing, you're in danger of losing signal and sounding stupid on a call.

Chris: Yeah, there should be a sign like they have on semi-trucks on the highway. If you can't see his mirrors, he can't see you.

Dave: Yeah.

Chris: I guess that sounds slightly sexist, but you've got to pick one or the other.

Okay, so we're going to talk. We've been talking about JavaScript in 2021.

Dave: Yeah.

Chris: It feels like in the water anyway, but I like it. I think it's been fun.

Dave: Yeah. I think every day I realize, "Oh! I was doing things the two years ago way [laughter] and that's so obsolete."

Chris: [Laughter]

Dave: I feel like even now it's still changing under my feet.

Chris: Yeah, totally. There are literal differences than a couple of years ago, which is cool.

Dave: Yeah, kind of recapping so far, I think the big thing is no IE, right? That takes off a lot of Polyfilling. That takes up a lot of budling and packing and even just how you import things.

Chris: Right.

Dave: It's less of a deal, right?

Chris: Yeah, it's causing some big reevaluations like do I even really need Babble on this thing? People are like, "Well, yeah, I do. Of course, because that's the thing that does my JSX."

Then they're like, "Well, that's weird. Maybe we should just process that some other way then." "Maybe we'll do the thing where we make the two packages: the old package and the new package." All these conversations are happening.

If you are fortunate enough to work on a very modern project, you might not need nothing at all. You might be just rocking and rolling.... Everybody I talk to is feeling that in some way. It's no IE, but plus ES6+.

Dave: Yeah. Yeah, the language evolution has been pretty good, so there are a lot of features. I think modules have to be the hugest thing, right?

Chris: If not async/await.

Dave: Async/await, I'm using that all the time now. Yeah, I don't know.

00:03:43

Chris: Yeah, tremendous. The language evolves in ways that is not just like, that's a little syntactic sugar. It kind of felt that way at first and now it's like, "Oops. Accidentally, that transformed the whole landscape so, wow." But there are all these little bits and pieces.

A couple of episodes ago, we had Fred and Jason on from Snowpack, Skypack, Preact, WMR, respectively, kind of thing to talk next-gen bundlers. That's what I called them. Then I did a little tweetstorm just to solidify my thoughts on what's a variety of things that you might put under the umbrella of JavaScript in 2021.

Dave: Mm-hmm.

Chris: The first one in that thread, I called them "The Next-Gen Bundlers are Here," and then I was like, I wonder if that was a wrong way to classify these things or what. Let's explore a little bit.

Webpack is a bundler. They say the word bundle on the homepage.

Dave: Yeah. Yeah.

Chris: Rollup and Parcel also do. Even esbuild, everybody's fancy boy these days--

Dave: Mm-hmm.

Chris: --calls itself a bundler. That's interesting. That's four things that literally refer to themselves as bundlers. I know they're all very different - in a way. But not quite prepared to talk about all the little differences there.

But then what I think of as next-gen bundlers are next-gen are the two that we talked about from that show: Snowpack and WMR. Then Vite, I believe, is the correct way to say it. Now, if you go to that homepage of Vite, it says it's for the French word "fast" or something. Then I put it into the Google Translate and had them pronounce it. It said "veet."

Dave: Okay.

Chris: I believe that's correct, although on the homepage it says it's pronounced V-I-T, which to me very much is "vit."

Dave: "Vit." Yeah, yeah.

Chris: In my head, forever, it was "vite."

Dave: Uh-huh.

Chris: All those are wrong. It's "veet."

Dave: "Veet" like yeet, like I'm just going to yeet this code. [Laughter] I'm going to "veet" this code.

Chris: I think of Veep, the show.

Dave: Oh, Veep.

Chris: But, sure. Yeah, Veep.

Dave: Okay. Okay.

00:05:45

Chris: [Laughter] Whatever. Vite. Okay, Snowpack calls itself a build tool. WMR calls itself a development tool. Vite calls itself front-end tooling. Tool is the word of these new ones, not so much bundler.

Dave: Okay. Okay.

Chris: Interesting. Interesting. I don't know what to think of all that, but I just thought that it was interesting that that has evolved, too, like the name of these, even though some of the jobs they do are different. It got me thinking about jobs they do.

Dave: Mm-hmm.

Chris: What are the jobs they do of tools like this? That's part of the opinionated stack of what these things choose to do and choose not to do. It's so fascinating what we have come to ask and expect of a tool like this, or a bundler, or whatever.

The word "bundle," I'm going to through them all really quick and then we'll back up. Maybe I missed some.

Dave: Cool. Cool.

Chris: Then we'll go into them. They combine stuff. They do the bundling. That might mean your code, but it also means stuff from NPM.

Dave: Mm-hmm. Mm-hmm.

Chris: But the trust on these things is like, please prepare all this code that I'm authoring for production. I need something that does all the work, that produces files that I know I can trust in production. That's kind of what we're asking from a bundler.

Dave: Small files not broken.

Chris: Yeah.

Dave: Smaller files not broken.

Chris: Yeah, do a good job. Not broken is huge.

Dave: Minified, I guess. Not small. Never small, but minified.

Chris: No. But, yeah, even minification is interesting because that's part of preparing a file for production, right? It would be like a source map. I expect that out of these tools. That's what I need to ship to production, so please make it for me. In the case of a source map, maybe.

Dave: Tree shaking might be in there.

Chris: Tree shaking is interesting because that's the one that removes dead code.

Dave: I don't want all of Lodash. I just want whatever.

Chris: Right.

Dave: [Indiscernible]

Chris: Who knows? Lodash is the perfect example because it's intended to be tree shaken, in a way. But I don't know. How much of React gets tree shaken out when you write it? I have no idea, but some or none? I don't know.

Then think of the 500 other libraries that your project probably uses. There's probably quite a bit of that going on.

Dave: Mm-hmm.

Chris: Then there's the fact that you have this tool and you're writing code in it that's intended for production, but it's also your development tool. You're also asking of this thing, "As I write code, you're running too. You're my partner in creating this website. You should be the Web server." That's become an expectation that your bundler is also your Web server. Very weird, but that's often the case.

Dave: Do you associate that with the old stuff or is that kind of in the new stuff?

Chris: I don't know. I think it's both.

Dave: I kind of put it in the new stuff.

Chris: It would be weird to be a bundler. You do?

Dave: I don't know. Webpack, I don't. I suppose you could install the right plugin or whatever, but I don't think of it as spinning up my local Node server.

Chris: It does, though. It totally does.

Dave: I thought it just spun up its own. That's what it is in my brain.

Chris: Oh, yeah. It spins up its own. Yeah, I guess that's what I mean.

Dave: I have to open a new terminal tab and type Webpack blah-blah, and it'll just start crunching that file.

Chris: Right, but you don't also use that like localhost 111 or something.

Dave: No.

Chris: You haven't taught Webpack to be that server.

Dave: No.

Chris: Yeah, because the problem is you use it. Something like Nuxt might use Webpack under the hood. I don't know if it does or not.

Dave: Yeah, I think Nuxt.

Chris: It probably uses Rollup.

Dave: Gatsby is kind of just a glorified Webpack file.

Chris: But they have their own server or something in it, so you think of that thing as the thing that's providing the server. But under the hood, it's probably whatever the bundler is.

Dave: Okay. Okay. Well, all right.

Chris: But it depends. I mean I use Webpack in the context of Rails, and Webpack server is running, crunching files, but it's Rails that's being the Web server.

Dave: Yeah.

Chris: You need something to be the Web server, and you kind of want it to be because if it's the Web server, then it can do other intelligent stuff like hot module reloading. If something else was the Web server, it wouldn't know when to do that and when to refresh and when to inject new code and stuff. You kind of want it involved with being the Web server locally. I don't know that anybody uses the Webpack server on production to serve the thing.

Dave: No. Hopefully not. Yeah, please don't.

Chris: Probably not.

Dave: Yeah.

00:10:08

Chris: But you want that to be fast, too. Now, you're trusting it. You're trusting this bundler for your production. That's why you're using it in the first place, but it's also become your development experience, too. You're trusting it on both sides of that equation.

Dave: Mm-hmm.

Chris: So, tree shaking. Then because it's your dev server and it's where all this processing is happening of JavaScript (because largely we're talking about JavaScript) people are like, "It should do everything." If I'm going to write in Sass, whatever my bundler is, I don't want to be totally on my own to figure out how to process my Sass or my TypeScript or my CSS modules or my JSX or whatever, too. I should be able to teach this bundler about anything I want to process.

Dave: Mm-hmm. Mm-hmm.

Chris: Anything. That should be part of the game, too. So, we have ESM or even fake ESM for Node modules and stuff. But you can't import a CSS file into a JavaScript file even though every Webpack tutorial you look at will do that.

Dave: Yeah.

Chris: That's a fake, invented thing that bundlers do. Now, bundlers are like, "Okay, well, that's your job, too. You should be able to deal with images. You should be able to deal with SVG if you need to. You should be able to deal with CSS." That's kind of an expectation of a bundler, too.

Holy crap! That list of stuff that it's doing is a big deal. Not to mention that it has to finger its way through your files to do this work.

Dave: Yeah.

Chris: It's also like an AST thing, or whatever. It's got to figure out how to do all this work. The jobs that it has are a lot, but that's not to say that every tool needs to do all these things. That's kind of what's changing, I think, is that not all of them do that, for example. The minification, for example. Webpack can do that and often does, but you look at a configuration and be like, "Oh, it's using the Terser Webpack plugin." Well, Terser isn't Webpack. That's not the same team.

Dave: Mm-hmm.

Chris: Terser is its own thing. It's bundled all together. You'll often see them together, just like you might see Tailwind and Purged CSS together, but they're not the same. They're not the same project. They just happen to use each other.

Dave: Yeah, they're siblings. Then Terser just uses whatever hooks Webpack provides to just run at the right time.

Chris: Yeah.

Dave: Yeah.

Chris: Then you look at WMR. It has this list of opinionated stuff it does. One of them is not tree shaking. I don't know if it does tree shaking or if that's just implied or what, but you don't see that word anywhere on the document. Then you're like, "Did it just punt on it, or does that not matter anymore or what?"

Dave: Yeah. I wonder. I assume it does in the build process. It says, "A highly optimized Rollup build production," so it uses Rollup.

Chris: So, Rollup, and Rollup does the three shaking.

00:13:10

Dave: Yeah, it uses Rollup to build it behind the scenes. But that's where these things get weird. It's just like a server. I guess I can skip ahead. I don't know. I was using Vite yesterday, last night, writing Vue files.

Chris: Okay.

Dave: Just in a directory, and I'm typing vite-serve, or whatever, or NPM run.

Chris: Okay, so it's got a Web server.

Dave: It's got a Web server, but it's like--

Chris: Does hot module reloading.

Dave: Hot module reloading and it's really fast. It's because of the esbuild is all built into there, right? That's using esbuild. I didn't realize other stuff was slow, but I'm realizing, oh, this is very fast. The same, I think, with WMR. It's like, oh, this is actually fast.

But what I think these tools are kind of doing is they're kind of doing on-the-fly translations. It knows about your -- it says, "Oh, okay, they're authoring in some kind of file that I need to watch, and then I'll transpile it and then I'll hot module reload." It's interesting.

Chris: Yeah.

Dave: It's like even back to that whole quintessential example. Import foo from foo is not JavaScript. That's Node. That's not ES imports.

Chris: Yeah. I wonder if Vite is doing this too, but I know that Snowpack and WMR are like, "Okay, you've imported Vue. I'm not going to do that again."

Dave: Right.

Chris: "I've already done this once.

Dave: I've done this, so--

Chris: Webpack will not. It's going to pull that again and it's going to combine it all together and it's going to do whatever it needs to do every time you hit command-S. I think that's kind of a core innovation of these other tools is that it's like, "Oh, no. I already have that copy. I've already done what I'm going to do for that."

Dave: Yeah.

Chris: Maybe in production, I'll bundle it all together, but while we're here in dev, I'm not going to do that. I've already done it.

Dave: I'm only changing the ones we already were using.

Chris: Mm-hmm.

Dave: Like that were on the page. So, I've kind of seen them more as these, like, on the fly translation layers. I don't know if you read Hitchhiker's Guide, but the Babel fish.

Chris: Sure.

Dave: For me, it's like Babel fish. It's just like, you write however you want and these things figure out how to do it as fast as possible to make it into something you can see, which is different. It's slightly different than, like, "Give me all your files and then I'm going to crunch them through my big Rube Goldberg machine. This is more like, "What are you working on, buddy? Cool, I'll just fix that for you and shove it over to the browser." Okay, great. "What's the next thing?" It's a different world, so I don't know.

00:15:55

[Banjo music starts]

Chris: This episode of ShopTalk Show is brought to you by axe-con 2021, a free digital (online, of course) accessibility conference.

Dave: From our friends at Deque, the makers of the popular Axe browser extension, comes an open and inclusive digital accessibility conference welcoming developers, designers, business leaders, and professionals of all levels to a unique event focused on building, testing, and maintaining accessible digital experiences.

Chris: Yeah, that's a lot, but it's pretty sweet. I've been using the Axe browser extension a lot and it's tremendous in what it can do. Axe-con, the conference, has amazing speakers like: Vint Cerf, widely known as The Father of the Internet; Rachel Andrew, known as The Mother of the Internet -- just kidding. To me, she is. Noted Web developer and former editor at Smashing Magazine, Rachel is; Val Head, speaker, author, design advocate at Adobe; Sara Soueidan, renowned speaker and UI engineer. Maybe other than Vint, all those people have been on the show, right?

Dave: Oh, yeah.

Chris: Who else is [clears throat] going to be there?

Dave: It's your boy!

[Laughter]

Dave: I'm going to be talking. I'm going to be talking about backlogs and how we can turn an accessibility backlog into actual accessibility stuff. There are so many other amazing people. I'm going to call out Angela Hooker (who I work with from time-to-time) at Microsoft. She's really amazing. I've listened to her talk about alt tags for like an hour and it was just inspiring. Denis Boudreau over at Deque, amazing accessibility person, very involved. Jamie Knight + Lion, Jamie works at BBC, but brings a diversity perspective to things. There are so many good people. Elle Waters has been on the show, I believe. Eric Bailey, who basically does the accessibility project, so Eric is just top-notch.

There are so many other people. I am just scrolling through the site. You want to go. They have a whole dedicated developer track. It's for us. It's for people like us.

Chris: Yeah. Right. By a company that obviously has all their chips in the game here, so look to see what they have to say, too. They're the perfect people to be throwing this conference, so that's pretty exciting. Yeah.

I don't know. I don't know. I'm just stoked. I want to be there for yours, though, turning into actionable stuff. The plugin helps with that because it's like, "Here's an issue. I've taken this guided tour. You should tell me what I should do."

Dave: Well, yeah, so I was going to say -- sorry. [Laughter] This is turning into a whole segment. Segun Ola is going to talk about integrating stuff into your dev tools. That's if I understand his talk title and stuff correct, I abstract correctly but there's going to be good stuff, like how you bring this stuff into your dev tooling process.

Chris: That's the number one thing I care about. When? When are we doing this?

Dave: Okay. Join us March 10th and 11th for this conference. Register for free at deque.com/axe-con.

Chris: I'm sorry. This is free? Okay.

Dave: Free. It's too good. Accessibility is that important.

Chris: A little too good.

Dave: You should show up. Yeah. can't wait to see you there. Hopefully, you come to my talk.

Chris: Okay. Okay. See you there. Bye-bye.

[Banjo music stops]

00:19:41

Chris: Now, I covered all the expectations and you say you're using Vite for a little thing.

Dave: Yep. Yep.

Chris: "Veetae" -- [Laughter] Sorry. Okay. Does it combine files? Yes, probably.

Dave: Yes. Here. I could tell you what it does exactly, but there is also a build step and so that build step produces little hashed files.

Chris: Okay, so you've seen -- this is probably a different story for dev in production or not? Is it just like, "Meh. We're so fast, I'm just going to do the same thing for both"?

Dave: Different story for dev and production.

Chris: There is. Okay.

Dave: Then, let's see -- run dev. I'm going to start--

Chris: It supports pulling stuff from NPM and doing whatever it's going to do and combining your code too. It's funny that we refer to it as third-party code and first-party code. What is second-party code?

Dave: I don't know.

Chris: Does anybody ever talk about it? All right.

Dave: Your best friend is--

Chris: Yeah, your colleagues. When somebody is talking about your code. I don't know.

Yeah, it's really confusing. I'll just say it's confusing because, again, browsers -- this is another thing where everything gets kind of mixed up for me. Browsers do a really good job because it hands it to source map. When I look in my browser, guess what I see. I just see Vue files because my browser tooling is now intercepting.

Chris: Yeah, that's incredible. If you have a problem on line seven, even your browser is going to tell you, in your Vue file, which it is definitely not interpreting itself.

Dave: Mm-hmm.

Chris: The problem is on line seven.

Dave: Yeah.

Chris: Okay, that's incredible.

Dave: Yeah, and so, like, I'm writing a Vue file and it says, "Okay. Cool. Here's your Vue file." It's just kind of different. I wish I--

Chris: That's another thing we'll throw on the pile is this error handling experience. We want that. We're asking that from our tooling.

Dave: I think browser tools factor into this as well. You can read the source a lot easier, and that's just a different -- I don't know. That's a different world.

Chris: Mm-hmm.

Dave: I have -- let me see how many JavaScript files come through. [Counting] Nine different JavaScript files. Maybe there's one plugin there. But it's like two Vue files, three Vue files, four Vue files and I think that's hot module reloading - or something like that.

Chris: Hmm. Okay.

Dave: But you know it's not like this intense load here that I'm seeing.

Chris: Does it do the NPM thing? Pull stuff third-party, yes.

Dave: Yes.

Chris: Because it's built for Vue and all that stuff.

Dave: Yeah. Yeah.

Chris: Does it do TypeScript? Yes.

Dave: Yes, it would.

Chris: It does other processing, too. It doesn't say anything about Sass, it looks like, but it will do CSS modules and it will do that special kind of importing of raw vanilla CSS and JavaScript files, which is so bizarre to me. I never got into that, but that's a thing.

Dave: Yeah, I think Vite uses plugins kind of in the spirit of, like--

Chris: Rollup or whatever.

Dave: Yeah. Just like, "Hey, you're using JSX. Use the JSX plugin." I think they actually maybe require you to append .jsx to your files instead of JS.

Chris: Mm-hmm. Okay.

Dave: Just because they can efficiently hand that off to the JSX transpiler.

Chris: It's doing that thing where, whatever you need to process, it will help you process it.

Dave: Right.

Chris: It makes optimized build, so of course it's doing minification and stuff. Certainly, like all the rest of these, it reaches out to some third-party tool to do that. It probably is not its own minifier. But okay.

I have no idea about the tree shaking. I never hear that word anymore. Does it do that or not do that?

Then there's this thing that you always heard in conjunction with tree shaking, which was code-splitting because, when you code split, it might be a file on your about page that needs some code that your homepage doesn't. It will tree shake out the things that aren't used one route to another. That seems like a big deal.

That was talked about a lot was this, like, I'm going to make two different bundles: one for this area of the site and one for this other area of the site. Not only that, but this bundler is going to assume that you might be building some kind of single-page app so that when you navigate to that other page, it's going to load that additional bundle.

Now, what's loading that additional bundle? Some network request surely must happen, right? Your bundles have in it like fetch code.

Dave: Mm-hmm.

Chris: They can do that. Who wrote that? You didn't. Some plugin didn't. Your bundler wrote it.

Dave: Yeah.

Chris: Webpack or whatever wrote/injected some special fetch code stuff in it that does that, which is fascinating to me, but that's a thing that it's doing for you that's on this pile, huge haystack of crap that the front-end tooling does for you. [Laughter]

Dave: Yeah, like some kind of dynamic import structure tree. I know they're trying to standardize that, maybe, like import maps. That's a little different. That's where you have named imports or something like that.

00:25:21

Chris: That's interesting, though, isn't it? I wonder if these tools can get dumber because the language gets smarter. For example, I know that was kind of the core innovation, perhaps, of Webpack was that it's spidering through your codebase to find all the crap that it needs to import. It's tricky business, and it could do all that. Cool, right? You don't have to teach it every last file you want to be combined in all that.

Think of a Grunt build or whatever. You had to be like, "Put jQuery and combine it with my index.js file and squish it together." You had to be really explicit that you wanted that to happen.

Dave: Do these in this order.

Chris: Yeah. With Webpack it was like, "I don't know. Just spider through my site and figure out what you need to do." That's how all of them work these days.

Dave: Mm-hmm. Mm-hmm.

Chris: Literally, everything does that. It just looks at your code and it figures out what it needs to do from your code rather than configuration. Well, that's not so amazing anymore if you just say, "Well, do that, but only do that with language features. Do it with ESM. Do it with native CSS imports - whatever. Only do what the language itself supports. Don't try to be fancy on top of that."

I don't think we're there yet. It looks like even Vite, as fancy and new as it is, says, "Oh, we support these kind of like non-standard import things because we know you want them, and so we're going to do that," so it has to have some fancy stuff built in. It looks like it's pretty opinionated about what it supports.

Dave: Yeah, that's like -- maybe we can get somebody on here to talk about that. That's sort of like JSX is not part of the platform but then people were like, "Well, we better support JSX. Everyone is using it, so we've got to do that." You know?

It's just interesting. Something gets popular enough, it's not a standard by any means, but then the concern becomes big enough that any new tool that shows up has to support the old one. You know?

Chris: Yeah. Right.

Dave: Too big to fail, kind of vibes, right?

Chris: That's kind of like hot module reloading is like that. It just has to have that. I don't know what's required to make that work, but nobody is going to work with a new bundler that doesn't have that.

Dave: Mm-hmm.

Chris: That would be nuts.

Dave: That's definitely nuts.

Chris: You need to have that fast experience, and it needs to have great error handling, so I know exactly what's going on and where. Hopefully, it looks beautiful in my browser when things error and I can see what file it's on - blah-blah-blah.

00:27:51

Dave: That said, I traded MacRabbit, the CSS styles. What is the app, the old MacRabbit app where you just like--

Chris: Oh!

Dave: --hot code styles in your app?

Chris: It's just called CSS something, wasn't it? It had the word CSS in the title. What was that? That's funny. That was hot. Yeah, people really liked that.

Dave: There was Espresso, but--

Chris: Then CodePen came along and be like, "We--"

Dave: [Laughter] "We do that now." Oh, my gosh. CSS Edit is what it was called.

Chris: Maybe it was Espresso.

Dave: CSS Edit.

Chris: Oh, CSS Edit. I knew it had CSS in the name.

Dave: Yeah, yeah. Espresso was the code editor. It was like this dedicated CSS authoring app back in the early 2000s or something. You would just type your CSS. It would hot reload it, like library load it on the page inside this little window and spit out a whole new webpage you could just author CSS really, really fast. But then Sass came along and it didn't support Sass, of course.

Chris: Right.

Dave: But I was like, I want those variables. So, I did trade for something slower and not as good and didn't library load. Eventually, I got those features, but I did trade it for--

Chris: Yeah. Very good point.

Dave: But I would also go back to MacRabbit if it existed because that was hell-a cool. I don't know, man. It was so good. Such a beautiful--

Chris: Yeah, I'm looking at it now. You can even buy Espresso, still, which has some of those features in it.

Dave: Oh, yeah.

Chris: It looks like Webflow, like a MacOS Webflow where you click text and you're like, "Oh, well, here's UI to change the text to small caps. It's a button and you press it. [Laughter]

Dave: Heck, yeah.

Chris: You know? Just different ballgame. Anyway, I thought I'd talk about it.

Back to Vite for one second. Does it do tree shaking and code-splitting? I have no idea. We'll get Evan on to talk about that. But maybe.

But it certainly has a Web server. It certainly does hot module reloading. It certainly handles other kinds of imports. It has a plugin system. It's new, so that will probably evolve over time.

But then it has this -- you know, you can still trust it. It's still saying, "Will produce great production code for you out of it. Don't worry about that. And we've got you on the flipside, too. It's super-fast and the DX of it is super good."

We kind of do ask a lot of these tools. It's very interesting.

Dave: Yeah. Yeah.

Chris: Very interesting, and so what happens in this, you can almost predict the next generation beyond this because you look at this list and the list doesn't actually change that much. It's just like, what are we going to break off because we don't need to do it anymore? What are we going to trust some other tool to do? It's like we need less because the language evolves or our developer tastes evolve, or whatever.

Maybe we won't need a dev server anymore because browsers are just like--I don't know--"Just point at your index.html file and use ES Modules for everything. We'll be really fast at refreshing." Maybe command-R gets so fast in browsers that you don't need hot module reloading or a dev server at all.

Dave: Yeah. There's something to be said. Hot module reloading is very nice when your bundle is one megabyte of JavaScript. But when it's 8,000 or 4,000 or something, refreshing is usually just fine. Yeah, if more features -- I don't know. Maybe bundles get smaller. Maybe -- I don't know.

Chris: I don't know. Maybe you don't have to bundle at all. That's starting to be part of the story, too.

Dave: Yeah.

Chris: Yeah, minification matters less because browsers -- you put your site in front of Cloudflare, and maybe you just start trusting the CDN layer--

Dave: Mm-hmm.

Chris: --to handle all your minification and all that stuff. Why does it have to be a part of a build process if Cloudflare is in front of it anyway?

Dave: Right. Right.

00:31:45

[Banjo music starts]

Chris: This episode of ShopTalk Show is brought to you in part by WooCommerce. WooCommerce is e-commerce plugin for WordPress, so you install it on your self-hosted WordPress site and you've got e-commerce going. It's the e-commerce that powers the e-commerce behind WordPress.com and, such as well, it is a hugely battle-tested software.

You know the statistics for WordPress are wild. It powers like over a third of the Internet, which is a hard thing to wrap your mind around. At least it is for me. But the statistics behind WooCommerce are similar. It's super dominant in the e-commerce space, so you know this is big-time software that you can trust.

It comes from the Automattic team itself, just like WordPress.com. They have a ton of developers behind WordPress itself and all that.

It's free, like WordPress is itself. It's open-source. You can just use it. You can do most anything you'd want to do with WooCommerce for free.

Its business model, though, is that they make, WooCommerce themselves make tons of plugins that are paid that extend the functionality to do advanced things that you'd want to do. For example, let's say you make something and you sell it. You can pull that off on WooCommerce using free stuff. They even have a shipping plugin that's an add-on for WooCommerce. That's free. That allows you to print out shipping labels and all that.

Let's say you're running a fairly complicated shipping situation, like, "I need to add weights for all my product. Then this combination of products exceeds this level of weight. It needs to have this price associated with it, but it's discounted if they go over this thing. Then it costs more if it's in this particular distance away from where I'm shipping it, and all that." Very complicated stuff.

They have a plugin called Table Rate Shipping. It handles all that and it's not some third-party thing that who knows if they're going to keep up - whatever. It comes from WooCommerce themselves. It's called Table Rate Shipping. It costs $99 a year. If you're at the level of business where that's what's going on with your shipping situation, $100, I'm sure, is very much within the cost of doing business for you - I hope.

I had a product one time, or I was selling through a company and the company didn't care about the fact that I was using WooCommerce or WordPress or anything, but they're just like, "I don't know. We ship our stuff with Ship Station." That's the industry standard for what they were doing. There is a plugin by WooCommerce for Ship Station, and so they didn't care how I sold these T-shirts, but the fact is that the order went to Ship Station meant that they could fulfill it and everything was hunky-dory. They didn't care about my side. They just cared that it worked with Ship Station. That's been true a number of times for me.

WooCommerce, great software. I just wanted to, you know, tell you about it. Tell you about a little bit. Thanks for the support.

[Banjo music stops]

00:34:45

Chris: Anyway, interesting stuff. JavaScript in 2021, just kind of wanted to think that through a bunch more. I should ask you about your personal experience a bit more. Is it Vite? Are you feeling it?

Dave: I like it. Yeah.

Chris: Do you feel productive?

Dave: I bit off two things, two pieces of technology: Vite, because I just was like, whatever. We're in the Discord. Discord is chatting it up. Plug the Discord here. Cha-ching. Cha-ching.

Chris: That's our Patreon and it's going awesomely. I love everybody in there. It's awesome.

Dave: It's fun.

Chris: Join us.

Dave: Lots of talk about your hands hurting, if you're into that. [Laughter] Different build tools and stuff.

Anyway, I was going to say, people were talking about bundlers and stuff like that in there.

Chris: Yeah.

Dave: I just was like, oh, I'm going to just have something to use Vite on. I can spoil it. I don't even know if I'm ever going to release this, but it's called RSS Tester. That's what I'm calling it now. It's basically just a little app where you can put the RSS feed in and view it in a fake RSS reader. It's just this idea of, like, "Oh, what's my RSS feed look like? Is it just trashed or what?"

Chris: Mm-hmm. Mm-hmm.

Dave: Just kind of a quick way to, like, spot-check this. I might not release it. I am having fun with it. I'm going to keep it. I'll probably keep building features. I might not release it because it dangerously sets HTML or whatever.

Chris: How are you parsing the XML? jQuery?

Dave: [Laughter] Here's something I learned. You know CORS Anywhere, everybody's favorite website?

Chris: Yeah.

Dave: That doesn't work anymore.

Chris: Seventy-five percent of the time, yeah. Ooh, it's down to zero percent of the time.

Dave: Zero percent of the time because they capped everything. They basically cut it out. They turned off every--

Chris: Yeah.

Dave: They basically turned on CORS, I guess. [Laughter]

Chris: Oh, that's too bad. What did you do, write a little Netlify...?

Dave: Now I have a function and I'm running this little Node app called RSS Parser, which turns an XML feed into JSON back.

Chris: What?!

Dave: Yeah! So, it's pretty cool.

Chris: What does that? Well, so then can you trust it, really? What if something happens in that conversion process that makes your feel look safe but really it's not?

Dave: I don't know. Yeah.

Chris: [Laughter] Sorry.

Dave: I haven't gotten that far, Chris.

Chris: [Indiscernible]

Dave: That's why I'll probably never release it because, immediately, somebody is going to be like, "I read a blog post that had an XML injection," or whatever script injection.

Chris: Yeah.

Dave: "Your site rendered the script injection." It's like, well, cool. You got me, man. I don't know. [Laughter] I don't know.

There's new browser stuff coming out, like the sanitize API. Have you seen that?

Chris: No.

Dave: There are features for sanitizing HTML and content and stuff like that.

Chris: That's nice.

Dave: I could, in theory, sanitize this stuff maybe easier and just make sure that nothing -- I don't know. Even that, though. You turn on the sanitizer and then it breaks Unicode. You know what I mean? It's just a bummer.

00:38:09

Chris: Yeah. I had to write some sanitization code this week, so there you have it. I used a gem that was good and did most of what I wanted, but it did too much and too little.

Dave: Yeah.

Chris: It was one of those things where it stripped some crap it shouldn't and didn't strip some other stuff that it should. I was like, "Oh, my god!" [Heavy breathing]

Dave: Yeah. Now all angle brackets come out as >: you know.

Chris: Yeah. Even that, I would have been like, "Fine." But, actually, that would have been just as obnoxious. Oh, I had a thought, though. Oh, I had to write -- I still have some production code on CSS-Tricks that pulls the feed, literally the XML. Then I run it through an XML parser thing. What was one of those called? It's like PHP-powered jQuery, essentially.

Dave: Okay. Okay.

Chris: Where you can load the DOM in PHP and execute selectors on it and transform it.

Dave: Yeah.

Chris: Whoof!

Dave: Very cool. Yeah.

Chris: Very cool. It's built into WordPress, so if you need an HTML and XML-y jQuery thing, it's there for you to use. I don't know how they use it internally, but that's not terribly surprising. All their hooks transform code and stuff. It loads that thing up because when you inject an image in WordPress, it puts the width and height attributes on images. Often, I'll just upload just enormous images, just 5,000 pixels wide or whatever, because I don't even care because it's going to make smaller versions of them on the fly. Even those go through a CDN to resize them and stuff. I don't care what the original is. The original should be enormous.

Dave: Mm-hmm.

Chris: But if my image is 5,000 pixels wide, the attributes on the image will say, "Width = 5,000. Height = 2,800," blah-blah-blah.

Dave: Yeah. Yeah.

Chris: Then I had that go into a feed, so that's what is output in the XML of the RSS feed. Then I would point it at MailChimp and say, "Send this as a newsletter." It would grab that image and whatever transforms it did on it would just put it in the email at 5,000 pixels wide. It was not a good scene, man.

Dave: Yeah.

Chris: That doesn't do good stuff.

Dave: I know from experience, that is just absolutely wrecking the Windows mail client.

[Laughter]

Chris: I just have this little XML parser that just finds those and, just for this feed that's intended just for MailChimp, which otherwise does the right thing, I strip those attributes and put in the medium-sized image or put in an image that's resized to be like 500 pixels wide or something that's perfect for email or something, but not if it's too small and whatever. It's just a little bit of custom code.

That makes its way into an XML file. It's on me to sometimes test that XML file and look at the output of it. I would open it up in your tool and be like, "Cool. Looks good."

Dave: Yeah. Does it even -- yeah, does it show a blog post-y kind of thing?

Chris: Did I miss a closing angle bracket, because if it does it's toast.

Dave: Yeah, so that's kind of it. You know I do silly RSS tricks and stuff like that. That's my new bog, RSS-Tricks.

[Laughter]

Dave: I just was like, you know, it would be cool to see what happens. One issue I'm running into is I use absolute URLs, like image-source=/image.jpeg.

Chris: Ooh. Yeah.

Dave: My thing doesn't do it, but Feedbin or something will. It has knowledge of a base name.

Chris: No! It fixes your crap for you?

Dave: It'll fix the URL.

Chris: That's nice.

Dave: That's interesting, too, right?

Chris: That is interesting. Does it consistently work in RSS readers or does it just happen to work in Feedbin?

Dave: I think it consistently works in RSS readers. They've negotiated the route or something.

Chris: I like that. That's good.

Dave: But again, that would be something to know. Do I need to use absolute URLs? But what's weird is when it goes to my personal site. Now that's in a CloudFront because Netlify has taken it and did a process on it too.

Chris: Yeah. Right. Oh, interesting.

Dave: Yeah. It's wild how you can author something, spit out a static site, upload that static site, and then changes happen.

Chris: Right.

Dave: Then even like your XML for your feed gets changed.

Chris: Right. Right. Right.

Dave: I don't know.

Chris: Then your workers get involved and you have this whole other layer of control way after you've built and deployed the thing.

Dave: Yeah. Yeah.

Chris: It can still be manipulated in a way. I can't remember the last -- I fixed a bug, but we had one on CodePen for a minute where Cloudflare was in front of even the -- just for a minute, was in front of the output code in a Pen. You know the little preview area? It injected this little script in there. You know Cloudflare has a bunch of these that, for example, optimizes images for mobile or something. I have no idea how it works, but it just does some kind of magic to make that experience better.

That should not probably be in your output on CodePen because then it's a child of the body and who knows what people do on CodePen. They can target body last child and have it do something important for their layout or something, and now it's not going to target this thing that they think it's going to target. It's going to target this script instead because it's been injected there.

Dave: Oh, yeah. Yeah.

Chris: You have to stop it from doing that, but that's the kind of example of something that you're like, "I can't test this in dev. I can't even write a test for it because the test will pass. It only happens in production." It's the worst kind of bug.

Dave: Those are the worst, and that's what you get. That's why you never bundle your code, kids. Never.

00:44:17

Chris: I know. Just do that. Don't even use HTTPS. I saw Remy Sharp was going off on that on Twitter the other day.

Dave: Oh, really? He's got some old man energy going right now, so. [Laughter]

Chris: It may be that--sorry, Remy--a little bit because it's not like he was arguing that HTTPS is bad. It's just that if you really fundamentally look at it, it is technically a barrier in some situations.

Dave: A lockout, yeah. Yeah.

Chris: Because some super-old browsers cannot parse the crypto that HTTPS is today. It's like a small one, but it's just like, you know, Grid Layout doesn't work in all browsers, but that doesn't break the entire website. We still talk about, like, "Well, we should write @supports rules to support these kinds of things." There is no @supports rules for HTTPS, you know?

Dave: Yeah.

Chris: It can be the ultimate shutdown. If we're going to have conversations about what if a site works with and without JavaScript, then maybe it should work with and without HTTPS also, or should it?

Dave: Okay.

Chris: That will get people fired up. Yeah.

Dave: Okay. Well, a twist. All right. Yeah, because TLS is kind of, I think, the underlying technology, like how they sign the certificates or whatever, and 1.1 is super hackable. I think we're on 1.3 or 1.4 now, or something like that.

Chris: Hmm.

Dave: If my--whatever--SSL or server is TLS 1.3, browsers--

Chris: If you use Let's Encrypt, it probably is.

Dave: Hopefully. Yeah, hopefully, it's the most secure version I can get. Then an older browser will just be like, "Dude, I don't speak this. I don't know what this crypto is."

Chris: Well, I think we're at the point where, like, IE6, which we used to all joke about--

Dave: Yeah.

Chris: Now, nobody ever mentions ever, but it was a thing for a very long time. I think we're at the point where if you loaded up a Netlify site or something, not that this is Netlify as well. They're just grabbing a Let's Encrypt and certificate.

Dave: Yeah.

Chris: It would just not load in IE6. It just would not. It would just get nothing.

Dave: For Netlify, they're protecting. It's a twist, right? You're protecting users with the best security available. It's like I installed airbags into this car. Why do you not like it? It's like, "Well, I drive an old car and we don't have airbags."

Chris: I'm the worst person to ask. I'd be like, "I completely don't care."

Dave: [Laughter]

Chris: I don't care about IE6. I don't even care if your site works, if it requires JavaScript to work. Whatever.

Dave: Where do you start caring? Tell me what version of mobile Safari you stop caring about.

Chris: I don't know.

Dave: Ten?

Chris: I hate to admit this, but some days my care-ometer is real low.

[Laughter]

Dave: That's fair.

00:47:10

Chris: [Laughter] It's like, this is a business. I'm trying to survive here. I think this is a fun question from Matthew Kreling here I have kind of saved up. "Switching back to a stale tab," meaning it's a tab you haven't seen in a couple of days--

[Laughter]

Dave: Ooh, hey. Hey, hey.

Chris: Ooh. "Chrome and Firefox seem to basically reload the website."

Dave: Mm-hmm.

Chris: Have you ever seen that? You go back to that tab and it's just like it was gone.

Dave: Yes.

Chris: The tab was there, but it hadn't even tried to load that page. "I am too lazy to provide more of a background," although, I did push Matthew on it and he made a video for me, so you're not that lazy, Matthew. "Was touted as a way to reduce load on your computer's CPU/memory. Does this suck or not?" [Laughter] "Discuss."

His little video here is just what you'd expect. He tabs back to a page that looks like it's ready to go, but it's not. It's like a GitHub repo or something, and you can see it spin. You can see the spinner in the tab. You can see the page do a white flash and it loads.

Dave: It kind of just restarts, re-hiccups.

Chris: Do you have an expectation that if a tab is open that there is something there, that it has loaded that stuff, or do you like it that the browser has decided to not do that?

Dave: So, you can either accept this new where tabs sleep. That's a new feature in Edge and Chrome, these sleeping tabs. It'll put tabs to sleep, like basically decommission the tab. You still have access to it. You can go back to it, but it goes to sleep. That may affect timers, like set timeout and stuff like that will basically crash. That's maybe what's happening on these things.

You can either accept that browsers do this, put tabs to sleep, or you have to give up your Chrome hogs too much memory jokes, or whatever. This is just how browsers are going to manage memory. Every webpage takes a certain amount of memory to load, render, and stuff like that. Every little tab takes memory to render.

Chris: Right.

Dave: If you don't want your fans to spin up just using Chrome, they have to do something to unload this memory.

Chris: Isn't it...?

Dave: I think it's a net win. It's weird and there are ways to work around those set timeout things. You can use -- what is the -- oh, window visibility API. Blah. That was a mouthful.

Chris: Oh.

Dave: But, basically, you just have to -- you can stash stuff in local storage and stuff like that too, but maybe your timer only runs when the window visibility API changes, you then reset your countdown timer or something like that. That's a feature you can use.

Chris: Um, yeah. I've seen it. I was on somebody's, Stefan something, on their page. I had their tab open for a bunch of days. Every time I came back to it, there was a screensaver on it of a little thing bouncing around.

Dave: Okay.

Chris: They implemented, "This page is idle, so I'm going to put a full-page overlay on it and animate it." I don't know if that's less memory or more, but hey, you know.

Dave: Well, I wonder how they're doing that. I wonder if there's a way to detect whether a page is idle or will be.

Chris: Right. There are probably good and bad ways.

Dave: Yeah.

00:50:45

Chris: Um, there was a tab that was super popular, every time I heard somebody mention it, called the Great Suspender. I just tried to Google it and there was a bunch of articles about Google killing it because apparently maybe it had some malware in it or something.

Dave: [Loud gasp]

Chris: But the point of that tab was this feature. It was that it would (a little bit more aggressively, perhaps) shutdown tabs that you weren't using, on purpose, to save memory. I think people -- it was rather beloved.

Dave: Yeah.

Chris: Because people like fast Chrome, you know, or fast any browser. So, I don't know. To me, it seems good. I've seen this happen a million times and never once have I went back to a tab, saw it refresh, and been somehow disappointed that it was doing that - like never. To me, it just seems like only a positive.

Dave: Yeah. No, I'm in the positive camp. It does have this weird staleness, but you know it's also browsers are trying to do a lot.

Chris: Does that mean it's not doing push notifications? How many websites are doing push notifications these days anyway?

Dave: Hopefully zero.

[Laughter]

Dave: According to Mozilla, like 99% of websites or users say, "No, don't send me." I think that's where service workers can come into play because that's a worker not on the main thread. It's happening offscreen kind of in the background. It's basically like, "Oh, if you get something for me, let me know. Then I can do something with it." It responds to inputs.

Chris: Cool.

Dave: I think they solved that problem, so you don't have to have the long pull asking for new notifications or something.

Chris: We'll do one more and then we're going to call it. Okay?

Dave: Okay. That's fine by me.

00:52:32

Chris: Jackson Bates writes in, "I work at a company with just two devs on the non-tech side of the company. We have tons of feature requests and new ideas for areas we can grow in. We bring in lots of outside agencies to help with data strategy, platform redesign, AWS infrastructure, shipping a WordPress marketing site or something, security, all that jazz. A reoccurring pattern that we are seeing is that when it comes to deliver, the consultants fairly often aren't actually capable of delivering. For example, we hired this WordPress team and they didn't know how to deploy it. They handed it over in pretty poor shape, or the cloud experts didn't seem to actually know how to change DNS records to use that stuff. Inevitably, I get pulled in to work on it and kind of clean up the mess." Jackson is wondering, "Is there any reliable methods you can think of for assessing consultants' capabilities before getting in too deep, or any other obvious tells we should be on the lookout for to spot the cowboys?" [Laughter]

Dave: Well, I hope you're not talking about Paravel, but that's fine.

[Laughter]

Dave: I think price is probably part of it.

Chris: Yeah. Did you cheap out?

Dave: Did your company cheap out? You may have to hire people who can do stuff. You can, like, proven track records, you know, like, do they appear to have shipped a bunch of products or projects?

Maybe it's something weird about your setup that's different. Sure, they didn't deploy, but is it because you have weird enterprise deployment requirements or something? That happens on our end sometimes. It's like, "Cool. Hey, here's your website. It's ready to go." They're like, "Oh, well, we can only deploy on Azure DevOps," or something, and it's really locked down. It's like, "Oh! That's a twist. Let's figure that out and maybe we'll need your help to actually get that deployment because we don't have your Azure account." That's something that happens, so it could be on y'all's end.

Chris: It could be, yeah. When you hire, don't you set expectations? Then if they fail on those expectations, there's something in the contract where they don't get paid or don't get paid as much or something. It seems like they failed at doing the thing that you hired them to do.

Dave: Yeah.

Chris: How is that--?

Dave: I mean every contract, at least we try, unless it's sort of like, "Let's just code and figure it out," kind of thing, most contracts have some kind of deliverable or you narrow down what the deliverable is.

Chris: Yeah.

Dave: Maybe you just need to be, like, "Deployed website," or try to come with -- it's hard to come up with all these things, overall, but maybe you just write a Notion doc or something of all these questions or problems you've had and then, the next time you get somebody, you just go through it and just be like, "Okay, who does this? Who does the deployment? Where does it live? Where does the project live? Who manages it? How does it deploy?"

I feel like Brad Frost has that front-end developer questionnaire. Is that what it's called? But it's basically like, "Who is doing Sass? Who manages that?" but you could build that for your consultants to fill out who handles deployment and stuff like that.

Chris: Yeah, so it's kind of on both sides, but mostly yours, to be more clear about all your requirements and ask ahead of time, "This is a requirement of this project. I'm not going to spring it on you at the end. This is what the endgame is going to look like." That way nobody is assuming anything. They either can do it or they can't. Then if they say they can and can't, then it feels more like a breach of contract rather than just like, "Oh, I thought you could do this and you couldn't."

Dave: Yeah. Well, and then maybe you just say -- hopefully, they know people. Do you know somebody who can do that, or whatever?

I too -- this is me, because it's not me, at the same time. We'll engage with people and there are cocky developers. I mean that in the nicest way possible. And more timid, like wishy-washy. I'm probably on the wishy-washy end, like, "Oh, I don't know. It depends what server, what CMS."

But then there are some people who are just like, "Oh, yeah. What? You're doing this? Sweet. We're going to knock it out of the park. We'll have a website. Boom. Yeah, we're doing it." They kind of operate on that, like, positive, less questioning, self-deprecation side of things. I think you can find those people, if you can find those people, who are just like, way too sure of themselves, almost. I think those people are great because they actually do tend to deliver a working product. Maybe do that.

Chris: Cool.

Dave: That's a good way to do it.

Chris: Mm-hmm. Yeah, that seems fair. I've had disappointing consultants, too. I have worked with some that are really slow, for example. Then I was like, "Slow? I didn't even set up a timeframe, in retrospect. So, who is slow?" I absolutely cannot blame someone for that. It's just some feeling I have even though I didn't communicate it or outline it while hiring them. That's on me, not them.

Dave: Yeah. Yeah, and that's some of it too, right? I say this as somebody who has hired as a consultant and somebody who hires consultants. It's sort of like if you don't set the expectation, maybe that's on you.

Are you doing daily standups with people to figure out stuff? What's your frequency of checking in and stuff like that? I know that's more work, but you can at least make sure the project is on track or something. There's always a million things, but--I don't know--this is the human part of Web development where it's just two humans colliding and you have to talk through your expectations.

Chris: Yeah. Fair enough. Well, thanks. Thanks, Mr. Dave.

Dave: Hey, yeah.

Chris: We're going to keep trucking along on this JavaScript in 2021 thing. There's more to talk about. I just feel like we could talk about bundlers and ESM forever, and those are a big part of the story, but there are other things to talk about. We have some guests lined up, so look forward to that.

Dave: Yeah. Thank you. Thank you, dear listener, for downloading this in your podcatcher of choice. Be sure to star, heart, favorite it up. That's how people find out about the show. Follow us on Twitter, @ShopTalkShow, for tons of tweets a month.

Head over to patreon.com/shoptalkshop and sign up. Get in that Discord, baby! Let's do it. Having fun.

Chris: Let's do it.

Dave: All right, Chris. Do you got anything else you'd like to say?

Chris: Just ShopTalkShow.com, and then click on the Patreon link. Bye.