505: Passing Props, Node Shipped Fetch, Digital Rot, and Making CodePen a PWA?

A bit of follow up from last episode on passing props, Node shipped fetch, intentional digital rot on the web, and how hard could it be to make CodePen a PWA?

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

  • 00:41 Passing props
  • 07:32 Node shipped fetch
  • 08:50 Node and prepare script
  • 13:33 Digital rot
  • 15:25 Sponsor: Notion
  • 16:32 .closest was speced and implemented
  • 18:50 VR Browsing
  • 23:25 Jest test
  • 33:48 Sponsor: The ShopTalk Show Discord
  • 34:46 Have you ever considered making CodePen a PWA?

Episode Sponsors 🧑

Transcript

[Banjo music]

MANTRA: Just Build Websites!

Dave Rupert: [Laughter] We are professional. Da-d-da-da-da-da-da.

Chris Coyier: Professionals.

Dave: Here there, Shop-o-maniacs. You're listening to another episode of the ShopTalk Show, a podcast all about front-end Web design and development. I'm Dave Rupert and with me is Chris Coyier. Hey, Chris. How are you doing this wonderful day?

Chris: I'm doing all right. A little cold here but feeling good. It looks like we have a little--

Dave: Uh... Yeah. We've got some errors and omissions [laughter] we'll kind of kick it off with here. First off, Austin Gill, who has a stream now -- you should check him out over on the old Twitch.

Chris: Twitch?

Dave: Yeah.

Chris: Yeah.

Dave: He's over on the Twitch. But he was saying we talked about Vue props very poorly on our recent episode. And he was saying, if you pass a prop -- that's really hard to say, "Pass a prop."

Chris: Pass a prop.

Dave: Pass a prop-prop. [Laughter] Say "Pass a prop to Pappa John" ten times fast.

Pass a prop to Pappa-- [Laughter]

Chris: [Laughter]

Dave: [Laughter] Okay. If you pap -- I can't say it. If you pass a prop to a component and the prop is not defined, it will be treated as an HTML attribute.

Chris: Hmm.

Dave: Okay.

Chris: Is that the secret sauce that makes Web components work then? Isn't that part of the deal is that other frameworks (in the past) have gobbled up props in that way, but you kind of need the props to be left in place for Web components? In a way, that's how you talk to a Web component.

Dave: That's how you talk to a Web component. If you send a JavaScript object to a Web component, it might just be like, "Whoa. Whoa. What's all this? I don't know what these curlies are."

He was saying it'll be treated as an HTML attribute. It's also accessible from within the component as this adder as prop. So, if you think like somebody biffed it or whatever, you can still access it from this adders, dollar adders.

Chris: You can get it anyway.

Dave: But yeah, you know I put together a Web component course, workshop for Front-End Masters. Hey, Chris. They had sponsored this show. They sponsored your blog for a while.

They reached for me to do a Front-End Masters Web component workshop. I'm taking my talk. I'm spinning it into a workshop.

Chris: Good idea.

00:02:40

Dave: Yeah, but the big question is, you can write Web components, and you can use your Web components in Drupel, and you can use your Web components in your WordPress.

Chris: Yeah.

Dave: Where it gets weird is you can start -- you can actually use Web components in Vue, and you can use it in Svelte and PReact.

Chris: Mm-hmm.

Dave: But where you can't use it is React. And React is such a big competitor in this space, or a big framework in this space, I have to kind of address why that is. I'm really trying to figure out why it doesn't work, and there's a really good issue from Rob Dodson where he lays out the paths, like this is a breaking change. This is not a breaking change, but the syntax is kind of bad.

I'm really trying to figure it out, and it deals with how the React just treats everything as a prop and Web components need attributes - I guess is sort of the thing. Right?

Chris: Yeah, there's that, but Web components have lifecycle methods, don't they? They at least have a constructor, and they have unmounted or something like that.

Dave: Connected callback, which means it's connected to the DOM.

Chris: Connected callback.

Dave: Then they have an attribute change callback, which you'd use. It's almost like set state - or something - or prop did update. Is that a thing? That's not a thing in React, but that's basically what it is. Some sort of property update.

Chris: Sure. A little mutation watcher thing.

Dave: A mutation happened. Yeah.

00:04:07

Chris: Yeah. Okay. What gets me about this is the mounted ones or the unconnected ones. These libraries, like React, make no promises about when they're going to re-render something. They might rip it out of the DOM and throw it back because they need to because that's how their framework works or because you changed a prop and that's a promise they made ten years ago is that they would re-render it.

Dave: Mm-hmm.

Chris: What then? Do you need to code your Web component that says, "Oh, actually, this is not the first time I'm appearing on this page. It's the second time."

Dave: Oh, yeah.

Chris: "Because my big daddy framework has re-rendered me."

Dave: Yeah, I don't know how that works.

Chris: It could fetch data. Now it's fetching data twice. Whoops.

Dave: The unique advantage maybe of Web components is the template fragments. You, at some point, create a DOM template. They call them a content fragment, so that piece of template is already parsed. It's already in the DOM. And so, it should render fine. It shouldn't be super intensive to re-render.

But you're right. There's sort of this--

Chris: Yeah.

Dave: What if my React component ten levels up triggers a relay out and then does my Web component re-fetch data and all that stuff? That's a good question.

Chris: That's all it is. It's a question because I don't know that. Maybe there is a line of code in the React code base that says, "Oh, this element has a dash in it, so I'm going to actually memo-ize it," or whatever they do to not do that. Maybe that's the case. I actually don't know what the answer is, and I do know that the very latest beta, non-stable React has said, "Web component support, so please test."

