Julien Huang - Stop making these Nuxt & Vue mistakes: introducing @nuxt/hints 1.0
About this talk
This talk focuses on the challenges faced during the transition from the build phase to the run phase of a web project, particularly in the context of using frameworks like Nuxt and Vue.js. The speaker discusses common issues such as hydration mismatches and cumulative layout shifts (CLS) that can negatively impact user experience. He introduces Nuxt Sense, a new development-focused module aiming to improve the performance of applications by providing real-time feedback on potential problems like hydration issues and HTML validation. Additionally, the talk highlights features of Nuxt DevTools that help developers identify and resolve performance bottlenecks, ensuring a smoother and more efficient deployment process. The speaker shares insights into future developments for Nuxt Hints and emphasizes community involvement in improving the ecosystem.
Full transcript
[music] >> Hello everyone. Um yeah, everyone can hear me well. Nice. So, yeah, it's my second talk at Vue js Amsterdam. It's good to be back after 2 years. Um for people who doesn't know me, my name is Julien. well, as Alex said, I do love food. Um oops, that's a surprise picture. Um so, yeah, I do love cook um cooking things um and baking um especially
cakes. Um I do powerlifting, um do love video games, uh and I do a lot of open source. So, yeah, as you can see on two pictures here, we have a cheesecake with a Nuxt logo and also a Storybook logo. And then here in France, what we call a galette des rois with another Nuxt logo. So, yes, if you're wondering, I do have a Nuxt iron. And
before you even ask the question, um I have been asked before, no, the Nuxt iron isn't used for anything else than marking cakes. So, um I'm part of the Nuxt core team and I had um change some changes um in my career last week. I joined a company called Chromatic. Does anyone knows what Chromatic is? Yes, one, two, three, four. Okay, yeah, so some of you. And
well, this company hosts also the Storybook core team. So, if you don't know what it is, um Storybook is a front-end tool to allow you building your component in isolation, um well, create your own design system. Um and and it does much more. For example, interaction testing, visual testing, and um accessibility testing. And so, Chromatic is a company and a platform, so which aims to improve the
UX of the internet by giving you developers um ways a single platform to automate your visual test, um visually review your component changes, host your design system, of course, and work with your team on um on all these changes for each commits, PRs, and on your main branch. Okay, so I guess it's enough about me. Let's talk about shipping actual projects to production. >> [gasps] >> How
many of you here has been on a project that went from a build phase to a run phase? It means that it has seen like uh its first deployment ever and being live on internet. Just raise your hand. So, quite a lot of you. Do you remember that feeling when your deployment pipeline goes green and you see your website being actually live on internet? It's a great
thing, is it? And usually what happens then, well, it's the um I would say boring run phase where you have to start fixing bugs. Um so, yeah, you get user feedback. There's there can be a lot uh and different kind of feedback. Um they can say that well, I have to wait before typing in the form in some form on uh your website or it kind of
bugs out. Let me explain to you. So, it actually happened on me to me Amazon. So, it can happen to anyone. I started, you know, to look for a headset with a microphone, but professional. Um and I typed um I think headset microphone in the search bar, press enter, um the page refresh, and I started immediately to type again in the input, and the input kind of
reset its state. So, here oh, you can see it. Yeah, so I lost P the space, P, and R. Um so, yeah, that can be a very annoying behavior from uh some website. Um so, it doesn't only applies to Amazon, actually. There's quite a lot of website, but Amazon is quite big. Um yeah, I'll explain to you what happened. Um this is actually a quite a critical
bug. Side by side, you have the same page, one uh on the left that has been server-side rendered, and on the right that has gone through a client-side navigation. On the left, you can see that there's like some components which are in a weird state, in loading state. You have like the loading uh skeletons. Um and at the same time uh the same component being like kind
of filled with all the data. Um so, yeah, that's a bit weird, and I hope it never happens to you because it's really hard to debug. Um this one is quite common. The page jumps around when it loads. Is it annoying? Because that's kind of the experience your users will get. Um well, I'm joking, of course. Um yeah, so here I'm on I want to order a
margarita pizza. And suddenly, there is a flash deal banner and recommendation that appears, and I misclick and well, I ended up adding garlic bread instead of my margarita pizza. I just want to order and eat. That kind of behavior can make your users leave and never come back. Let's see what kind of could causes these behaviors. Um first, for the two first um example I showed you,
it's hydration. So, for people who doesn't know what hydration is, it happens on some frameworks. If you have a server-side where the app render application, if we take Nuxt for example, you're creating a Vue application server-side um when your make a request, we render the Vue application, stringify it into HTML, send back the response, so your browser gets an HTML response which contains a script that is
your Vue application. It will load it, and Vue runs like any SPA. And when it runs, it will load your component, each one, render it, and at render time, the DOM element before even your Vue application loads, and the render, the initial render of your Vue app uh your Vue component. Vue will compare them, make a diff. If there is a diff, well, it will run, remove
the DOM element, and of course, set the new render. The issue is that it renders the component twice, and so it delays the interactivity of your Vue um of your application, and basically, if your app takes a lot of time to load, it will of course try to take the state from maybe query your URL queries, uh and so it will reset the input. I believe this
won't happened in Vue anymore because there was a PR that kind improved um so, this behavior. And here, when you have a diff that is too big, what can happen is that your framework can bug and forget to remove the DOM elements or uh applying applying some weird uh forgetting to remove classes from what is currently on the DOM elements, and that's how you get with uh
some such a critical hydration issues. For the last issue with the page jumping around, it's actually just a CLS issue. So, CLS stands for Cumulative Layout Shift. Um it's a web core vital metric, um and it just measure how much your elements are moving around when your page loads. And that's kind of hard to detect most time most of yeah, it's usually in that kind of issue
is triggered by injected code. For example, tag managers. if you've seen some of my talk, I really don't like tag managers just because it's not managed by developers, most of the time by marketers. And um developers don't even know what's being loaded on their own website. Now, um yeah, so these issues are kind of hard to debug. Uh what if I told you that Nuxt could try
to find a way um and tell you what could be improved on your website? And that's just basically my talk introducing you to Nuxt Sense. Um it's for now a dev only Nuxt module that tries to give you real-time in your console on what's happening in your application and how you could improve it. And I prepared a small live demo. So, here, yeah, I'm on a MacBook.
I didn't move um the another tab to another screen. I'm not used yet to Please, give me Thank you. Um so, yeah, here we have um Nuxt Bytes. It's an example I've prepared for the talk. And if you go here in the inspect, so, it's a Nuxt project that already has Nuxt Hints. If you go in the console, you will see different kinds of logs. So, it's
so small, I cannot see it from where I am. Can you? Yes. Is it big enough or should I move it somewhere else? Yeah, no, that's well, yeah, I Yeah, it's probably better this way. And of course, I've set the um PC layout on my keyboard. Um yeah, so, you have different kind of warnings. Um let's say this one. Let's start with HTML validation. So, um when
you render your your page server-side, um usually you want to keep your HTML valid. Um it's a it's less of a problem uh client-side, but server-side, um you need to keep your page valid because otherwise, um it can trigger some hydration issue. So, we will log you anything that um you should add um to your HTML page. Um then, this one is actually a hydration issue um
that View usually logs you by showing you the component tree, what has been mismatched, but yeah, that's all. So, what I wanted to see is actually if we could help users Yeah, there's a lot of shoes here. Yeah, help users by telling them, well, which component has a hydration mismatch. And if it does, well, we will tell them which file they can look at so they can
fix it. You have additional logs here, hints lazy load information. Um this one is about tracking which component can be lazy loaded, so Nuxt Hints track every um file um that is being imported, every component that is being imported, but not used. Um and so, if it is not, well, you could lazy load them. And so, you would reduce the bundle, the initial bundle size for your
end users. We also do things such as like Web Vitals metric um here on this button, it kind of block the JavaScript main thread. Um and on any poor or waiting that needs improvement, we will log you out um the metric that has been um emitted by Web Vitals. Um yeah, I think that's pretty much all. If I forget anything, it will be on my slides. So,
let's try to get back to the slides. Perfect. Um what else? Yeah, um so, let me explain to you how I think works under the hood for hydration mismatch detection. We basically check for each component at render time the HTML before and after View's hydration. Um and if there is one, we log you something in the console. Yeah, so, what can cause a hydration mismatch? Basically, if
um doesn't render the same thing as uh what's currently in the the DOM, but the root causes can be different things. If you're using browser-only API in setup, um if you're using non-deterministic values like Math.random, date also because you won't have the same date server-side and client-side, um async behaviors, uh if you're like trying to fetch data, but not using servers uh like SSR-friendly refs in Nuxt.
And invalid HTML. As I explained, sometimes, um so, you get your HTML as a response, send it back to the browser, and there's a behavior that a lot of browser implements is trying to auto-correct Um so, it's a bit strange. In fact, the hydration mismatch doesn't comes from your HTML response, it's come from directly from your browser. Can try to auto-correct, and then that's how everything can
bug out. And so, we have a whole feature on HTML validation. Each time you render a page server-side, we will trigger um import HTML validate, run it on every uh HTML rendered, log you anything that should be a warning or an error in your console. We also look for some Web Vitals metric. First is LCP and images. And we catches some uh mistakes people can make. First
is adding loading lazy on your LCP image because an LCP is the the biggest element on your page, and you want your users to get it first. And if you set loading lazy, it will delay um the well, um the moment your browser will start to load your image. Fetch priority high. Um basically, it's an attribute that tells the browser to prioritize this image to download. With
an height attribute, um so, yeah, when your browser gets an image, it doesn't know what size it has. So, it doesn't reserve any space. If your image is really big, basically, when it loads your picture, it will start to push um other element down, and this can cause um some layout shift. And finally, we will um always tell you well, try to prefer WebP and AVF format,
which are lighter than um JPEG and PNG. Other Web uh other Web Core Vitals metric are CLS and INP. So, CLS, I just explained for the images, it's um just layout shift. Um common causes can be images without detection, content injected after load like by tag managers. Font swapping can also trigger some um layout shift. It's usually minimal, but yeah, it can happen. INP, each time your
users will interact uh with your buttons, um if you do some heavy computing synchronously, it can basically stop the kind of stop the responsiveness of your um and make your application feels buggy. Then, component lazy loading. Well, uh I already explained it, I think. Um so, yeah, if it's um imported, but not used, we will log uh something in the console to tell you, well, which component
can be lazy loaded. So, you can either use the lazy prefix in in Nuxt, for example, or use define async And we also track third-party scripts. mostly showing you about how much time it took to download and pass the the script, um warn you about missing cross-origin attribute, tell you if it's render-blocking, and of course, suggest you to use Nuxt Script Nuxt Script, um which is another
Nuxt module, official module, maintained by Harlan um from the Nuxt Core team. And it has a really nice developer experience. Um it's you will see if you will try. So, yeah, um since it's an official Nuxt module, of course, it will come with a dev tool And I will have to get back to the demo. Does anyone knows about Nuxt DevTools here? Yeah, quite a lot of
you. Perfect. So, let me close the console, and basically, it's similar to View DevTools and Vue DevTools. You have a small, how is it called? Like a model button, like floating button, yeah? And here, we have the Nuxt Hints page. So, it means that you have an UI um that just what that you can use, um and it's probably better for you than having a hundred console
logs. So, yeah, let's see quickly. We have all the Web Vitals metrics here. Um something I've I think it's quite cool is, well, I interacted with these buttons that triggers an INP or waiting. And if you hover over the interaction target, you can see that there's um it's highlighted. And if you click on it, we oh well, it's on my other screen, but we basically will open
um yeah, can I bring No. Oh, yeah, I know why. I need I probably need to get a Mac OS um to understand how everything works. So, yeah, we will open uh for example, this was triggered on dashboard.view and we will open um directly the page or the directly in VS Code for you. Now, how do I get back to Google Chrome? >> [applause] >> Oh, so
yeah, uh well, I was talking about Web Vitals. So, you click here, it opens VS Code. Yeah, perfect. Um what's next? Yeah, we have also third-party script. Um just shows you which shows shows you uh how many third-party script you're loading, which ones are loaded, um if it took well, too much time to parse, um and well, you can see which URLs have. You can log the
element or copy the URL. Um hydration, uh this is probably very important. So, this um the hydration will um feature will watch over all your server-side rendered page and save it server-side, so in your development instance, and you we try to before and after hydration and make a diff of it, so it's Yeah, it's easier for you to find what has mismatched. So, here it's about some
uh the text result. So, in red is I think usually uh what has been removed and green what has been added or yeah. Um so, yeah, I hope it will help you a lot. Uh what else? HTML validation, it's kind of the same thing. Uh it lists all the warning and an error, the location. So, here at line two, I should have added a lang attribute to
my HTML tag. And finally, lazy loading, we will list you which component has been imported is in your um like yeah, it's in your file dependency, um but has not been rendered. I think that's pretty much all for the part. Um let's go back again to the slides. Um so, yeah, that's was all for Nuxt DevTools uh Nuxt Hints DevTools Um if we take a look back
at the journey of Nuxt Hints, you'll see that the first commit has been done in >> well, actually in August 23 uh by Jacob, who's um on the side here. And the second commit was done in 25, February 25. Hey, that's how open source works. Some project can sleep for a while and just wake up. The first alpha was done um was released in November 25. And
1.0 will be released today. >> So, what do we have on the road map? not that much, I'd say. Uh we will have pre-render hints, which will tell you if a page could be pre-rendered uh because it doesn't have any dependencies like to any uh user request or any external API. Um optimi- optimization hints for hot assets and uh like fonts and script that Jacob is working
on it. And finally, production mode. Um because Nuxt Hints is for now a dev only module, it can it could go to production, so you know, you could like maybe report it uh to your telemetry platform. And yeah, that's pretty much all I say. Um any ideas are of course welcomed. Uh we've released alpha um alpha stage in November to gather more feedback and what could be
improved. And yeah, so I guess it's time for 1.0. And I already prepared everything, so yeah, I just need to squash and merge. I hope nothing will break. And I even have prepared the draft release. >> So, technically I Yeah, if I verify everything, yeah, perfect. I can publish it now. Click on the button. And yeah, it's published. There should be a CI that runs and publish
everything automatically. So, what do I need to add? Yeah, um Nuxt Hints, yeah, um the future of Nuxt will be basically be directed by the committee as as a Nuxt core member, we all hope um to that improving develop experience will in the end improve the user experience and user experience. Um so, yeah, that's why I'm asking you for your help in giving more ideas, more feedbacks,
um what we could improve, whether it is on Nuxt Hints side or Nuxt or any uh modules in the Nuxt ecosystem. Um so, yeah, I guess that we can say Nuxt is a framework that was made and is made by the committee for the committee and also for other communities um as we try to share what can be shared with other frameworks. So, yeah, thank you very
much. Um I'm very looking forward, you know, to work with Storybook and Chromatic. Um it won't change my involvement um in Nuxt. Um and in fact, it's probably also a huge opportunity to make Storybook View what Nuxt work better together.