Nuxt Nation
Nuxt Nation is an online event that is held by Vue School, with speakers such as the Nuxt and Vue authors.
These are some notes I took while attending the online conference on 16 & 17 November 2022.
Some of the talks, that I took notes from can be found on the Vue School YT channel
There are Free workshops from Nuxt Nation, with limited seats.
Nuxt 3.0 Stable
- Vue2 used connect which is used by ExpressJs, now they use h3 which is one of the fastest Js frameworks and works in any environment (node, Cloudflare workers, ...)
- Vue Router 4 is not included by default if you do not have a
pages
directory. - Nitro is a server, it uses h3 under the hood, but it's also a bundler (it will track all the dependencies and delivers an output that is less than 1 mega bite and can be deployed on any platform including Cloudflare workers)
- Out of the 34.1KB, Vue is 25.3 and Nuxt is 8.7kB
-
Auto imports.
-
Components inside the
component
directory can be used without import. -
Pages directory. Each file is mapped to a route.
-
server/
directory allows you to go full stack with Nuxt with a database. -
composables/
Nuxt is shipped with many composables to help manage App data, and you can add your own. -
Modules.
-
content directory for building pages with markdown.
Client Side Error Handing In Nuxt
- Michael Thiessen
-
End users are unpredictable.
-
Something unexpected will happen.
-
Instead of the app crashing we need to handle these errors.
-
createError
method is provided byNuxt
and it works on the client side and server side.
- To handle the above error in a nice way using the
<NuxtErrorBoundry />
component. It allows us to isolate errors, instead of relying on the generic error. The whole app doesn't crash just this specific part. - Any error that happens within the boundaries of this container will be handled
- There will be no error in the console as the
NuxtErrorBoundry
will catch it. - It switches between rendering the default slot and the error slot. Which allows us to put an error message.
- If the part with the error crashes we can then still use the rest of the app.
- It's not enough to catch the error, we want to reset it (set its value to null)
- Also before resetting it we must try to resolve the error to not get stuck in a loop of resetting and then getting the same error again.
- How to resolve depends on the context and the expected errors. One way to do so is to navigate to a safe place away from the error. And we can do this using the
navigateTo
method.
Common errors
- Networking requests
- User Inputs
- Redirects
createError method has the option to create a fatal error. If it's an error we can't recover from you can use it to though a full-screen error.
error monitoring systems
NuxtErrorBoundry
Vs v-if
- Not much
If you navigate away without resetting the error the error will still be there. Then it's best to do some sort of middleware that resets errors or perhaps a key on the NuxtErrorBoundry
that is key to the route that you're on so each time you navigate away it forces it to reset the error.
The error can return an object as well as a message.
Vue Js Composables
- Inside a composable directory you can refactor code that you repeatedly use.
- Nuxt will automatically pick up that you created the composable and you can use it in your pages script tag and it will be automatically imported.
- Then when you update your composable the changes will apply to all your pages.
<!-- /composables/useSimpleHead.ts -->
export default ({ title, description }) => {
useHead({
title,
meta: [
{ hid: "description", name: "description", content: description },
// Open Graph
{ hid: "og:title", name: "og:title", content: title },
{ hid: "og:description", name: "og:description", content: description },
// Twitter
...
]
})
}
Nuxt Image
https://v1.image.nuxtjs.orginstall
yarn add --dev @nuxt-image-edge
A package that allows you to resize and transform your images using a built-in optimizer or your favorite image CDN
add the model in the nuxt.config.ts
file
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss',
'@nuxt/image-edge',
]
})
Use <nuxt-img>
tag instead of the <img>
tag inside your components
You can also use the <nuxt-picture>
tag
Vue Macros
- A series of proposals of ideas that are not yet officially implemented by Vue.
macro vs runtime code a macro allows more complicated features to be implemented.
Nuxt Rendering Modes
Nuxt rendering docs- In a traditional Vue App, each page is rendered on the client side. Which can improve the app's performance, but creates SEO issues.
- Nuxt allows universal rendering. The server provides the browser with a fully rendered page, then it acts as SPA. Fixing the SEO issues, yet still providing the performance of a SPA.
- Hybrid Rendering. No need to choose just one rendering mode for the whole app (client or server-side rendering). You can define rendering rules for a group of routes.
- We can for example set a blog as a static that gets rendered only once, then set another part of the app to be SSR.
Nuxt Custom Dev Tools
use-cases
- Activate/deactivate Feature flags
- Intercept and modify requests
- Offline development mock responses
- Fake user roles
- Trigger app events
- Share configuration with other stakeholders
What are feature flags?
can be used for beta testing
can be used for a/b testing
deploy without risks
Roll back without code changes
Test performance profiling
Kill switches
- Maintenance mode
- Sunsetting
npx nuxi init -t module my-module
@nuxt/kit A library that encapsulates all the methods you'll need to create Nuxt modules.
How Nuxt 3 is allowing us to build faster apps
- Frontend is king.
- 70% of customers admit that page speed impacts their willingness to buy from an online retailer. Deloitte
- Frontend drives revenue.
- Building SPAs improves the UX but there's much more that goes into creating a good UX than just that.
- JavaScript meta-frameworks (like Nuxt or Next) emerged to reduce the workload and make you focus on building the front end. They improve the developer experience.
- Performance is fundamental. Performance is key for the user experience. The design will not be noticed if the performance is bad.
- what is performance
- The objective measurement of a perceived user experience of a website or application. MDN.
- Core web vitals are key.
- The only metric that is going to tell you if the experience is good or bad is revenue. So good core web vitals do not necessarily mean that the experience is good, but bad core web vitals do mean that the experience is bad.
What makes a good performance?
- Main content is visible in less than 2.5 seconds.
- First interaction is delayed less than 100ms.
- Less than 10% of elements change their position during page loading.
Metrics from builder.io
Benchmarks are useful but they are not the ultimate source of truths. So many things that can influence benchmarks.
CLS (Cumulative Layout Shifts)
Things that can cause layout shifts
-
FOUC (Flash of un-styled content)
-
Happens when the HTML is rendered before the CSS
-
Nuxt inlines the global CSS and the CSS from the current page inside the index HTML.
-
Problem CSS is render-blocking, so the page won't render until the whole CSS is. Thus it's extremely essential to inline CSS that is crucial (that will cause FOUC) and nothing more.
-
Nuxt solves this by inlining the critical CSS only. The CSS is above the fold.
-
To inline only critical (above the fold) CSS you can use @nuxtjs/critters plugin. Requires zero configuration. Critters a library from google.
-
FOUT (flash of unstyled text) or FOIT (Flash of invisible text) Especially when using a 3rd party font. a common way is to display fallback font Use the nuxt-font-metrics module to it automatically
To improve LCP and FID
-
Reduce the amount of JS
-
Follow the Purple pattern
- Preload most important assets
- Render the initial route ASAP
- Prefetch remaining assets
- Lazy-load other routes and secondary assets
-
Nuxt Js automatically does code splitting. Splitting each route into a separate bundle.
-
Also nuxt auto imports the components and composables for each page to make sure nothing is redundant
-
32kB initial bundle size
-
0 ms total blocking time as a foundation
-
automatic imports and code splitting to keep the bundle small
-
Prefetching other routes, when they click on it they don't have to download, just the Js will be executed. (Downloading the code that we need in the future in advance)
-
Nuxt is not blindly prefetching all the possible routes.
- By using
<NuxtLink>
as soon as those links appear in the viewport.
- By using
- Lazy-loading secondary content is the developer's job.
Nuxt on the Edge
- For some content just has to be dynamically rendered, and it's best to do this on the edge (the location that is closer to the user)
- This requires running Nuxt on the edge function
- Every time you run a cloud function, every time you call it it has to cold start the whole app. This used to take 314ms in Nuxt 2, now using nitro it takes 3ms only.
- Cloud function have a limitation on disk space and went down from 51 152 KB in Nuxt 2 to 716 kB using nitro.
Comparing Nuxt 2 to Nuxt 3
- Now working with Vue3 instead of Vue2
- Adding more features to Universal Rendering
File structure
/pages
- Dynamic Params syntax changed
/pages/[id].vue
/pages/edit-[id].vue
- To define page meta
- Dynamic Params syntax changed
/components
- Components (and composables) are both auto imported
- To render a component on the client side only you can wrap it in
<clientOnly>
element like in Vue 2, but you can now name the component's file itself like this:MyComponent.client.vue
instead. - lazy load components by prefixing with "lazy"
<LazyMountainList v-if="show" />
- You can combine a directory structure to assemble a component name
/layouts
directory- extract common UI or code patterns into reusable layouts
/middleware
- run code before navigating to a route
- define a global middleware by appending
.global
to the end of the file name.~/middleware/log.global.js
- Middleware definition
/plugins
- Provide global helpers, registers Vue plugins, and directives
- In Nuxt 3 they are auto-registered based on their presence in the /plugins directory. No need to manually register them in /nuxt.config.ts ![[Pasted image 20221118160839.png]]
- Just use composable instead of helper functions.
/static
directory has become the/public
/store
store or state management directory from Vue 2 no longer exists- A
const useX = () => useState('x')
is available out of the box, or you can choose to install Pinia for global state management. server
directory has been added to Nuxt 3 ![[Pasted image 20221118161518.png]]- Nuxt Bridge
- Will bring Nitro, Vite, Composition API, Script setup, Auto imports, and other features will be backported to your Nuxt 2 project. Then you can start to incrementally migrate.
- There are some steps it's not installed and it's done.
Multi-Variant Apps With Nuxt3
-
Use theming and configs as the base of multiple Nuxt projects.
-
Projects that have a designated version per customer.
-
Use domain-driven design in a Nuxt project ![[Pasted image 20221118192202.png]]
-
Possible via Nuxt's hooks and module system.
-
But, you'll be fighting against Nuxt's default folder structure. Has to be done for every project.
-
extends
- Extend your Nuxt app based on other (partial) apps
- Can be used from a local folder, npm packages, and git repos* (no dependencies are going to be installed when you pull it from a git repo)
- Uses unjs/c12 under the hood.
- Each of the sources will be transformed into a layer
- Supports all the benefits of the special Nuxt folders
- Full IntelliSense, HMR, and TS support
- Auto imports
- Layers can override previous layers
app.config.{ts,js}
- Exposes reactive config for your app
- Can be updated during runtime
- Will be added to the client only - don't add secrets!
- Full HMR support
useAppConfig
composable to retrieve app config- Infers types based on the provided config
export default defineAppConfig({
socials: {
twitter: 'TheAlexLichter'
}
})
- Can be used for anything
- design tokens
- social links
- branding text
- Throughout the layers (sub-applications) you can reference that.
Caveats
- Aliases are always resolved to the final app
- Don't use
@
,~
, ... instead, use relative paths (but only in the sub apps)
- Don't use
- Unexplored - only a few usage examples out there, e.g.:
- Hooks from
nuxt.config.{ts,js}
are not yet merged - use modules instead. - Not in the Docs yet.
Upcoming features
- Named layers - access files from layers via named alias
- e.g.
~layerName
-~layerName/assets/logo.png
- e.g.
- Follow #3222 for updates of
extends
Building and deploying mobile apps with Nuxt/Ionic
Why Nuxt/Ionic?
- Nuxt benefits brought to mobile.
- A Nuxt module that you can add to your existing project with zero config
- Leverage the power of Ionic and Capacitor
- Native look-and-feel
Nuxt Ionic Features
-
Auto import all Ionic components, icons, and composables.
-
Out of the box Page Routing.
-
Leverages IonRouter, and handles nice animations as you navigate.
-
Access the router via
useIonRouter()
-
Support for Nuxt routing utils like
definePageMeta()
-
Theming
-
Override styling via exposed CSS props
-
Built-in utility functions
-
via the auto-imported compassables
-
Swiping gestures
-
Animations
-
...
What is Capacitor
- Open source native bridge; allows you to run a web app on a mobile device
- Easy access to common device features; camera, geolocation, file picker, ... (things you need to interact with the device you're building for)
- Run on IOS and Android devices
Getting Started with Nuxt/Ionic
- Create a starter Nuxt 3 app
npx nuxi dev
- Add Nuxt/Ionic Module
npm install @nuxtjs/ionic -D
- Set up routing
- Create a
/pages
directory. - Create an
/pages/index.vue
page. - Create a
/pages/resources.vue
page.
- Use components & Icons
- Update the theme
- Create a
/theme
directory. - Create a
/theme/varibles.css
file
paste the CSS variables code
- Update
nuxt.config.ts
- load the app
npx nuxi dev
- Then enable dark mode from the chrome dev tools in the browser.
- It should change to dark mode
Adding Capacitor to your Nuxt/Ionic project
- Install Ionic CLI
- Gives us access to some capacitor commands.
npm install -g @ionic/cli
- Enable capacitor integration
ionic integrations enable capacitor
-
Add an android or IOS project
ionic capacitor add android
-
Build web code we need to sync the android project with a web build version of our app.
- Create a build
npx nuxi generate
- Sync project with capacitor.
npx cap sync
-- This will copy the build to our android project
- Open and run on mobile
- Start the app on a simulated android device
- Android studio and SDK should already be installed on your machine.
- You also need to have a device created to be able to pull up an emulator
npx cap run android
pick an emulator
It should open up and run
- For IOS The process is similar for IOS. You need XCode and Xcode CLI installed Then replace any command that had android in it with IOS
Deploying on Appflow
A cloud app management system built by ionic a paid service
main features
-
generates native binaries in the cloud
-
Real-time code deployments/updates to users (live updates) (push changes to users using the web interface without needing the app store approval process)
-
Automates app delivery to app stores
-
connect your web repo using your version control of choice
-
Create the web build that you built locally
-
App flow will create a native build
-
Allows you to deploy to app stores
-
Allows you to push live updates
Ionic Resources
- Nuxt/Ionic Docs
- Nuxt/Ionic playground
- Nuxt/Ionic GitHub
- Ionic Docs
- Capacitor Docs
- Appflow Docs
- Nuxt/Ionic Simple Demo App GitHub Repo
- Ionic Discord
-
You can turn any web project you have into a mobile app using Capacitor, Ionic components are just what give you the native look and feel.
Good solutions for working with Icons in Nuxt
- Nuxt-icon, uses Iconify. Nuxt's author is working on making it the one recommended solution.
Why use Nuxt when you can do it yourself with Vite? (Nuxt Vs. Vite functionalities differences)
-
Nuxt provides an echo system for ready-to-use solutions
-
Nuxt is stable
-
Nuxt team works hard to make everything work out of the box
-
The Nuxt team always recommends one Nuxt module solution that keeps working and behind the scenes they work on improving it.
-
Vite and Nuxt serve different goals.
-
Nuxt is a complete framework; it gives you conventions and a lot of conveniences, ... If you follow the recommended paths in Nuxt you'll be very efficient and Nuxt will abstract away a lot of the underlying complexities for you.
-
Vite covers a lot of the common features that are shared between frameworks. When you go into SSR with Vite, you have to set up your SSR architecture (how to handle data fetching, routing page transitions, ...) all of these Vite is un-opinionated, so you have to figure that out yourself. It is not an easy feat to put everything together yourself.
-
Vite is a shared common tooling layer that meta frameworks are built on.
-
So the question is are you trying to build your meta-framework using Vite, or do you want to use a meta-framework that is already polished (Nuxt)
How do you balance your primary job with maintaining open-source projects?
- Managing multiple big projects is a challenge.
- Find the right people.
- Build a team.
- Delegate.
- Let them take on more responsibilities.
Does npx nuxi generate
scale? Is there a plan for an ISR (incremental static regeneration)?
-
When you use
nuxi generate
in Nuxt 3 it generates a fully static output that, during the build time, pre-renders every possible route and their data in the payload and you can deploy it on any hosting service. -
For a normal website (with the build of pages) it is possible at build time, but when we have lots of articles the build time gets longer and longer. And like a shop, we don't need to rebuild every possible page at runtime.
-
Nuxt 3 has a built-in server that is portable enough to be hosted anywhere. If there is any page that we are sure it's not going to be regularly changed we define them on the build time they are prerendered and the rest of the pages would be directed on the runtime on an ISR basis.
-
Route rules allow for this kind of hybrid rendering for ISR
-
Static files are generated but are also integrated with the platform. This (currently) works for Vercel and Netlify. They are also natively bundled. And ISR works out of the box.
-
What we have to do is define which routes we want to be generated on demand.
-
For Netlify you don't need to use
Nuxt generate
you can useNuxt build
. You can specify what routes you want to pre-render by default so they will be static. Then any new pages will hit the lambda and will be cached until the next deployment. -
It currently works with Nuxt 3 on Netlify and they are working with Vercel to have it supported.
-
You can also use a caching layer and normal NodeJs and it will work as well.
Are there any other big meta frameworks like Nuxt that use Vite?
-
Quaiser already supports using Vite.
-
Vite press, a static site generator.
-
Isles, a Vite-based meta-framework that uses island architecture.
-
Astro is a Vite-based meta-framework that's framework agnostic.
Which is better to create a large app Next.js or Nuxt.js?
- They both work.
- Both are fast.
- It's hard to compare performances. Marketing benchmarks are not accurate.
- Pick the one that makes you more productive.
- Just because a lot of people are using a tool doesn't mean it's best for you.
- Evaluate based on your needs and preferences.
- Both Vue and react are massively popular and both provide good community support, so go with the one that better fits your mental model.
Micro-frontend Architecture in Nuxt 3?
- They had some experiments to support web components to integrate different apps. Through experience, they found out it doesn't work because Nuxt itself is like a host it can be integrated with some sub-apps like components, so they created a system called extends which can combine different apps and use Nuxt like a host.
- So right now it's not in the plan to support Microfrontend,
- but there are hopes, as they are working on a new feature called component islands. Component islands are standalone and they can integrate with the whole application. They can, at some point, extract it and support different frameworks, Those components could run on any framework and be hydrated by themselves.
Can you talk about clean architecture and why we should or should not apply it to front-end development?
- If you're working with a frontend codebase typically your framework dictates the way you organize code already so you'd best follow the conventions of the framework you've chosen, instead of imposing too much architectural complexity on yourself.
- Typically (these design patterns of clean architecture) these conventions are designed for situations where you have a really big team, for example, 100 devs working in a huge organization. If you're not in such an environment you don't have that problem.
- Could be a premature organization for writing code.
- A lot of front-end projects have smaller teams, unlike large back-end projects.
- Most front-end projects don't need to go there.
How to use concurrency and interval properties in NuxtJs static mode, when there are many headless cams data API calls on hundreds of pages?
- No specific option for it, it's automated. This is handled by Nitro.
- Or since you have more than a hundred pages, it's probably better to use hybrid rendering and ISR to generate on demand. Instead of pre-rendering all of them.
What is the process of becoming a Nuxt ambassador?
- Right now there is no defined process.
- Thinking of a new program that allows everyone to get involved.
- They have the "Nuxt Insiders" that meets weekly to discuss their work, but this is mostly for module authors and contributors.
- Anyone is an ambassador by advocation, the Nuxt team is thinking about how to get ambassadors rewarded. Info will be given on this next year.
- Everyone is encouraged to write articles, and explain any project that uses Vue, Vite, or Nuxt. Until you get noticed.
What are the next big steps for Nuxt, Vite, and Vue?
- For Vite. working on Vite 4, perhaps in a month. The main theme of the upgrade is upgrading to roll-ups 3 and other things that are related to the react echo system.
- For Nuxt: Component islands, improvements for hybrid rendering (the ability to specify at the page level). Improving modules to work seamlessly in Nuxt; image, auth. And lots of docs.
- For Vue: SSR-related improvements (built-in ability to lazy or on-demand hydrate async components), Vue Promote (new compilation strategy for Vue components) similar to solid Js, should result in better performance and better memory footprint, won't affect the way you write code, but the code should be faster, lighter, and more performant. Most improvements should also automatically benefit Nuxt users.
Nuxt In Large Companies
Nuxt as a backbone of a scalable platform
JUMBO Showcase
Well-known offline and online grocery chains in the Netherlands and Belgium. They develop a lot of their software in-house. Over 300 devs working First, they grabbed an off-the-shelf solution. They started to add a couple of Vue components. They grew and had different teams to specifically handle different customer journeys. They switched from a monolith to a distributed application architecture
As the system evolved the complexities increased.
They were using Vue and their apps were using Vue components.
So they build a component library.
A lot of maintenance for all these micro apps, and for the component library
What they wanted instead
- Modular landscape
- Independent moving parts (easily add or remove apps)
- Simplify dependencies (simplify maintenance)
They considered using Nuxt as a simple app that would connect all these modules. They discarded this idea because they didn't want people to be working on the same codebase, depending on other teams' features to be delivered to deliver theirs.
Instead, they built their system
- Built a component library.
- Already part of their design system (to facilitate work between designers and devs)
- All components go here
- CMS
- A means of getting data into your system
- It has to be headless
- Wrote an adapter to allow any CMS to be compatible with the system
- Connected to all the components in the component library
- Content Service
- Newly built system (NodeJs)
- Brains of the platform
- Connects other systems
- validates data models
- does routing
- Content Renderer
- Gets content from content service
- Needs to work with VueJs component
- Support SSR
- Nuxt is an obvious candidate
Challenges
- Map 100s of components & props to one editor UI (To solve this they extract component properties from Vue and give them back to the CMS as config. They can tell the CMS editor that a component has certain props.)
- Only ship what you need to reduce load (Nuxt components module allows them to read into all of the components that are being used on that page. So they tree shake everything per page and provide a per-page bundle)
It works for them. But they do use caching.
Which CMS does JUMBO use?
- Adobe experience manager.
- An enterprise-level CMS.
- What you see is what you get editing.
- It can also render and cache pages well.
Nuxt Extends
- Allow you to extend one Nuxt application with another one.
- Theming is a perfect example of Nuxt extends usage.
How it works in code.
Inspecting the "nuxt-commerce-theme" in the node-modules. You'll see that this package comes with the nuxt.config.ts
file and a vue components folder that you can use in your app.
So now we can add these components to our Nuxt app.
So Nuxt extends to allow you to build reusable Nuxt themes.
Pinceau
piceau-
A new package for the Vue community.
-
Aims at simplifying your work with Vue components by giving you a set of tools that will help you write and maintain CSS across your app.
-
Design tokens configurations.
-
CSS functions.
-
Computed styles.
-
Variants.
-
Pinceau config is compatible with the design tokens format.
-
Pinceau config is compatible with design tools like Figma and Sketch
End-to-End Type Safety with Nuxt and tRPC
What is type safety?
Is when the compiler validates types while compiling, throwing an error if you assign the wrong type to a variable.
It just reduces a handful of bugs that you might not see otherwise.
What is end-to-end type safety?
End-to-end type safety is having a single source of truth for your types across all the layers of your app.
If the User object changes for one of your layers, for the database for example, then it is going to require a lot of maintainabilities and more work. Can create issues, headaches, and a lot of work.
Type Script Remote Procedure Call (tRPC)
- tRPC is a method of exposing server functions to the client in a typesafe manner.
- tRPC is only a solution when you're using type script on the backend and the front end.
- One way of thinking of tRPC is an alternative to REST and GraphQL
How to use tRPC in a Nuxt application
- Install dependencies
npm install @trpc/client @trpc/server trpc-nuxt zod
- Add
trpc-nuxt
to yournuxt.config.ts
@trpc/client
to make typesafe API calls from your client.@trpc/server
for tRPC endpoints and routerstrpc-nuxt
Nuxt module built & maintained by wobsorianozod
server-side input validation
Another example; an Auth Router with a login procedure.
This is the entry point for your API and exposes the tRPC router. This is where you can expose your API to middleware to manage things like CORS.
Merging the routers into a centralized appRouter
The AppRouter type signature is passed to trpc-nuxt's createTRPCNuxtPorxyClient
function.
Using provide
to inject trpc
into the client.
Using it will give you autocompletion on the client side. Clicking on the query in the index.vue file (fort end) takes you directly to your back end (helloRouter.ts) Refactoring queries and procedures. Changing them on the client site will change them automatically on the backend.
Does tRPC provide runtime validation or is it all about types for use at development time?
- Because it's only importing and exporting types. None of the code will be a part of the client. So once this is shipped the front end or the client has absolutely no idea of the backend, and that's one of the big benefits it's a very lean solution to this problem.
Is trpc-nuxt ready for production? Not yet.
Add 3D to your Nuxt app with Three.js
- ThreeJS is a library that leverages WebGL to render 3D scenes on the web. (Basically makes it easier to use 3D in the browser)
First, we need to draw something
Then we need a camera to see it
ThreeJs has 2 types of cameras. We'll use perspective because it's the most similar to the human eye.
A scene to put it all together
A renderer to show it
This won't work cause we didn't pass the reference for these canvas elements
Use TemplateRefs + Lifecycle hooks
It renders but it looks like an image. No interaction.
This is because we only render it once.
The Loop
The requestAnimationFrame
function allows us to create a loop that runs at the browser's refresh rate.
We have a sphere that animates smoothly.
Be mindful of reactivity
Nuxt + ThreeJS
The 3D world is not optimal for SSR, it might work but performance will not be optimal.
Nuxt allows you to use the ClientOnly
component to render a component only on the client side.
Or you can add the .client
suffix to the component file
Next steps
- Add light and different materials (MeshStandardMaterial, MeshPhongMaterial)
- Use textures (TextureLoader)
- Add OrbitControls
- Add a model via GLTFLoader
- Animations with GSAP
Resources
Any performance gotcha's that are important to watch out for when using ThreeJs with Nuxt?
- Try to update all the instances without reactivity.
- You can use a shallow ref and wrap to manage it, especially if using composable.
- Extract the logic from the experience and put it composables (all the logic for the render)
UNJS and Nuxt 3
Presentation linkunified Javascript tools.
unjs/unbuildMade for building Nuxt 3 modules and packages
unjs/changelogenBeautiful change logs using conventional commits Used for Nuxt 3 releases notes and change-logs
unjs/unplugin Unified plugin system for Vite, Rollup, Webpack, and more.
unjs/unimport A system that makes imports automated. Smartly tree shaken. ...
unjs/ofetchBetter fetchAPI natively works on node, browsers, and workers.
Provides universal $fetch
for Nuxt 3.
node-fetch-native If you have a custom server or nodejs project. Future proof. Supports native fetch implementations for the server.
unjs/h3Minimal h(ttp) framework build for high performance, composition, and portability Makes it easier to scale up the project. Fast. You can use h3 for any custom solution you have. Nitro is built on h3.
unjs/unstorage Universal storage layer. Cross-platform, Multi Driver KV storage powering Nuxt 3 and Nitro cache. Persistent storage is one of the essential parts of making a universal framework. You can combine different stores into a simplified key and value storage layer. Used by Nuxt for caching and deployment Works out of the box for any deployment platform
unjs/listhen
- Elegant HTTP listener.
- Powering Nuxi CLI
- Small package with one single purpose to listen
unjs/c12
- Smart configuration loader.
- Powering Nuxt 3 and Nitro with extends and theming support.
unjs/ipx
- High-performance, secure, and easy-to-use image proxy based on Sharp and libvips.
- Powering Nuxt Image and Next.js images on Netlify.
- If you want to optimize your images you can use Nuxt image, or if you have any custom solutions, or if you want to host it on a private CDN you can directly use ipx.
unjs/untyped
- Generate config, docs, and types from schema and more
- powering Nuxt 3 config and schema
- Depends on one single schema config which is typescript, comments to define documentations and defaults, and normalization. Untyped generates the code and documentation.
unjs/giget
- Download templates and git repos
- Powering nuxi init
unjs/nitro
- A powerful toolchain and runtime framework from the UnJs ecosystem to build and deploy any javascript server. anywhere.
- A meta-framework for Unjs.
- Combines different packages to make an experience similar to Nuxt but for the server side. ??
What is headless?
Example app using Storyblok and Algolia with Nuxt- They don't come with their own UIs they are servers or software that we can communicate with by using an API.
- Examples
- Storyblok
- A headless content management system (CMS)
- You add some content on Storyblok and fetch this data using an API in your NuxtJs website.
- Algolia
- A search and discovery platform
- You can add results to the index and then search this index through your website
- Also has a recommended API that learns from what customers are doing on your website. So it can (for an e-commerce website) recommend to the customer products based on their previous search.
- Storyblok
Stack
- Nuxt Tailwind
- Nuxt Image
- Storyblok Nuxt
- Nuxt Algolia
Nuxt Security
Security module for Nuxt based on OWASP Top 10 and Helmet Just by importing this module, you're making your app a bit more secure.
Supercharged <head>
management
Vue head v1 and the future of SEO with Nuxt v3
HTML Metadata, Meta Info, Meta tags, Head tags
All the same. Managing machine-readable elements and attributes outside the Vue render tree for SSR and DOM.
VueUse Head
useHead
composable
What does being a VueUse composable mean?
Accepts reactive arguments: ref, computed, and reactive getter.
Cleans up the side effect automatically, if it has any.
Avoid wrapping in watchers.
What's going on with useHead
-
Fully typed
useHead
-
Reactive getter support
-
Array support
-
Prop promises
-
DOM event handlers
-
unhead
- New engine powering VueUse Head v1, now part of UnJS
- Side-effect based: Less aggressive removal of tags and attributes. No more non-essential states in the DOM.
- DOM rendering optimizations. 5x faster (-10ms CPU time for an average site)
- Powered by hookable. Same hook system as Nuxt.
-
Server-Only Tags
- Rendering tags that would only render on the server. Such as inputs to assets URLs.
Making SEO Easier
- useSEOMeta
- Over 100+ definitions, powered by tree shaken.
- intended to be tree shaken from the client build
- Official Nuxt support coming soon (for now use it with manual imports, you can just import directly from the client)
Practical Nuxt 3 SEO Tips
Performance
- Nuxt server components (Stop hydrating things on the client side)
- nuxt-fontaine
- @nuxtjs/partytown
- @nuxtjs/critters
- issues (scan your site and give you a lighthouse report for it to fix accessibility and SEO issues)
SEO
- nuxt-schema-org
Do these meta tags have to be rendered server-side or will crawlers still find them when they're rendered on the client side?
Rendering on the server side is a safe option. Google said we're going to run your JS, so it might be fine. However, server rendering them is highly recommended. No reason not to, unless you have a single-page app (SPA), in those instances Nuxt 3 will read your head config and throw that in the SPA's HTML template.
Can useHead be used in custom composable?
useHead can be used anywhere, it's kind of like Pinia, it has a global state that we can reference rather than relying on the specific Vue setup state. If you want to use useHead in middleware, custom composable go for it. If you have any issues with it make an issue on the Nuxt repo or VueUseHead and they'll look into it.
When would you choose to link CSS via useHead versus the CSS option in nuxt.config
?
The Nuxt CSS option does some CSS optimization, inlining it. If you use useHead it would be a link and you'd have to make an HTTP request for the style sheet. Stick to the CSS option, unless you need some sort of async script, that is not essential for your app you can use useHead for it.
Beyond Static: Building with Nuxt 3 and Nitro
In Nuxt 3, it is possible to create fully hybrid sites. Which have individual route rules, which enable different rendering strategies for different sections of your website.
To explore that we'll create a little blog site and see what that might be like to deploy.
If you want to start a new project. It's recommended to go to nuxt.new There are a couple of templates there, but some interesting things are coming soon.
You can follow the Nuxt official installation DocsOpen a terminal and run npx nuxi init appName
app.vue
-- is the entry point to our app.
nuxt.config.ts
-- No need to do anything here, for now.
nuxt.json
-- has nuxt as a dev dependency and the dependencies we just installed should be automatically added
tsconfig.json
-- is going to enable our editor IDE to know a little bit about the Nuxt environment, it's running in.
Start the dev server
Add a <script>
tag to the app.vue
file
and import the @picocss/pico
dependency.
It will add some styles to the app. That is going to make it a little bit nicer.
- Add navigation to
app.vue
<NuxtLink>
is a drop in replacement for an<a>
link.
- Replace the
<NuxtWelcome />
with<NuxtPage />
<NuxtPage />
component is going to render whatever the active route is.
- Create a
pages
directory in the root folder. - Create an
/pages/index.vue
andpages/about.vue
pages - Fetch some Json placeholder inside the
pages/index.vue
page.
- We can use a transform hook in the useFetch options, to validate the response, by creating a new schema inline, an array of posts, then parsing the data, it's going to force us to know if something is going wrong and throw an error. Also, it's going to provide a nicely typed response to have access to things like
post.id
in the template.
- Generate a
postSchema
using Zod.
- Loop over the posts and render them on the page.
- Update the
app.vue
page.<NuxtPage />
will
- Run a dev server
$ npm run dev
and check the result.
- Create
/pages/posts/[id].vue
Here's the result when clicking on a post.
Finally to deploy we might want to have some configurable rules at nuxt.config.ts
.
We can also create a server API route server/api/test.ts
We might make this accessible to other apps and turn on cors mode in this case at nuxt.config.ts
Turn off the dev server $ ctrl c
If you run npm build
a node server will be built for you. If you deploy it to any hosting service, Vercel, Netlify, Cloudflare Pages, ... Nuxt will try and detect the environment and create the right kind of build.
If you want to test it locally you can pass the NITRO_PRESET environment variable or just configure it in nuxt.config
Everything is going to be put into a single folder that can be deployed. Any needed dependency will also be located in this folder, so it will not need to be installed again. Normally it's a .output
folder, but in this case, it's a .netlify
folder.
There's also a dist
folder which will have all the things that Netlify is going to the server from CDN. This will also include _headers
and _redirects
files which will configure Netlify to use builder functions.
Deploying the output to Netlify will give you a URL to test it on. Using the link we can visit the site and see it working as expected.
In the terminal, we can have a look at the headers for requests
If we fetch the home page, every time we fetch it's a new request, a newly rendered page (Age=0)
For the about page, the first fetch request is the age=0
, but on subsequent requests, it keeps going up. Because it's never going to be generated again it's a fully static page. The same is true for posts pages.
It means that you don't need to redeploy when you change the content of CMS if you're using hybrid rendering.
Tools To Explore
- Docus -- Create your own Docs with Nuxt.
- Nuxt typography
- Nuxt Studio (still in Beta)
- Vuetelescope.com
- sidebase.io -- An auth module
- Nuxt (3) Module Builder
- Vue storefronts
- Strapi