Dave: "We're going to try to--" Yeah. Experimental branch that you can test Web components.

Chris: Cool.

Dave: Yeah. I need to get my hands dirty and figure that out. Really, I'm just kind of at the level of I'm trying to figure out what's actually the problem. What's the problem? Then how do I replicate it? Then does this new stuff sort of fix it?

Chris: Right. If all your Web component was a, say, design system, which is, in my opinion, a great use case, then who cares if it re-renders? All it's doing is applying some styles.

00:06:34

Dave: Yeah. Well, what's kind of weird, too, is let's say I'm using Axios in my Vue app. Right?

Chris: Okay.

Dave: I'm loving Axios. I'm just using it.

Chris: Mm-hmm.

Dave: I'm using Axios for all this stuff. My Web component probably doesn't use Axios. It's maybe not hooking into any of the caching or global sort of settings I have set up.

Chris: Right. I would think that's the way to do it is to leave the data fetching generally to the parent, to the framework componentry.

Dave: And then that chucks it down.

Chris: If the Web component needs data, yeah, just chuck it down.

Dave: Yeah. That's what I would think. It's just interesting. I don't know. You have all these--

Chris: Architectural trusts.

Dave: It is like a linear thing. You know? It's kind of like how there's, in Node, if you've installed any amount of Node apps, you probably have four or five different Fetch polyfills [laughter] on your Node app at one time.

Chris: Mm-hmm. Mm-hmm.

Dave: You have blackbird, bluebird. Node Fetch.

00:07:32

Chris: Did you see that the other day? Node shipped Fetch.

Dave: Node shipped Fetch.

Chris: They're like, "We did it! Node has Fetch now." What I don't understand, and this is just pure ignorance, is why was that so hard? Can't you just put Fetch in there?

Dave: [Laughter] I don't know. I could probably ask Bradley Meck or somebody. But I don't know.

Chris: Is it because you have to hand implement it, and it's complicated? But don't you just kind of get it for free from V8 - or whatever?

Dave: Yeah. I think you get it for free, but I wonder if it's because Node has its own networking stack and this sort of touches the networking stack - or something.

Chris: Probably. Yeah. Just pure ignorance, and I'm sure it was very complicated. No doubt in my mind that it was complicated, but I just don't understand why exactly. You know?

Dave: Yeah. I mean I've heard getting import syntax working and stuff, that was a nightmare too.

Chris: Oh, yeah. I mean that was a decade nightmare. [Laughter]

Dave: You'd think it was just like, "Yeah, it's just one line of code." [Laughter] Apparently, importing a file--

Chris: Pop it in there.

Dave: --is really tough. [Laughter] And doing it spec compliant, that's the other thing, too, probably, is getting it to where it meets, you know, greenlights all the tests and stuff.

00:08:50

Chris: I was just thinking, just yesterday. I had a little mini conversation about Node and how--

Have you ever seen a prepare script, like when you name--? You could write script in your package.json.

Dave: Mm-hmm.

Chris: You could have a scripts, and you could write "Dave."

Dave: Oh, yeah, yeah, yeah.

Chris: And then if you write "yarn run Dave" or "NPM run Dave," it'll run. But Dave won't run automatically. You have to run it. You have to type that into the CLI for it to run. But if you name it "prepare," I think it just runs when the install script runs.

Dave: Hmm. Yeah.

Chris: You know what I mean? You don't have to be troubled to run it because it's just automatically going to run.

I was thinking about it in the context of the dangers of NPM in that if that then gets put into a packages package.json, it will also run when it runs. Meaning that it just exposes the insecurity of that.

When you run NPM install or Yarn install, it's executing a bunch of code on your local machine. There's some kind of feeling usually that, like, "Ah, these dependencies, they're just some files or whatever that I include elsewhere," but they're more than files. They're executable code, and they can execute even if you don't ask them to.

Dave: Yeah. It compiles binaries. You know what I mean? That's a pretty serious deal that it's running X code to compile binaries on my computer.

I was dealing with an issue. Well, Open UI dealt with this issue. People were trying to get the environment up and running, but this library called sharp, which I think is used by--

Chris: Image processing?

Dave: Image. Something.

Chris: Yeah, it is.

00:10:35

Dave: Sharp was blowing up, and it didn't work on Node 16, and it didn't work on Node 12.

Chris: Ooh...

Dave: And so, then Melanie Sumner, over in the D-d-d-d-discord, was trying to use this thing called spacebook.app, which is kind of like one of those doc sites, but it's 11ty-based. It's not VitePress. It's not Gatsby, GitBook, or something. It's sort of like a GitBook, but it's all 11ty-based.

I was like, you know I'm building out this doc site for my course, my workshop, in VitePress. And VitePress is great, but it's -- it's actually super great, but I'm kind of at the point where it's like, "Why am I using Vue?" I don't need to. I just want to include a script tag in the page.

Chris: Oh, interesting. VitePress doesn't -- it optionally uses. I've never heard of VitePress. I know all the Vue, like Nuxt or whatever.

Dave: Yeah. It's Evan You's mix on VuePress, which is all the doc sites in Vue world are built on VitePress. But anyway, I just was like, I would love an 11ty-based doc site.

Chris: Yeah. Yeah.

Dave: I checked out Spacebook. Then I was having a problem, and that was pinned to V12, so I PR'd it to upgrade it to V14, and it all works. It installs clean. But it just goes to show, it's kind of wild.

Chris: Did your PR get accepted?

Dave: It did. Yeah.

Chris: Aw...

Dave: That was very nice. It's up and running, but what a weird sort of world where you have to install binary on your computer to use a piece of software.

Chris: That has nothing to do with images.

Dave: It has nothing to do with images. I'm trying to just write text on a page. Now it's all blowing up, you know?

Chris: Mm-hmm.

Dave: That's wild.

Chris: Yeah, it's a little wild. [Laughter]

00:12:37

Dave: A little wild. Then Luro, we have Puppeteer in there. I think we have Playwright for tests and stuff, too. That's just blowing up, too. [Laughter] I'm dealing with it today. I think it's because I'm passing a no sandbox flag and it's all exploding.

Chris: Hmm.

Dave: I compiled it wrong, Chris. I don't know. [Laughter]

Chris: Yeah. Not the most fun part of development. It makes you want to--

When you get something working, there needs to be some kind of virtual - I don't know - scientific glass bells that you put down over a little wooden plate, like if you're going to smoke a Manhattan or something. You might put the glass in there. The smoke gets trapped inside the glass bell. It looks all beautiful. I want one of those glass bells for websites where you're like, "Okay. It's working." [Suction]

[Laughter]

Dave: No one touch it.

Chris: Nothing touching.

Dave: It's on display now.

Chris: Don't touch anything.

Dave: Unless you are a certified museum curator.

Chris: [Laughter]

00:13:38

Dave: I had this idea for an NFT that slowly degrades over time. You have to pay more money to restore the NFT.

Chris: Oh, that's great. Yeah.

Dave: Like actual art. You have to keep investing in it.

Chris: Right. Right.

Dave: Then maybe tricksters could come and deface your art. You have to pay to get it restored.

Chris: Oh, that's a very good idea.

Dave: These NFTs bros, they're thinking too small, Chris. They're not thinking of the recurring revenue on that NFT. You know what I mean?

Chris: That's a good idea, like that classic idea of a script you put on your page. Then based on the publication date or the last date that that page was touched, that letters start to crumble and fall away from it.

Dave: Yeah.

Chris: The page, the background turns yellow a little bit.

Dave: Yep. Patinas. Yeah.

Chris: Yeah.

Dave: Coffee stains.

Chris: Literal bit rot. Yeah.

[Laughter]

Chris: Coffee stains, that's great. The last paragraph is just inexplicably missing.

Dave: You could probably do this very easily--

Chris: A library.

Dave: --with background mix blend mode - or whatever. Right?

Chris: Hmm. Yeah. Keep it chill. Don't do splitting JS on your whole page or anything nuts. Just make it fade a little bit. Even just opacity might help a little bit.

Dave: Yeah. Change it up.

Chris: If you can't read it, your job then is to click this button in the corner that takes you to the page on GitHub where it's hosted and you have to review it.

Dave: Yeah. Yeah. Yeah.

Chris: Re-commit it, and then it goes back full opacity.

Dave: [Laughter] It's purely based on last updated or something. That's great.

Chris: Yeah, exactly.

Dave: Yeah. Oh, fun.

00:15:25

[Banjo music starts]

Dave: Today's episode is brought to you by Notion. That's notion.so.

As you probably already know (if you listen to the show), I use the heck out of Notion. I call it my second brain. I put everything in Notion. I track projects, the side projects I'm working on. I track actual projects like work projects. I track goals for my year, my weekly habits. I track all kinds of things.

I blog in Notion. I collect links for my blog in Notion or anything I read and want to jot down some thoughts. I log books and keep track of little tidbits and snippets. I collect quotes in Notion. I use the heck out of Notion.

It's an excellent place to just dump all your thoughts that you don't want just spinning around in your brain and get it onto the digital paper. Notion is great for that.

A lot of flexibility and customizability with the database structure. It is just wonderful, and I think you'll love it. If you love organizing your thoughts and getting all those problems out onto a tool, this is good for you. That's Notion, notion.so. Go try it today.

[Banjo music stops]

00:16:49

Chris: What else do we got here from the news desk?

Dave: Another error and omission from Brian Kardell over at Igalia. He was saying -- I think I said that the DOM -- if you're moving off of jQuery, you're going to miss it because it doesn't have closest. He pointed out that there is closest in native JavaScript.

Chris: Is there?!

Dave: See! You didn't know either?

[Laughter]

Chris: No.

Dave: There is, and it was spec'd and implemented about the same time as the other sort of stuff, like query-selector-all and stuff.

Chris: Aw... There's still got to be some that jQuery had. Right? Is it parents maybe that it doesn't have?

Dave: Yeah. It's like parents and siblings and wrap and stuff like that. Brian was--

Chris: Yeah, or like replace self - or whatever. I don't think that was a real jQuery one, but there was one that - I don't know.

Dave: Yeah. We just got replace all. You know what I mean? [Laughter] Replace all finally just showed up. Brian made just a good point. This does exist, so I wanted to clarify that.

There's a reason I don't use it, though. That's why I can't figure it out, and I don't really have time to investigate. But there's a reason, like, did I use it once and it was weird? I'm trying to--

Chris: Oh, you're talking about closest, specifically.

Dave: Closest, specifically. Really, I can't. Yeah, I don't know because I think you could also do closest. I forget. Or get all of them. Maybe it doesn't. I don't know. Maybe this only returns one match, not all matches - or something. I can't really remember.

Chris: Oh, that could be it. Yeah. Not that that is wrong. It's just a different API choice than you're used to.

Dave: Yeah, but to be honest, I haven't used jQuery in a better part of a decade, so I really don't remember what it was like.

Chris: Yeah. It's funny how formative it was, though. But, yeah, we've talked about jQuery a million times. It really is over, though. Sorry.

Dave: I think it's time to move on. Yeah.

00:18:51

Chris: You know Brian scooped us, too. This was a while back, so this is very public news now, but Igalia took over Mozilla's VR browser.

Dave: Mm-hmm.

Chris: Which I didn't really get at first because it's like, okay, there's a browser in VR. Got it. You put your little headset on. It stands to reason you should be able to visit a website while you're in there.

Dave: Mm-hmm.

Chris: Why not? I can't imagine what kind of immersive erotic experiences people would want to partake in, in here.

Dave: [Laughter]

Chris: But anyway, whatever. There's a browser in there.

Dave: Chris is suddenly on the vibration API train.

Chris: [Laughter]

Dave: Yeah. Good. Good, Chris.

Chris: Part of me is like, "Isn't there some kind of Rosetta for operating systems, for VR things? Can't you just run whatever software in there?" Maybe not. I don't know enough about this, so again speaking from ignorance.

It turns out actually there's a browser that's custom made for VR, and that makes sense. As Brian was kind of explaining, it's like, "What is it like to go back?" for example.

Dave: Mm-hmm.

Chris: The back button in a VR browser, is it just a little button at the top of the bar on the left of the URL? Probably not, right? Maybe, but that's not thought -- you're not considering what VR is like to use to just use that same old model.

Dave: Yeah.

Chris: I haven't even installed Wolvic yet, but I think that's the idea is what if we made a browser for VR?

Dave: Mm-hmm. Mm-hmm.

Chris: And so, Igalia is going to take it over, and I have no idea what is going to come of that, but they probably don't have a ton of competition yet.

Dave: Yeah. I think Facebook has Carmel. Meta, we call them now.

Chris: Oh, so there is.

Dave: But that's their--

Chris: Yet another thing I'm wrong about.

Dave: But I think that's the Oculus official one. You know?

Chris: Hmm.

Dave: I think it stands to reason there should be more than one browser choice per website -- per whatever.

Chris: Yeah. Well, Wolvic will be interesting in that it's from Mozilla, so it'll be whatever they call. It's not Gecko anymore, right? What do they call their little presto or--?

Dave: Well, I think this one, if I'm not mistaken--

Chris: It's not that.

Dave: Maybe we need to have them on here, but I think it's WebKit-based.

Chris: Oh, it is?

Dave: Yeah, so it's actually a WebKit browser.

Chris: Why would Mozilla build a WebKit browser?

Dave: I think the XR team was kind of their own world, so I think that was the easiest way to get going, maybe, or something. I'm not sure. But I think it might be WebKit-based. Hmm. There's more than one WebKit browser. Think about that. Hmm. Change your paradigm.

Chris: Well....

Dave: [Laughter]

00:21:37

Chris: It's not surprising to me, in a way. I mean there are all kinds of WebKit browsers. Do you think it's more used than Chromium? I'd wager to say yes. I don't know. Maybe I'm wrong, but WebKit, to me, feels cleaner somehow, just because I was looking into this with Chromium the other day.

Chromium, the project, is not decoupled from Chrome all that much. It is. Chrome does put more stuff, but there's all kinds of stuff in Chromium that's very super Google specific.

Dave: Right. Right.

Chris: It turns out that the companies that want to use Chromium because--I don't blame you--it's very good. It's open-source. It seems like the future of browsers - like it or not - that your job then becomes ripping crap out of Chromium for you to use. Like a lot of stuff!

Dave: Yeah. I've heard--

Chris: There's 50 to 100 major APIs that have got to be pulled because they are irrelevant to--

Dave: Wow!

Chris: If you're, say, Brave. I think there's an open-source project that maintains that. Although, how thankless is that? You know?

Dave: [Laughter] Yeah, it's like, "Honey, why are you up late?" "Oh, I'm supporting million dollar VC-backed companies."

[Laughter]

Chris: Right.

Dave: "With my fork of Chromium that has no Google stuff in it, honey. So, I'm staying up late."

Chris: Yeah. She's like, "Oh, is that what your Patreon is that you make $160 a month from?"

Dave: Yeah. [Laughter]

Chris: "Yes, honey. Yes."

Dave: Yes. Yes. I make $160 a month supporting these billion dollar companies.

Chris: Uh-huh.

Dave: That's what I do.

Chris: [Laughter]

Dave: For fun. After I do a whole day of programming, I stay up late and work on this fork of Blink. Hmm.

Chris: Gnarly.

Dave: Love to open-source.

00:23:24

Chris: Love it. Here, I've got a question for you. This is a little bit new to me. I even saw a NotLaura.com blog post that she was getting into this too. Maybe this is old hat for most people listening, but it's just new to me.

I'm so used to using Jest. You know Jest?

Dave: Yes. Yes.

Chris: You write assertations.

Dave: Yeah. Assert it.

Chris: You load up a thing, and you say, "Run this function." Then I expect it to be something. Right?

Dave: Expect--

Chris: I've written a lot of these tests.

Dave: Expect, expect to be, expect to be, expect not to be.

Chris: Yeah.

Dave: Yeah.

Chris: Whoa!

Dave: Whoa! Yeah.

Chris: A little Jest Shakespeare stuff there. Sometimes, it's really nice and expressive to do that. We have loads of tests for our pre-processors on CodePen, like, "Given this input, does it produce this output?" Which you'd think, "Why are we responsible for that? Shouldn't the processors themselves do that?"

Well, no because we have stuff that we have to strip for security, and we have add-ons that we add that aren't necessarily part of the core library. We have all kinds of different stuff we have to test for. Say there are dozens of tests, at least, for each pre-processor that run.

Dave: Mm-hmm.

Chris: Usually what I do is take a string. Maybe I'll even put it in a file in the file system and say, "Go get this file. Then process it. Now compare it to the results of this other file." Okay, fine.

Or maybe I'll be more chill about it and just write a string of code as a template literal right in the Jest test, like $red is red.

Dave: Mm-hmm.

Chris: Background is $red. Did that produce the right CSS? Is Sass working as I expect it to? Great.

Then I'll compare it to maybe not even the full output. Maybe just a little piece of the output because I'm really just testing one little specific thing. That's kind of the spirit of the test. Great. Fine.

But there's this whole concept of testing that I was weirdly unaware of because I have lots of blind spots and this was one of them. There's this thing called snapshot testing. Meaning that rather than me handcrafting the output and putting it in a string or a file to test that you can just say, "Boop. Snapshot," at the end.

Dave: Mm-hmm.

Chris: Then the first time you run it, it saves the output and assumes that that's correct. Then if it ever changes, it alerts you to that.

To me, it just seems like A) it's more better [laughter] because you're not comparing some substring of the output. You're comparing the entire output exactly as the machine made it. It saves you time because you didn't have to craft the output that you expect it to have. Yeah, it just seems great in that way. I don't know.

00:26:12

Dave: I'm into it. This feels like your glass canister, your glass dome, right? You're like, "We're going to snapshot this, and it's not going to change." [Laughter]

Chris: Yeah.

Dave: We want a lot of bells to happen if this changes, right?

Chris: Right.

Dave: I guess what do you want to happen? I change something. I don't know. I snuck into the demo database and changed the H1. Now the snapshot is failing.

Chris: I think it asks you. It's like a wizard at the end.

Dave: Oh, okay.

Chris: Be like, "This test failed." You can say, "Oh, no, but actually that's cool now. Save a new snapshot of that."

Let's say you changed the shape of the user object or something.

Dave: Mm-hmm.

Chris: Email_address became email (uppercase A) Address - or something. Who cares? But that changed the shape of some data. It probably wasn't even what you were testing.

Dave: Mm-hmm.

Chris: Actually, so that is a little annoying. It probably trips flags more often because it's comparing so much output. You don't have to write all your tests as a snapshot. You could write some of your tests as a snapshot.

Dave: Yeah. This is kind of good for the "barstool falling down in another bar" problem, sort of. Would you say?

Chris: Hmm. Yeah, well, at least you're alerted to the problem early.

Dave: Yeah. Like if I change whatever my WYSIWYG editor component. If I update that and then, all of a sudden, five components later, it just doesn't render. I'd want to know.

Or if I change prop shapes, I mean that's something I do, regrettably. [Laughter] I'm just like, "Refactor props, bro."

Chris: Mm-hmm.

Dave: I'm going to switch this up.

Chris: Yeah. It depends on how you test those. Those don't seem as unit test-y, to me.

Dave: Because snapshot is the output HTML, really, more than the--

00:28:05

Chris: Yeah. I don't know what types of things you can and can't snapshot effectively.

Dave: Mm-hmm.

Chris: It does seem like the entire HTML output of a page seems like a possibly reasonable thing to test. Although, that's going to have high churn.

Dave: Right.

Chris: [Laughter] Everything is going to break that test.

Dave: Yeah. Yeah.

Chris: I think it's more like you're testing individual functions.

Dave: Like my component, the output of the component.

Chris: Maybe. Yeah, a single component. Maybe. I'm really thinking of really boring business logic stuff like a function that's like, "Calculate price of annual plan prorated based on date," or something.

Dave: Okay.

Chris: It barfs out a JavaScript object with the price and what it should be. It's more kind of boring code in that way. It's not really UI-facing code so much as data.

Dave: Okay. Okay. You want to just match it against JSON then, those two shapes.

Chris: I think so. That either string output or stringified output is the type of crap that makes the most sense to snapshot, but I'm new to this, so I don't know. I was mostly just thinking about it theoretically just because of how many tests I've had to hand-craft the output for. I was like, "Whoa!" If I could have just been like, "Nah, just save a snapshot," that would have been great.

Dave: Yeah.

Chris: What is it? Ava.js is the one.

Dave: Ava.js. Yeah.

Chris: Is the one that has the snapshotting. I don't know. Maybe Jest has it too. I don't even know.

Dave: Possibly.

Chris: The irony was, we were using Jest and, if you want to write a Jest test that just says, "Import function from file," it's like, "Oh, no. Jest is not ESM, so you just can't."

I'm like, "What?! Jest, the biggest framework in the world. You can't use ESM?" Wow! Okay. Well, let's use something else then.

Dave: That one is an issue. [Laughter] I've had more than a dozen tests just blow up because they're like, "Some dude 12 levels down is using import. I'm out. I quit. I give up."

Chris: Yeah! Oh, yeah. Totally. Anywhere in the tree - anywhere. Yeah.

Dave: You're just like, "We can't resolve this or what?" You know?

Chris: Mm-hmm.

00:30:26

Dave: There's a new -- talk about Vite projects, there's a Vitest.

Chris: Vitest. Yeah, dude. It looks great. [Laughter]

Dave: I'm just like, "How brave am I? Am I brave enough to just--?"

Chris: To do this? Oh, you're brave.

Dave: Smash a couple beers and just flip over to this. [Laughter]

Chris: [Laughter]

Dave: Is that the solution right now?

Chris: It might be. It might be. Although, the whole project is in development, so it's a little risque, let's say.

Dave: Yeah. They're like, "Please, don't use it," but I'm just like, you get Vite, which is awesome, and there's no Webpack-y step. It just runs.

Chris: Yeah, so it's going to smoke fast. Yeah.

Dave: Oh, so fast.

00:31:07

Chris: And TypeScript support.

Dave: TypeScript support.

Chris: That was another reason that it came up in our discussions because that's another thing that's hard to get Jest to play with.

Dave: Mm-hmm. For the imports alone--

Chris: Right, but component testing, too. Yeah, this seems like this is going to win in the long-term.

Dave: Yeah. Yeah. I'm sure you could fork Jest, but that's the issue -- and not issue. Jest isn't broken. Jest works great. It's worked on a lot of sites. It's gotten people a lot of value over a lot of time.

Chris: Yeah. Sure.

Dave: I want to acknowledge that.

Chris: It's the jQuery of testing. [Laughter]

Dave: I hate when people are like, "Oh, the new thing is out. The thing you're learning is dumb." That's not it. Jest is great. It just has this one kind of growing major problem is everything moves over to imports that it doesn't support that. But Jest is probably in the position they are supporting so many customers, they can't just delete half the code and switch over to that. They can't just do that, that easily, because they have all the stuff built on the whole react setup.

Chris: Right. For sure.

Dave: Sorry, require setup, which I think is part of the React situation as well. React doesn't ship bundles, if I recall, or modules - I don't think. I think it's all--

Chris: I think they still don't.

Dave: Yeah.

Chris: Yeah.

Dave: React is in the same situation.

Chris: If you pull it from Skypack or something, they'll force it to work. There are ways, man.

Dave: [Laughter] Dark pathways. Hey, bud.

Chris: [Laughter]

Dave: Hey, bud, use this bootleg version of React.

Chris: You could switch. [Laughter] Yeah. You could use--

Yeah, they should make a bootleg React with modules. The APIs look compatible too. Oh, God, it has snapshots too. And the Jest style, so me saying that Jest doesn't have snapshotting, but I don't think I quite said that. But just for the record, that's very not true. They totally do have that.

Dave: It does. It looks good. It looks like you have to -- yeah. I guess it'll snapshot. Man, now I'm interested. Now I'm interested.

Chris: Yeah. This looks good.

Dave: One thing I don't use very effectively is mocks, too. I didn't think I realize you just have the folder called ___mocks, or whatever. Then it just auto-says--

Chris: Is that like fake data?

Dave: Yeah, it's like fake data, like a user or something. It'll give you a user variable automatically. I didn't think I realized it did all that automatically. I saw it everywhere, but I didn't realize, "Oh, that's all happening auto-magically." You can say, "Jest mock some module," or whatever, but anyway. I was surprised.

Chris: Indeed.

00:33:49

[Banjo music starts]

Chris Enns: This is Chris, your ShopTalk Show editor. Let's take quick pause here between the amazing things that Dave and Chris are saying to remind you to check out the ShopTalk Show Patreon, patreon.com/shoptalkshow.

One of the coolest things I've noticed in being part of the Discord, which you get to be a part of once you're a Patreon member, is the helpdesk channel where people ask questions about stuff and they get a direct line to not only sometimes Chris and Dave, but also a whole community of people who have experience, have answers, who are wise, who are wisdomous in the Web dev world.

Even I, a lowly audio editor in the world of Web dev, have asked questions about things that I have no idea what I'm doing and have gotten really helpful answers and pointed in the right direction and not just laughed at for using FrontPage 98 for all my Web development in 2022.

Check out the Patreon, patreon.com/shoptalkshow. Now back to the show.

[Banjo music stops]

00:34:59

Chris: One here from the D-d-d-d-discord here from Josh Collingsworth, a friend of the show, a pal in the Discord, all that. Has a great blog.

Dave: Triple threat. Triple thread.

Chris: Great designer. Great writer.

Dave: Great developer.

Chris: Great developer.

Dave: There you go.

Chris: We even did a video based on Josh's header. Remember those little random poopies?

Dave: The grid? The little--

Chris: Random grid one. Yeah.

Dave: Little speckles? Yeah.

Chris: That was Josh's site. I'd throw him over in your Feedbin or your RSS reader of choice. I've been in there cleaning stuff out, adding new feeds.

Dave: Good.

Chris: Feeling good about my RSS. Yeah.

Josh writes in with a question kind of from me about CodePen. "I play a lot with progressive Web apps lately and wondered if you'd ever consider making CodePen a PWA. I know PWAs are usually all about the mobile install story, and that CodePen is much more desktop focused. I still think it would be pretty cool. I'd love to have a CodePen icon on my dock for spinning up new Pens quickly and be able to command tab right to my CodePen editor instead of having it just be another browser tab - one of many. I assume there are probably some perf and bandwidth gains there from a service worker, too. It seems like a win, even if not a lot of people care about installing it, but wondering what the thought process goes into that or, for that matter, how hard it is to do with a Rails app."

There's a lot. [Laughter] There's a lot to think about there. I don't think there's any, you know, like, would it be better if we totally went all in on that route? Almost certainly yes, but what's the road to that is paved with spikey ass rocks. [Laughter] And so, you've got to just be real sure that's what you're going to do.

I think, if we were going to do this, it would be probably like a year of effort -ish. At that level of how many people are involved and architectural choices and all that, that you'd have to be real sure that, at the end of that, there's a rainbow, that it was the right kind of business call to make and that's going to take you into the future, not just be this little thing you did - or something.

Dave: Yeah.

00:37:16

Chris: You know? Yeah. to me, it's not so much the mobile story that's interesting. It'd be the offline story that if I was going to do that, I'd be like, "Oh, what we're doing here is making an offline version of the app." Right? You can't just choose to do that. Everything would have to work or you'd have to be really clear about what is and isn't going to work - and stuff. The more that does work the better, so why do it at all if it's not pretty full featured?

Dave: Mm-hmm.

Chris: I'd want to make sure that it does what CodePen can do but offline. Then what do you do about data because offline data is--? CodePen is all about data. This is not a "Can I read this blogpost offline?" or whatever or save some state of something so I can view it. That's no fun. You'd want the thing to be fully functional, so how do you do things like create a file and be safe that when I go back online, it's going to sync that file up and not cause any problems or anything?

Then there's a collaborative and team-based nature of CodePen that's like, "What if two people do that?"

Dave: Yeah. Yeah.

Chris: You both have write access to it. That's what I mean by a year of effort. This isn't just, "Oh, you just put a manifest file at the root and put a service worker there that says which files to hold offline and stuff." That's not true either. All that processing we do, we have made this architectural choice to generally do it as Lambdas, dockerized protected Lambdas that do all the processing. They're fast, they're safe, and they're scalable, and inexpensive. There are all these great reasons we don't really regret it. None of that will work offline.

Then it's like, "Okay, but it could."

Dave: Unless...

Chris: Because what about wazum?

Dave: Yeah.

Chris: Then you start this architectural journey of making those run as Web workers or figuring out how those things -- you could ship those down to the user. But then do you ship all of them down? Do you ship some of them down? Do you have a little dashboard that says which ones are ready to use offline and which ones aren't?

I feel like that already was a heart pounding amount of thought of work and that that's the tip of the iceberg. There's going to be way more to think about. It's just no joke. It's just a huge thing.

00:39:37

Dave: I feel like y'all could ship a manifest. That's probably an hour. You could ship and register and ship a service worker that does nothing, that only says, "If offline, chuck them to a 'Oh, no! You went offline,' page," like a Chrome Dino kind of thing.

Maybe you cache a cool Pen. You have a contest to be the Chrome or the--

Chris: Something. Yeah.

Dave: The CodePen offline game, or whatever. Right? Then you cache that. Only the offline page and the--

You could actually just have a page called "Offline" that embeds. Anyway...

Chris: Sure. Some experience that's not crazy to build.

Dave: Yeah. Yeah. Yeah. You have the offline page and the service worker and some icons in the meta theme color and you're done. Right? That works.

Chris: That way it's installable - is the point.

Dave: It's installable, at least, and people could get it on their local. Right? I think you could do that, but you don't have to have the glorious offline story, but I think in y'all's situation, if you went offline, you'd probably want to undo all the pieces. Does that make sense? That's where maybe just going to an offline page is the best choice, unfortunately. What if somebody is on and off? If they have spotty wi-fi, is it super ruined? That would be a question I have.

I'm thinking about favorite hearts and stuff like that. You'd almost want that to turn off if somebody is offline - or something.

Chris: Yeah, rather than save that. Mm-hmm.

Dave: I think you could have the shell just show up, and that's what I'm thinking about doing with Luro as well, just have the shell exist.

Chris: Hmm.

Dave: But then it's not that easy. That's what I want to say.

Chris: No. Maybe, yeah, I could see in a Luro situation where it saves the last state of a big pile of data and then it's read only, but at least you got it.

Dave: Mm-hmm.

Chris: That'd be kind of cool, actually, because it seems like that would be -- I don't know. It'd be still useful in a way, like Delta wouldn't do that on their app because you don't want to be showing people that your flight is at the wrong gate - or something.

Dave: Yeah. I'm less concerned about the offline thing. You could just be like, "Oh, you're offline. Sorry." [Laughter]

Chris: Sorry. Yeah.

Dave: Or do the read only thing. I think there's just lots of stuff that doesn't need to work, but I think there are certain people who want--

It's easier to say, "Go to luroapp.com and then log in." There are some people who just want to click an icon and have it show up.

Chris: Mm-hmm.

00:42:31

Dave: I think about the Figma app. Do you use Figma, the application or Figma the website?

Chris: Honestly, I go back and forth a little bit. But generally, I use the app, the native local app.

Dave: I just opened Figma the app, and it says, "Log in with browser." [Laughter] That's all it says. Guess what. It's just a Web app. Figma the app is just a Web app.

Chris: Oh, it is, but there's a little bit of bonus to it in that your local fonts work and stuff.

Dave: Right. Notion, just a Web app. [Laughter]

Chris: Mm-hmm.

Dave: Discord, just a Web app. It's all the same thing, and so I don't know. Sometimes I'm like, "Oh, I'm in a browser. I'll just open Figma in the browser." I do sometimes regret that because [laughter] Figma is one of my 700 tabs, and I kind of need it at times. But you know. Maybe that's it is maybe you can just kind of -- I don't know.

But they'd be cool. I don't know. You'd kind of want to do things with CodePen like you'd want to have an actual tabs, maybe, like Tab 1 is CodePen 1, and Tab 2 is CodePen 2, or something.

Chris: Hmm.

Dave: There'd be kind of cool things you'd want to do natively in CodePen, I think. Maybe that's now you're in Electron territory.

Chris: Yeah, maybe. I think there are interesting answers to some of this stuff that I'm absolutely not promising. I have no idea when and if we're going to do any of this. It's all theoretical. It's just fun to think about.

There are certain pieces of technology that support--

For one thing, I think it would be interesting. There are lots of paths forward to having processing offline. Most developers do all of their processing on their local computer, so why does CodePen have to be that different?

Dave: Right. Right. Right.

00:44:30

Chris: There are paths forward that bring that a little more in home. But one thing I think is really interesting is this concept of UUIDs. [Laughter] You know? Ever since I started going to Bend JavaScript, that's how I met this fellow Robert who now works with us at CodePen. He's one of the maintainers of the UUID library on NPM, which has 20 billion zillion downloads kind of thing. You know?

Now browsers are starting to ship it in browsers, but the point of them is that if you create one (at any time, just ask for one), it's the only time that number has ever been created ever.

Dave: Mm-hmm.

Chris: Or ever will be. It's an absolutely unique number. I think there are some caveats to it, but not really.

Dave: It's like in the trillions or something. Yeah.

Chris: Yeah, grains of sand on the planet - or whatever.

Dave: Mm-hmm.

Chris: Probably no two have ever been created that are the same so that if you do that offline, let's say you make a file, that you can do that and say, "This file has this UUID." Then when you sync it up online, it's going to be safe. There will be no other--

Even if 100,000 other people also did that same action on your team - or something - they'll have different identifiers. They're not going to overwrite each other because you know that they're unique, even if you did that action offline. You don't have to ask a database, "Is this unique? Give me a new unique database identifier." It is unique, even if it doesn't have database connectivity. It's kind of cool, you know?

There might be other things that overlap. I like it when there are computer science concepts that help do what end up being modern features of apps.

Dave: No, that would be interesting what you could do. I don't know. But like you were saying - I don't know.

I've recently hit this situation where it's like we want this feature in Luro, and I'm kind of doing mental math. I'm like, "Okay, that's six months of work." Those are really hard to bite into. I think we're totally going to do it, but it's hard to be like, "This is just going to take a fricken' long time."

Something like support CodePen locally would just be a huge task. That would be a massive engineering undertaking. It might be worth it, but it's just very big.

00:46:59

Chris: In a related way, literally everything you do is this chunk of your day. It's this chunk of your time. It's this chunk of stuff that you have to support forever. It impacts the work that other people are doing. It's not just this little feature. It has tendrils.

Dave: Mm-hmm.

Chris: It has a lifespan. Choices like this are a big freakin' deal. You can make little, tiny choices that influence the rest of your life.

Dave: Mm-hmm.

Chris: It's wild. [Laughter] You know? They're not to be taken lightly. Not to scare anybody away from just doing stuff, but that happens, I think, at a certain scale, size, and age of an app. You're probably already there with Luro, but it doesn't affect little side projects that you're just screwing around with. But I feel this deeply.

We made one little change on CodePen a month ago that had something to do with URLs. It's just one of those things where you're like, "Oh, that'll clean up our future APIs. What a great idea." It was a great idea, and it's done, and it's out, and we've been kind of feeling the repercussions of what that change is for a month or more. That was a little URL change.

Dave: Mm-hmm.

Chris: Not like an architectural shift.

00:48:09

Dave: Yeah. I just bailed out of a whole serverless function thing, and you'd think, "Oh, I'll just copy/paste the functions over into the server app. Bada bing, bada boom, it works." Not. Not the case. Not that easy.

I mean it was like still like you were saying, feeling the repercussions of this change that we made. Or it's that thing where you talk yourself into features, like, "Oh, let's support Azure logins. That seems like a good idea. Yeah, everyone is hyped on Azure. We have a client that uses Azure. We're all into Azure."

Chris: Yeah. Sure. Azure it up.

Dave: Guess what. You're doing that for the rest of your life. When you touch the login form and you potentially break Azure, whoa. Busted, bro. You know? There are at least a million of those where you've hyped yourself into a really good idea (or a good idea at the time) but now it's just this massive debt machine.

Chris: But maybe, just maybe, in a perfect world, you could architect things (either from the beginning or during a first major refactor) that says, "Okay. We know that this is going to change. We've decided that Azure is cool now, but what is Azure?" In this case, you're speaking of it just as an OAuth provider. What can I change here to make sure that if we were to add or remove OAuth providers, it's no big deal?

Dave: Right.

Chris: It's a one hour job or less. How can I set that up so that that's true forever?

Dave: I feel like there's almost always -- there's always a 15-minute fix that you can get done now.

Chris: Mm-hmm.

Dave: Then there's a one month fix that is probably way better. You have to choose.

Chris: [Laughter]

Dave: I can either do the 15 minute fix right now to support it and be done or architect it over a course of a month, scope it out, budget, build.

00:50:22

Chris: I like those timeframes that you chose there because they're true. What you don't want to say is that the right fix is always, always the right answer. It probably generally is the right answer, but a month. Really? Yes. Yes, a month. You only get so many of those, so that's the right framing. You can't do all your things that way because now you're out of months.

Dave: Yeah. Well, Jim job hops every six months, so Jim only has six of these in his tank. [Laughter] He can only do six tasks while he's employed.

Chris: Yeah.

Dave: Hopefully, it's good. Hopefully, it's worth it and doesn't create other problems.

There's a month, but then there's the month of repercussions after that - or two months. You know?

Chris: Yeah, right. So, he's really only got three.

Dave: He's only got two or three tasks he can possibly do in his tenure.

Chris: That sounds about right.

Dave: Anyway... We should wrap up. We've got a hard stop edition of the ShopTalk Show. This was good chatting, Chris. Thanks, Josh, for sending in a question.

Chris: Indeed.

Dave: If you have a question, send it on in. We have a form on the website.

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 16 tweets a month. And we have a new YouTube. We're ShopTalk Show on YouTube. You can find it. The link is on the site. The link is on the site, so click on that link. Right now, we have an ugly channel URL, but we'll get that all fixed up after 30 days or something.

Then the next thing is join us in the Discord, patreon.com/shoptalkshow. D-d-d-d-discord fun.

Chris, do you got anything else you'd like to say?

Chris: Oh... ShopTalkShow.com.