{"id":7666,"date":"2024-02-07T16:18:45","date_gmt":"2024-02-07T09:18:45","guid":{"rendered":"https:\/\/www.briswell-vn.com\/?p=7666"},"modified":"2024-04-02T13:11:38","modified_gmt":"2024-04-02T06:11:38","slug":"nuxt-the-intuitive-web-framework","status":"publish","type":"post","link":"https:\/\/www.briswell-vn.com\/en\/news\/nuxt-the-intuitive-web-framework\/","title":{"rendered":"Nuxt &#8211; The Intuitive Web Framework"},"content":{"rendered":"<p><\/p>\n<h2><span class=\"notion-enable-hover\" data-token-index=\"0\">Introduction<\/span><\/h2>\n<p>Nuxt is an open-source JavaScript framework based on Vue.js. The latest version is currently Nuxt 3. Nuxt 3 is an upgrade from the Nuxt framework based on Vite, Vue 3, and Nitro with support from Typescript.<\/p>\n<p>Nuxt simplifies the development of web applications under Server-side rendering (SSR) and Static Site Generation (SSG) methods, in addition to other methods such as CSR, ISR, ESR, and SWR. Nuxt provides a structured and convention-based approach to building Vue.js applications, allowing developers to focus on developing features instead of dealing with complex configurations.<\/p>\n<p>&nbsp;<\/p>\n<h2>Why use Nuxt?<\/h2>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Server-side Rendering (SSR)<\/span>:<\/strong> Nuxt enables server-side rendering, which means that the Vue.js components are pre-rendered on the server before being sent to the client. This improves initial page load performance and allows for better search engine optimization (SEO), as search engines can index fully rendered content.<\/p>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Static Site Generation (SSG)<\/span>:<\/strong> Nuxt can generate static HTML files at build time, which can be served directly from a CDN or static hosting service. This approach eliminates the need for server-side rendering on each request, resulting in faster page loads and improved scalability.<\/p>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Faster rendering<\/span>: <\/strong>The Vue Virtual DOM (VDOM) has been rewritten from the ground up, allowing for better rendering performance. On top of that, when working with compiled Single-File Components, the Vue compiler can further optimize them at build time by separating static and dynamic markup. This results in faster first rendering (component creation) and updates, and less memory usage. In Nuxt 3, it enables faster server-side rendering as well.<\/p>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Smaller bundle<\/span>:<\/strong> With Vue 3 and Nuxt 3, a focus has been put on bundle size reduction. <span style=\"font-weight: 400;\">By implementing the tree-shaking technique, the production environment of the application will exclude Vue&#8217;s features such as template directives and components that are not used when bundling. This can help reduce file size,<\/span><span style=\"font-weight: 400;\"> download faster, and improve loading time for applications. This way, a minimum Vue 3 application can be reduced to 12 kb gzip compressed.<\/span><\/p>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Extensive ecosystem:<\/span><\/strong> Nuxt has a diverse development ecosystem contributed by the community. You can take advantage of community plugins, modules, and tools to extend and customize your application.<\/p>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Support Typescript<\/span>:<\/strong> Although Nuxt 2 already supports Typescript, Nuxt 3 has improved Typescript support, you can use Type-checking and other tools that Nuxt provides based on Typescript.<\/p>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Simplified development<\/span>:<\/strong> With Convention Over Configuration, Nuxt reduces boilerplate code and simplifies the development process. It comes with built-in features such as routing, code splitting, and state management, enabling you to focus on building your application logic rather than worrying about setup and configuration.<\/p>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Better <b>experience <\/b><b>for developers<\/b><\/span>:<\/strong> Nuxt offers a robust development environment with features like hot module replacement, automatic reloading, error handling, and more innovative tools like debugging, testing, dev tools, and others. These features streamline the development workflow, allowing for faster iterations and better debugging capabilities.<\/p>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Scalability and performance<\/span>:<\/strong> Nuxt optimizes your application&#8217;s performance through features like automatic code splitting, lazy loading, and pre-rendering. It ensures that only the necessary JavaScript is loaded for each page, resulting in faster load times and a better user experience. Additionally, Nuxt&#8217;s modular architecture allows for easy scalability <span style=\"font-weight: 400;\">when upgrading your application to higher versions.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2>Some built-in supported technologies<\/h2>\n<ol>\n<li><a href=\"https:\/\/webpack.js.org\/\">Webpack 5<\/a><\/li>\n<li><a href=\"https:\/\/vitejs.dev\/\">Vite<\/a><\/li>\n<li><a href=\"https:\/\/nitro.unjs.io\/\">Nitro<\/a><\/li>\n<li><a href=\"https:\/\/vuejs.org\/\">Vue 3<\/a><\/li>\n<li><a href=\"https:\/\/router.vuejs.org\/\">Router 4<\/a><\/li>\n<li><a href=\"https:\/\/www.typescriptlang.org\/\">Typescript<\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h2>Feature comparison<\/h2>\n<p>In the table below, there is a quick comparison between 3 versions of Nuxt:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-7690 size-full\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06143637\/feature-comparison.png\" alt=\"\" width=\"737\" height=\"816\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06143637\/feature-comparison.png 737w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06143637\/feature-comparison-271x300.png 271w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06143637\/feature-comparison-226x250.png 226w\" sizes=\"auto, (max-width: 737px) 100vw, 737px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h2>Directory structure<\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-7706 size-full\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06160101\/directory-structure2.png\" alt=\"\" width=\"212\" height=\"807\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06160101\/directory-structure2.png 212w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06160101\/directory-structure2-79x300.png 79w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06160101\/directory-structure2-66x250.png 66w\" sizes=\"auto, (max-width: 212px) 100vw, 212px\" \/><\/p>\n<p><strong>.nuxt:<\/strong> Nuxt uses the <strong>&#8220;.nuxt\/&#8221;<\/strong> directory during development to create your Vue application.<\/p>\n<p><strong>.output:<\/strong> Nuxt creates the <strong>&#8220;.output\/&#8221;<\/strong> directory when building your application for <span style=\"font-weight: 400;\">the production environment.<\/span><\/p>\n<p><strong>assets:<\/strong> The <strong>&#8220;assets\/&#8221;<\/strong> directory is used to add all the content of the site that the builder (Webpack or Vite) will process. The folder usually contains the following file types: Stylesheets (CSS, SASS, etc.), Fonts, and images will not be served from the <strong>&#8220;public\/&#8221;<\/strong> directory.<\/p>\n<p><strong>components:<\/strong> The <strong>&#8220;components\/&#8221;<\/strong> directory is where you put all your Vue components which can then be imported inside your pages or other components.<\/p>\n<p><strong>composables:<\/strong> Nuxt 3 uses the <strong>&#8220;composables\/&#8221;<\/strong> directory to automatically import your Vue composables into your application using auto-imports.<\/p>\n<p><strong>content:<\/strong> Supports .md, .yml, and .csv files to create a CMS for your application.<\/p>\n<p><strong>layouts:<\/strong> Used to change the look and feel of your application. An application can have multiple layouts for example: admin layout, guest layout, and registered clients layout. These layouts will be reused on different pages to handle their appearance (sidebar, menu, footer, etc.). During installation, Nuxt CLI provides default layouts\/default.vue layout and is used on all pages.<\/p>\n<p><strong>middleware:<\/strong> Used to handle requests before the page is displayed to the user. Middleware allows you to perform tasks such as authentication, access checking, activity logging, and other custom processing before the page is rendered.<\/p>\n<p><strong>modules<\/strong>: Nuxt scans the <strong>&#8220;modules\/&#8221;<\/strong> directory and loads them before starting. It is a good place to place any local modules you develop while building your application.<\/p>\n<p><strong>node_modules:<\/strong> The package manager (npm or yarn or pnpm) creates the <strong>&#8220;node_modules\/&#8221;<\/strong> directory to store the dependencies of your project.<\/p>\n<p><strong>pages:<\/strong> Nuxt provides file-based routing to create routes in your web application using Vue Router.<\/p>\n<p><strong>plugins:<\/strong> Nuxt automatically reads the files in your <strong>&#8220;plugins&#8221;<\/strong> directory and loads them at the creation of the Vue application. You can use the .server or .client suffix in the file name to load a plugin only on the server or client side.<\/p>\n<p><strong>public:<\/strong> The <strong>&#8220;public\/&#8221;<\/strong> directory <span style=\"font-weight: 400;\">contains static files and provides resources directly to HTTP requests without additional processing logic. For example, you can place image files, font files, robot.txt, favicon.ico, or other static files.<\/span><\/p>\n<p><strong>server:<\/strong> Nuxt automatically scans files inside these directories to register API and server handlers with HMR support: ~\/server\/api, ~\/server\/routes, ~\/server\/middleware.<\/p>\n<p><strong>utils:<\/strong> Nuxt 3 uses the <strong>&#8220;utils\/&#8221;<\/strong> directory to automatically import helper functions and other utilities throughout your application using auto-imports.<\/p>\n<p><strong>.env:<\/strong> Nuxt CLI has built-in dotenv support in development mode and when running <code>nuxi build<\/code> and <code>nuxi generate<\/code>. In addition to any process environment variables, if you have a .env file in your project root directory, it will be automatically loaded at build, dev, and generate time, and any environment variables set there will be accessible within your nuxt.config file and modules.<\/p>\n<p><strong>.gitignore:<\/strong> This will list the names of files and folders in the project that you do not want to be parsed every time you manipulate git.<\/p>\n<p><strong>.nuxtignore:<\/strong> The .nuxtigore file allows Nuxt to ignore layouts, pages, components, composables, and middleware in the project root directory (rootDir) during the build process. The .nuxtigore file follows the same specifications as the .gitignore and .eslintigore files, where each line is a glob pattern indicating which files should be ignored.<\/p>\n<p><strong>app.config.ts:<\/strong> Used to configure and customize the Nuxt application.<\/p>\n<p><strong>app.vue:<\/strong> The main component in Nuxt 3 applications.<\/p>\n<p><strong>nuxt.config.ts:<\/strong> The nuxt.config.ts file contains your custom Nuxt configuration and allows you to configure your application, these configurations include head title and associated styles and scripts, middlewares, plugins, authentication, modules, and even APIs.<\/p>\n<p><strong>package.json:<\/strong> Contains all the dependencies and scripts for your application.<\/p>\n<p><strong>tsconfig.json:<\/strong> Nuxt automatically creates a .nuxt\/tsconfig.json file with other reasonable defaults. You just need to create a tsconfig.json file outside of the root and import it from the initialized Nuxt file.<\/p>\n<p>&nbsp;<\/p>\n<h2>Feature<\/h2>\n<h3><strong>Auto-imports<\/strong><\/h3>\n<p>Auto-import is a new feature developed by Nuxt 3 which is quite convenient. All files in components, composables, utils are automatically recognized and just need to name the component, composables, etc. without having to import again. Auto import is enabled by default but can also be turned off in the nuxt.config.ts file as follows:<\/p>\n<pre>export default defineNuxtConfig({\r\n  imports: {\r\n    autoImport: false\r\n  }\r\n})\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>Rendering Modes<\/strong><\/h3>\n<p>Nuxt supports different rendering modes, universal rendering, and client-side rendering but also offers hybrid rendering and the possibility to render your application on CDN Edge Servers.<\/p>\n<p>&nbsp;<\/p>\n<h3><strong>Server Engine<\/strong><\/h3>\n<p>Nuxt 3 is powered by a new server engine, <a class=\"notion-link-token notion-focusable-token notion-enable-hover\" href=\"https:\/\/nitro.unjs.io\/\" rel=\"noopener noreferrer\" data-token-index=\"1\"><span class=\"link-annotation-unknown-block-id--197090588\">Nitro<\/span><\/a>.<\/p>\n<ol>\n<li>Cross-platform support for Node.js, Browsers, service workers, and more.<\/li>\n<li>Serverless support out-of-the-box.<\/li>\n<li>API routes support.<\/li>\n<li>Automatic code-splitting and async-loaded chunks.<\/li>\n<li>Hybrid mode for static + serverless sites.<\/li>\n<li>Development server with hot module reloading.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h2>Getting started with Nuxt<\/h2>\n<p><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Prerequisites: <\/span><\/strong>Nodejs version 16.0.0 or later.<\/p>\n<p>A simple setup with Nuxt CLI, used with the nuxi command will help you to install and manage all Nuxt components. With npx installed, you can easily create a project with the command below:<\/p>\n<pre>&gt; npx nuxi init project-name<\/pre>\n<p>As an output you will get this.<\/p>\n<pre>Nuxt project is created with a v3 template. Next steps:\r\n\u203a cd project-name\r\n\u203a Install dependencies with npm install or yarn install or pnpm install\r\n\u203a Start development server with npm run dev or yarn dev or pnpm run dev<\/pre>\n<p>Install dependencies.<\/p>\n<pre>yarn install<\/pre>\n<p>And here is the new project structure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7728 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06171557\/init-project.png\" alt=\"\" width=\"213\" height=\"615\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06171557\/init-project.png 213w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06171557\/init-project-104x300.png 104w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06171557\/init-project-87x250.png 87w\" sizes=\"auto, (max-width: 213px) 100vw, 213px\" \/><br \/>\nYou should now be able to start your Nuxt application in development mode.<\/p>\n<pre>yarn dev -o<\/pre>\n<p>Then visit the browser at <a href=\"http:\/\/localhost:3000\">http:\/\/localhost:3000<\/a>, to see the newly created Nuxt application running.<\/p>\n<p>By default, the app .vue file is the core component that acts as the entry point and renders its content for each application route. Is the root component of your Nuxt application and represents the layout and structure that wraps all other components. It usually contains the main layout, navigation, and any global components or logic that need to be shared across multiple pages.<\/p>\n<p>Change a bit the content in the app.vue file and see the display.<\/p>\n<pre>&gt; app.vue\r\n&lt;template&gt;\r\n  &lt;div&gt;\r\n    &lt;h1&gt;Welcome to the homepage&lt;\/h1&gt;\r\n  &lt;div&gt;\r\n&lt;\/template&gt;<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7732\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06174754\/app.vue_.png\" alt=\"\" width=\"1427\" height=\"181\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06174754\/app.vue_.png 1427w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06174754\/app.vue_-300x38.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06174754\/app.vue_-1024x130.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06174754\/app.vue_-768x97.png 768w\" sizes=\"auto, (max-width: 1427px) 100vw, 1427px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h2>Features<\/h2>\n<h3><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Pages<\/span><\/strong><\/h3>\n<p>This is where your Application Views and routes will be located. By default, Nuxt uses a file-based routing system, where each .vue file in the <strong>&#8220;\/pages&#8221;<\/strong> directory corresponds to a route.<\/p>\n<p>To use pages, create the file pages\/index.vue and add the &lt;NuxtPage \/&gt; component to app.vue (or remove app.vue when you want pages\/index.vue for default entry). Pages are Vue components and can have any valid extension that Nuxt supports (by default, .vue, .js, .jsx, .mjs, .ts, or .tsx). Nuxt will automatically generate routes for every page in your <strong>&#8220;~\/pages\/&#8221;<\/strong> directory.<\/p>\n<pre>&gt; app.vue (app.vue default entry)\r\n&lt;template&gt;\r\n  &lt;NuxtPage \/&gt;\r\n&lt;\/template&gt;\r\n\r\n--- .vue ---\r\n&gt; pages\/index.vue\r\n&lt;template&gt;\r\n  &lt;p&gt;Home Page&lt;\/p&gt;\r\n&lt;\/template&gt;\r\n\r\n&gt; pages\/about.vue\r\n&lt;template&gt;\r\n  &lt;p&gt;About Page&lt;\/p&gt;\r\n&lt;\/template&gt;\r\n\r\n--- .ts ---\r\n&gt; pages\/index.ts\r\nexport default defineComponent({\r\n  render () {\r\n    return h('h1', 'Home page');\r\n  }\r\n});\r\n\r\n--- .tsx ---\r\nexport default defineComponent({\r\n  render () {\r\n    return &lt;h1&gt;Home page&lt;\/h1&gt;;\r\n  }\r\n});<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>Layouts<\/strong><\/h3>\n<p>Layout plays an important role in determining the overall structure and design of the pages in your application. Layouts in Nuxt represent a reusable template that wraps around your page components and provides a consistent look and feel across multiple pages. Can create many different layouts like login layout or homepage layout or many other layouts.<\/p>\n<blockquote><p><em><span style=\"color: #ff0000;\">If you only have a single layout in your application, we recommend using app.vue with the &lt;NuxtPage \/&gt; component instead.<\/span><\/em><\/p><\/blockquote>\n<p>If nothing is set, Nuxt will specify default .vue as the default.<\/p>\n<pre>&gt; app.vue\r\n&lt;template&gt;\r\n  &lt;NuxtLayout&gt;\r\n    &lt;NuxtPage \/&gt;\r\n  &lt;\/NuxtLayout&gt;\r\n&lt;\/template&gt;\r\n\r\n&gt; layouts\/default.vue\r\n&lt;template&gt;\r\n  &lt;div&gt;\r\n    &lt;h1&gt;This our default layout&lt;\/h1&gt;\r\n    &lt;slot \/&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&gt; pages\/index.vue\r\n&lt;template&gt;\r\n  &lt;p&gt;Home Page&lt;\/p&gt;\r\n&lt;\/template&gt;<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7735\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06175418\/default-layout.png\" alt=\"\" width=\"1427\" height=\"205\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06175418\/default-layout.png 1427w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06175418\/default-layout-300x43.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06175418\/default-layout-1024x147.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06175418\/default-layout-768x110.png 768w\" sizes=\"auto, (max-width: 1427px) 100vw, 1427px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Now let&#8217;s do something more interesting. Let&#8217;s create a custom layout and display our <strong>\/About<\/strong> page using our customized layout.<\/p>\n<pre>&gt; layouts\/custom.vue\r\n&lt;template&gt;\r\n  &lt;div&gt;\r\n    &lt;h1&gt;This our custom layout&lt;\/h1&gt;\r\n    &lt;slot \/&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&gt; pages\/about.vue\r\n&lt;template&gt;\r\n  &lt;p&gt;About Page&lt;\/p&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script setup&gt;\r\ndefinePageMeta({\r\n  layout: 'custom',\r\n});\r\n&lt;\/script&gt;<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7746 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07135628\/page-about.png\" alt=\"\" width=\"1428\" height=\"135\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07135628\/page-about.png 1428w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07135628\/page-about-300x28.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07135628\/page-about-1024x97.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07135628\/page-about-768x73.png 768w\" sizes=\"auto, (max-width: 1428px) 100vw, 1428px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h3><strong>Routing<\/strong><\/h3>\n<h4><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Dynamic routes<\/span><\/strong><\/h4>\n<p>Now, let&#8217;s look at the different ways to create routes using routing based on Nuxt files.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7739 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06181322\/structure-pages.png\" alt=\"\" width=\"172\" height=\"226\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>In our example, let&#8217;s look at the <strong>&#8220;pages\/&#8221;<\/strong> directory structure. There are two different types of pages: static pages and dynamic pages whose content changes based on route parameters.<\/p>\n<ol>\n<li>Static page\n<ul>\n<li>index.vue \u2192 \/<\/li>\n<li>about.vue \u2192 \/about<\/li>\n<li>category\/index.vue \u2192 \/category<\/li>\n<\/ul>\n<\/li>\n<li>Dynamic page\n<ul>\n<li>category\/[slug].vue \u2192 \/category\/language<\/li>\n<li>user-[group]\/[id].vue \u2192 \/user-admin\/123<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<pre>&gt; pages\/category\/[slug].vue\r\n&lt;template&gt;\r\n  &lt;p&gt;Category slug : {{ $route.params.slug  }}&lt;\/p&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script setup&gt;\r\nconst route = useRoute();\r\nuseHead({\r\n  title: `Category ${route.params.slug}`\r\n});\r\n&lt;\/script&gt;\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7743 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06181711\/routing-category-slug.png\" alt=\"\" width=\"1470\" height=\"225\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06181711\/routing-category-slug.png 1470w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06181711\/routing-category-slug-300x46.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06181711\/routing-category-slug-1024x157.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/06181711\/routing-category-slug-768x118.png 768w\" sizes=\"auto, (max-width: 1470px) 100vw, 1470px\" \/><\/p>\n<p>&nbsp;<\/p>\n<pre>&gt; pages\/user-[group]\/[id].vue\r\n&lt;template&gt;\r\n  &lt;p&gt;Group : {{ $route.params.group }} - ID : {{ $route.params.id }}&lt;\/p&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script setup&gt;\r\nconst route = useRoute();\r\nuseHead({\r\n  title: `User group ${route.params.group} ID ${route.params.id}`\r\n});\r\n&lt;\/script&gt;\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-7752 size-full aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07154241\/routing-user-group-id.png\" alt=\"\" width=\"1432\" height=\"227\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07154241\/routing-user-group-id.png 1432w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07154241\/routing-user-group-id-300x48.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07154241\/routing-user-group-id-1024x162.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07154241\/routing-user-group-id-768x122.png 768w\" sizes=\"auto, (max-width: 1432px) 100vw, 1432px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h4><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Nested Routes<\/span><\/strong><\/h4>\n<p>A hierarchical display page structure where a parent route has child routes or sub-routes. This is useful when you have pages that share a common layout. It is also useful when you want to organize <span style=\"font-weight: 400;\">nested <\/span>routes in your application. Can display nested routes with &lt;NuxtPage&gt;.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7753 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07154348\/structure-nested-pages.png\" alt=\"\" width=\"234\" height=\"395\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07154348\/structure-nested-pages.png 234w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07154348\/structure-nested-pages-178x300.png 178w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07154348\/structure-nested-pages-148x250.png 148w\" sizes=\"auto, (max-width: 234px) 100vw, 234px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>This file tree will generate these routes:<\/p>\n<pre>[\r\n  {\r\n    path: '\/user',\r\n    component: '~\/pages\/user.vue',\r\n    name: 'user',\r\n    children: [\r\n      {\r\n        path: '\/',\r\n        component: '~\/pages\/user\/index.vue',\r\n        name: 'user-child'\r\n      },\r\n      {\r\n        path: '\/:id',\r\n        component: '~\/pages\/user\/[id].vue',\r\n        name: 'user-id',\r\n\tchildren: [\r\n\t   {\r\n\t     path: '\/profile',\r\n\t     component: '~\/pages\/user\/[id]\/profile.vue',\r\n\t     name: 'user-id-profile'\r\n\t   },\r\n\t   {\r\n\t     path: '\/division',\r\n\t     component: '~\/pages\/user\/[id]\/division\/index.vue',\r\n\t     name: 'user-id-division',\r\n\t     children: [\r\n\t\t{\r\n\t\t  path: '\/:division\/:divisionId',\r\n\t\t  component: '~\/pages\/user\/[id]\/division\/[division]\/[divisionId].vue',\r\n\t\t  name: 'user-id-division-id'\r\n\t\t}\r\n\t     ]\r\n\t   },\r\n\t ]\r\n      }\r\n    ]\r\n  }\r\n]\r\n<\/pre>\n<p>Result from user route with child routes.<\/p>\n<pre>&gt; pages\/user.vue\r\n&lt;template&gt;\r\n  &lt;p&gt;User Page&lt;\/p&gt;\r\n  &lt;NuxtPage \/&gt;\r\n&lt;\/template&gt;\r\n\r\n&gt; pages\/user\/index.vue\r\n&lt;template&gt;\r\n  &lt;p&gt;User Child Page&lt;\/p&gt;\r\n&lt;\/template&gt;<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7755 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155153\/routing-nested-user-child.png\" alt=\"\" width=\"1431\" height=\"222\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155153\/routing-nested-user-child.png 1431w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155153\/routing-nested-user-child-300x47.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155153\/routing-nested-user-child-1024x159.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155153\/routing-nested-user-child-768x119.png 768w\" sizes=\"auto, (max-width: 1431px) 100vw, 1431px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Result from user profile route with the parameter user id.<\/p>\n<pre>&gt; pages\/user.vue (parent route)\r\n\r\n&gt; pages\/user\/[id]\/profile\r\n&lt;template&gt;\r\n  &lt;p&gt;User Profile Page - User ID : {{ $route.params.id }}&lt;\/p&gt;\r\n&lt;\/template&gt;<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7756 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155428\/routing-nested-user-id-profile-1.png\" alt=\"\" width=\"1432\" height=\"227\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155428\/routing-nested-user-id-profile-1.png 1432w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155428\/routing-nested-user-id-profile-1-300x48.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155428\/routing-nested-user-id-profile-1-1024x162.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155428\/routing-nested-user-id-profile-1-768x122.png 768w\" sizes=\"auto, (max-width: 1432px) 100vw, 1432px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Result from user division route with the parameter user id.<\/p>\n<pre>&gt; pages\/user.vue (parent route)\r\n\r\n&gt; pages\/user\/[id]\/division\/index.vue\r\n&lt;template&gt;\r\n  &lt;p&gt;User ID : {{ $route.params.id }}&lt;\/p&gt;\r\n  &lt;p&gt;User division : {{ $route.params.division }}&lt;\/p&gt;\r\n&lt;\/template&gt;<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7757 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155551\/routing-nested-user-id-division.png\" alt=\"\" width=\"1431\" height=\"282\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155551\/routing-nested-user-id-division.png 1431w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155551\/routing-nested-user-id-division-300x59.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155551\/routing-nested-user-id-division-1024x202.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155551\/routing-nested-user-id-division-768x151.png 768w\" sizes=\"auto, (max-width: 1431px) 100vw, 1431px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Result from user division route with parameter user id and division id.<\/p>\n<pre>&gt; pages\/user.vue (parent route)\r\n\r\n&gt; pages\/user\/[id]\/division\/[division]\/[divisionId].vue\r\n&lt;template&gt;\r\n  &lt;p&gt;User ID : {{ $route.params.id }}&lt;\/p&gt;\r\n  &lt;p&gt;User division : {{ $route.params.division }} - Division ID : {{ $route.params.divisionId }}&lt;\/p&gt;\r\n&lt;\/template&gt;<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7758 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155723\/routing-nested-user-id-division-divisionId.png\" alt=\"\" width=\"1432\" height=\"272\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155723\/routing-nested-user-id-division-divisionId.png 1432w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155723\/routing-nested-user-id-division-divisionId-300x57.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155723\/routing-nested-user-id-division-divisionId-1024x195.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155723\/routing-nested-user-id-division-divisionId-768x146.png 768w\" sizes=\"auto, (max-width: 1432px) 100vw, 1432px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h3><strong>Navigation<\/strong><\/h3>\n<p>It is the process of moving between different pages or routes in your application. Nuxt uses the &lt;NuxtLink&gt; component to link pages. It will render a &lt;a&gt; tag with the href attribute to set the route for the page.<\/p>\n<pre>&gt; pages\/index.vue\r\n&lt;template&gt;\r\n  &lt;div&gt;\r\n    &lt;p&gt;Home Page&lt;\/p&gt;\r\n    &lt;nav&gt;\r\n      &lt;ul&gt;\r\n        &lt;li&gt;&lt;NuxtLink to=\"\/about\"&gt;About&lt;\/NuxtLink&gt;&lt;\/li&gt;\r\n        &lt;li&gt;&lt;NuxtLink to=\"\/category\"&gt;Category&lt;\/NuxtLink&gt;&lt;\/li&gt;\r\n        &lt;li&gt;&lt;NuxtLink to=\"\/user\"&gt;User&lt;\/NuxtLink&gt;&lt;\/li&gt;\r\n      &lt;\/ul&gt;\r\n    &lt;\/nav&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;style scoped&gt;\r\na {\r\n  text-decoration: none;\r\n  line-height: 1.5em;\r\n  color: #0e0d0d;\r\n  font-weight: 600;\r\n}\r\n&lt;\/style&gt;<\/pre>\n<p>When clicking on each link <span class=\"notion-enable-hover\" data-token-index=\"1\">About, Category, the User<\/span> will be redirected to the corresponding page.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7759 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155923\/navigation.png\" alt=\"\" width=\"1432\" height=\"292\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155923\/navigation.png 1432w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155923\/navigation-300x61.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155923\/navigation-1024x209.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07155923\/navigation-768x157.png 768w\" sizes=\"auto, (max-width: 1432px) 100vw, 1432px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Use &lt;NuxtLink&gt; component with parameter Props &#8220;to&#8221; have 2 objects of interest:<\/p>\n<ol>\n<li>name: The page name is also the corresponding route. Ex: pages\/category\/[slug].vue \u2192 \/category\/:slug. Name the appropriate separator between the child folders as &#8220;-&#8220;: category-slug.<\/li>\n<li>params: Parameters to pass when using dynamic routes.<\/li>\n<\/ol>\n<pre>&gt; pages\/category\/index.vue\r\n&lt;template&gt;\r\n  &lt;p&gt;Category Page&lt;\/p&gt;\r\n  &lt;nav&gt;\r\n    &lt;ul v-for=\"(cate, index) in categories\" :key=\"index\"&gt;\r\n      &lt;li&gt;\r\n        &lt;NuxtLink :to=\"{ name: 'category-slug', params: { slug: cate } }\"&gt;\r\n          {{ cate }}\r\n        &lt;\/NuxtLink&gt;\r\n      &lt;\/li&gt;\r\n    &lt;\/ul&gt;\r\n  &lt;\/nav&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script setup&gt;\r\nconst categories = ['language', 'reading', 'programming', 'art', 'other'];\r\n&lt;\/script&gt;\r\n\r\n&lt;style scoped&gt;\r\na {\r\n  text-decoration: none;\r\n  line-height: 1.5em;\r\n  color: #0e0d0d;\r\n  font-weight: 600;\r\n}\r\n&lt;\/style&gt;<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>Assets<\/strong><\/h3>\n<ol>\n<li>The <strong>&#8220;public\/&#8221;<\/strong> directory content is served at the server root as-is.<\/li>\n<li>The <strong>&#8220;assets\/&#8221;<\/strong> directory contains by convention every asset that you want the build tool (Vite or Webpack) to process.<\/li>\n<\/ol>\n<p><strong>Public directory<\/strong><\/p>\n<p>For example, referencing an image file in the <strong>&#8220;public\/img\/&#8221;<\/strong> directory, available at the static URL \/img\/nuxt.png:<\/p>\n<pre>&lt;template&gt;\r\n  &lt;img src=\"\/img\/nuxt.png\" alt=\"Discover Nuxt 3\" \/&gt;\r\n&lt;\/template&gt;<\/pre>\n<p><strong>Assets directory<\/strong><\/p>\n<blockquote><p><span style=\"color: #ff0000;\"><em><span class=\"notion-enable-hover\" data-token-index=\"0\">Nuxt won&#8217;t serve files in the assets\/ directory at a static URL like \/assets\/my-file.png. If you need a static URL, use the public\/ directory.<\/span><\/em><\/span><\/p><\/blockquote>\n<p>You can set stylesheet files (CSS, SASS, etc), fonts, or SVG. To insert global statements into your Nuxt components, you can use the Vite option in your nuxt.config file.<\/p>\n<p>See the example below:<\/p>\n<pre>&gt; assets\/css\/styles.css\r\na {\r\n  text-decoration: none;\r\n  line-height: 1.5em;\r\n  color: #0e0d0d;\r\n  font-weight: 600;\r\n}\r\n\r\n&gt; assets\/sass\/_colors.scss\r\n$primary: #49240F;\r\n$secondary: #E4A79D;\r\n\r\n&gt; assets\/sass\/app.scss\r\n@import url(\"https:\/\/fonts.googleapis.com\/css2?family=Nunito:ital,wght@0,200;0,300;0,400;0,600;0,700;0,800;0,900;1,200;1,300;1,400;1,600;1,700;1,800;1,900&amp;display=swap\");\r\nbody {\r\n  font-family: 'Nunito',\r\n}\r\n.btn-bg-color {\r\n  background-color: $primary;\r\n}\r\n\r\n&gt; nuxt.config.ts\r\nexport default defineNuxtConfig({\r\n  css: [\r\n    '~\/assets\/css\/styles.css',\r\n    '~\/assets\/sass\/app.scss',\r\n  ],\r\n  vite: {\r\n    css: {\r\n      preprocessorOptions: {\r\n        scss: {\r\n          additionalData: '@use \"@\/assets\/sass\/_colors.scss\" as *;'\r\n        }\r\n      }\r\n    }\r\n  }\r\n})<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong><span class=\"notion-enable-hover\" data-token-index=\"0\">Components<\/span><\/strong><\/h3>\n<p>The <strong>&#8220;components\/&#8221;<\/strong> directory is where you put all your Vue components which can then be imported inside your pages or other components.<br \/>\nNuxt automatically imports any components in your <strong>&#8220;components\/&#8221;<\/strong> directory (along with components registered by any modules you may be using).<\/p>\n<p>In addition, Nuxt also has built-in components such as: &lt;ClientOnly&gt;, &lt;NuxtPage&gt;, &lt;NuxtLayout&gt;, &lt;NuxtLink&gt;, &lt;Teleport&gt;, etc.<\/p>\n<pre>&gt; components\r\n--| BaseHeader.vue\r\n--| BaseFooter.vue\r\n--| base\/\r\n----| html\/\r\n------| Alert.vue\r\n\r\n&gt; layouts\/default.vue\r\n&lt;template&gt;\r\n  &lt;div&gt;\r\n    &lt;BaseHeader \/&gt;\r\n    &lt;BaseHtmlAlert \/&gt;\r\n    &lt;slot \/&gt;\r\n    &lt;BaseFooter \/&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>Composables<\/strong><\/h3>\n<p>Nuxt provides several composables like useAppConfig, useAsyncData, useCookie, useError, useFetch, useHead, etc. Also, Nuxt will automatically import files inside your <strong>&#8220;composables&#8221;<\/strong> directory with the auto-imports feature.<\/p>\n<p>&nbsp;<\/p>\n<h3><strong>Plugins\u00a0<\/strong><\/h3>\n<p>Nuxt automatically reads the files in your <strong>&#8220;plugins&#8221;<\/strong> directory and loads them at the creation of the Vue application. You can use the .server or .client suffix in the file name to load a plugin only on the server or client side.<\/p>\n<blockquote><p><span style=\"color: #ff0000;\"><em><span class=\"notion-enable-hover\" data-token-index=\"0\">All plugins in your plugins\/ directory are auto-registered, so you should not add them to your nuxt.config separately.<\/span><\/em><\/span><\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<h3><strong>Modules<\/strong><\/h3>\n<p>Nuxt provides a list of community-developed modules. Gives you many choices for application development.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-7761 aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07160511\/modules.png\" alt=\"\" width=\"276\" height=\"867\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07160511\/modules.png 276w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07160511\/modules-80x250.png 80w\" sizes=\"auto, (max-width: 276px) 100vw, 276px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Install the necessary modules for your application and configure them in the nuxt.config.ts file.<\/p>\n<pre>export default defineNuxtConfig({\r\n  modules: [\r\n    '@vueuse\/nuxt',\r\n    '@element-plus\/nuxt',\r\n    'nuxt-lodash',\r\n    'nuxt-security',\r\n  ]\r\n})<\/pre>\n<p>For custom files, Nuxt scans the <strong>&#8220;modules\/&#8221;<\/strong> directory and loads them before starting. It is a good place to place any local modules you develop while building your application.<\/p>\n<pre>modules\/*\/*.ts\r\nmodules\/*.ts<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>Data Fetching<\/strong><\/h3>\n<p>With Nuxt 3, there is almost full support for composables and built-in libraries to perform data-fetching from a browser or server environment including useFetch, useLazyFetch, useAsyncData, useLazyAsyncData, and $fetch.<\/p>\n<p><strong>useFetch<\/strong><\/p>\n<p>useFetch is rendered on the server side (in Nuxt&#8217;s server-side rendering mode) and is used to load data into your Nuxt application. useFetch can be used in pages, components, or plugins. Usage of useFetch is very simple as below:<\/p>\n<pre>&lt;template&gt;\r\n  &lt;div&gt;\r\n    Page visits: {{ count }}\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script setup&gt;\r\nconst { data: count } = await useFetch('\/api\/count');\r\n&lt;\/script&gt;<\/pre>\n<p>Options:<\/p>\n<ol>\n<li>method: Request method.<\/li>\n<li>query: Add queries to requests.<\/li>\n<li>params: Alias to query.<\/li>\n<li>body: Request body.<\/li>\n<li>headers: Request headers.<\/li>\n<li>baseURL: Base URL.<\/li>\n<li>key: Unique value, controls how data is cached and how requests are implemented.<\/li>\n<li>server: Whether to fetch the data on the server (defaults to true).<\/li>\n<li>default: Set default values for the data.<\/li>\n<li>pick: Extract specific properties from object data.<\/li>\n<li>watch: Watch changes of some object to trigger a useFetch call.<\/li>\n<li>transform: Use to transform the output.<\/li>\n<li>immediate: When set to false, prevents the request from triggering useFetch immediately.<\/li>\n<\/ol>\n<p>Return value:<\/p>\n<ol>\n<li>data: The data that useFetch calls from the API.<\/li>\n<li>pending: The useFetch state is still called (true\/false).<\/li>\n<li>refresh\/execute: The refresh or execute function can be called outside of the useFetch used to fetch the data.<\/li>\n<li>error: Object error in case the API call fails.<\/li>\n<\/ol>\n<p>Here is a small example using some of the above options.<\/p>\n<pre>const { data, pending, error, refresh } = await useFetch('https:\/\/api.nuxtjs.dev\/mountains',{\r\n    pick: ['title'],\r\n    query: { param1, param2: 'value2' }\r\n})\r\nconst refreshData = () =&gt; refresh();<\/pre>\n<p>This usage will return the title of the elements in the array returned from the URL as &#8220;<a class=\"notion-link-token notion-focusable-token notion-enable-hover\" href=\"https:\/\/api.nuxtjs.dev\/mountains?param1=value1&amp;param2=value2\" rel=\"noopener noreferrer\" data-token-index=\"1\"><span class=\"link-annotation-unknown-block-id-1150985498\">https:\/\/api.nuxtjs.dev\/mountains?param1=value1&amp;param2=value2<\/span><\/a>&#8221; and we can call useFetch again via the refreshData function.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>useAsyncData<\/strong><\/p>\n<p>With useFetch, each use passes a long URL into useFetch and if this URL is used in many places it is quite difficult to manage. Usually, we will create an API directory and write API calls to the files in it, then import them into the component or page. With this approach, useFetch cannot be used. For convenience, useAsyncData is similar to useFetch.<\/p>\n<pre>&lt;template&gt;\r\n  &lt;div&gt;\r\n     Page visits: {{ data }}\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script setup&gt;\r\n\tconst { data } = await useAsyncData('count', () =&gt; $fetch('\/api\/count'));\r\n&lt;\/script&gt;<\/pre>\n<p>Suppose there is a function:<\/p>\n<pre>export const getPosts = () =&gt; axios.get('\/api\/posts');<\/pre>\n<p>To use useAsyncData, we just need to change it to:<\/p>\n<pre>const { data } = await useAsyncData('projectSearch', () =&gt; getPosts());<\/pre>\n<p>UseAsyncData options and return values are the same as in useFetch. There is a small note when using useAsyncData or useFetch that we remember to add keys to them and remember to clearNuxtData if we want useAsyncData or useFetch to be called again when we switch pages. For example, this:<\/p>\n<pre>&lt;script setup&gt;\r\n\tawait clearNuxtData('count');\r\n\tconst { data } = await useAsyncData('count', () =&gt; $fetch('\/api\/count'));\r\n&lt;\/script&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>useLazyFetch<\/strong><\/p>\n<p>The spelling of useLazyFetch is similar to useFetch because it is basically useFetch with the option lazy: true. Lazy will load data asynchronously, and Nuxt will load data in parallel with the code right behind. Except for useFetch, it will be done before executing the code behind it. In addition, you can use the pending property to determine if the data has been loaded (pending = true when the data has not been loaded and opposite).<\/p>\n<pre>&lt;template&gt;\r\n  &lt;div&gt;\r\n     Page visits: {{ count }}\r\n  &lt;\/div&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script setup&gt;\r\n    const { pending, data: count } = await useLazyFetch('\/api\/count');\r\n&lt;\/script&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>useLazyAsyncData<\/strong><\/p>\n<p>useLazyAsyncData is similar to useAsyncData but with the lazy: true option. The implementation is the same as useAsyncData:<\/p>\n<pre>const { pending, data: post } = await useLazyAsyncData('post', () =&gt; getPosts());<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>$fetch<\/strong><\/p>\n<p>Nuxt uses <a href=\"https:\/\/github.com\/unjs\/ofetch\">ofetch<\/a> for global visibility with the $fetch helper to make HTTP requests in your Vue app or API routes.<\/p>\n<p>We should use useFetch or useAsyncData + $fetch to prevent double fetch when fetching component data.<\/p>\n<pre>&lt;script setup&gt;\r\n\/\/ During SSR data is fetched twice, once on the server and once on the client.\r\nconst dataTwice = await $fetch('\/api\/item')\r\n\/\/ During SSR data is fetched only on the server side and transferred to the client.\r\nconst { data } = await useAsyncData('item', () =&gt; $fetch('\/api\/item'))\r\n\/\/ You can also useFetch as shortcut of useAsyncData + $fetch\r\nconst { data } = await useFetch('\/api\/item')\r\n&lt;\/script&gt;<\/pre>\n<p>You can use $fetch for any method executed on the client-side.<\/p>\n<pre>&lt;template&gt;\r\n  &lt;button @click=\"contactForm\"&gt;Contact&lt;\/button&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script setup&gt;\r\nfunction contactForm() {\r\n  $fetch('\/api\/contact', {\r\n    method: 'POST',\r\n    body: { hello: 'world '}\r\n  })\r\n}\r\n&lt;\/script&gt;<\/pre>\n<p>&nbsp;<\/p>\n<h3>Server<\/h3>\n<p>Nuxt automatically scans files inside these directories to register API and server handlers with HMR support: ~\/server\/api, ~\/server\/routes, ~\/server\/middleware.<\/p>\n<p>Ex: create a route \/api\/hello with \/server\/api\/hello.ts.<\/p>\n<pre>&gt; server\/api\/hello.ts\r\nexport default defineEventHandler((event) =&gt; {\r\n  return {\r\n    hello: 'world'\r\n  }\r\n})\r\n\r\n&gt; pages\/hello.vue\r\n&lt;template&gt;\r\n  &lt;pre&gt;{{ data }}&lt;\/pre&gt;\r\n&lt;\/template&gt;\r\n\r\n&lt;script setup&gt;\r\n  const { data } = await useFetch('\/api\/hello');\r\n&lt;\/script&gt;<\/pre>\n<p>Handle file names can be suffixed with .get, .post, .put, .delete, &#8230; to match the request&#8217;s HTTP Method.<\/p>\n<pre>&gt; server\/api\/test.get.ts\r\nexport default defineEventHandler(() =&gt; 'Test get handler')\r\n\r\n&gt; server\/api\/test.post.ts\r\nexport default defineEventHandler(() =&gt; 'Test post handler')<\/pre>\n<p>Handle request with Body:<\/p>\n<pre>&gt; server\/api\/submit.post.ts\r\nexport default defineEventHandler(async (event) =&gt; {\r\n    const body = await readBody(event)\r\n    return { body }\r\n})<\/pre>\n<p>Handle request with Query:<\/p>\n<pre>&gt; server\/api\/search.ts\r\n\/\/ Template query: \/api\/search?param1=a&amp;param2=b\r\nexport default defineEventHandler((event) =&gt; {\r\n  const query = getQuery(event)\r\n  return { a: query.param1, b: query.param2 }\r\n})<\/pre>\n<p>&nbsp;<\/p>\n<h2>Conclusion<\/h2>\n<p><span style=\"font-weight: 400;\">With the new version of Nuxt, in addition to the growing Vue.js community, the strength of the core technologies has gradually attracted the user community of Vue.js in general and Nuxt in particular. This has helped provide a rich and diverse documentation resource.<\/span><\/p>\n<p><strong>Advantage:<\/strong><\/p>\n<ol>\n<li>Performance has improved.<\/li>\n<li>Improve mobile application performance.<\/li>\n<li>Flexible and modular architectures.<\/li>\n<li>Better Typescript support, plugins, and debugging tools.<\/li>\n<li>SEO optimization.<\/li>\n<li>Integrates well with Vue 3.<\/li>\n<li>Less complicated configuration.<\/li>\n<\/ol>\n<p><strong>Disadvantage:<\/strong><\/p>\n<ol>\n<li>For beginners, it is necessary to know Vue.js.<\/li>\n<li>Nuxt requires its standard folder structure. This can be difficult when you need to customize the folder structure or integrate with other structured external tools and libraries.<\/li>\n<li>Some Vue.js libraries and plugins may not be compatible or require additional configuration when used with Nuxt.<\/li>\n<li>Nuxt is a powerful framework designed for complex applications. If you have a simple project or a single-page app, Nuxt can introduce unnecessary complexity and cost.<\/li>\n<li>The community is small and growing.<\/li>\n<\/ol>\n<p>Statistics between popular rendering frameworks:<\/p>\n<div class=\"mceTemp\">\n<p style=\"text-align: center;\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-7762 size-full aligncenter\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161448\/download-chart-nuxt-next.png\" alt=\"\" width=\"1647\" height=\"581\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161448\/download-chart-nuxt-next.png 1647w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161448\/download-chart-nuxt-next-300x106.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161448\/download-chart-nuxt-next-1024x361.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161448\/download-chart-nuxt-next-768x271.png 768w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161448\/download-chart-nuxt-next-1536x542.png 1536w\" sizes=\"auto, (max-width: 1647px) 100vw, 1647px\" \/><\/p>\n<\/div>\n<p style=\"text-align: center;\">(<a class=\"notion-link-token notion-focusable-token notion-enable-hover\" href=\"https:\/\/npmtrends.com\/\" rel=\"noopener noreferrer\" data-token-index=\"1\"><span class=\"link-annotation-unknown-block-id-1221904394\">https:\/\/npmtrends.com\/<\/span><\/a>)<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-7764 size-full\" src=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161729\/ratio-rendering-framework.png\" alt=\"\" width=\"1357\" height=\"623\" srcset=\"https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161729\/ratio-rendering-framework.png 1357w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161729\/ratio-rendering-framework-300x138.png 300w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161729\/ratio-rendering-framework-1024x470.png 1024w, https:\/\/s3-ap-southeast-1.amazonaws.com\/homepage-media\/wp-content\/uploads\/2023\/07\/07161729\/ratio-rendering-framework-768x353.png 768w\" sizes=\"auto, (max-width: 1357px) 100vw, 1357px\" \/><\/p>\n<p style=\"text-align: center;\">(<a class=\"notion-link-token notion-focusable-token notion-enable-hover\" href=\"https:\/\/2022.stateofjs.com\/\" rel=\"noopener noreferrer\" data-token-index=\"1\"><span class=\"link-annotation-unknown-block-id--1884666644\">https:\/\/2022.stateofjs.com\/<\/span><\/a>)<\/p>\n<p>&nbsp;<\/p>\n<h2>Reference:<\/h2>\n<p><a href=\"https:\/\/nuxt.com\/\">https:\/\/nuxt.com\/<\/a><\/p>\n<p><a href=\"https:\/\/npmtrends.com\/\">https:\/\/npmtrends.com\/<\/a><\/p>\n<p><a href=\"https:\/\/2022.stateofjs.com\/\">https:\/\/2022.stateofjs.com\/<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>Introduction Nuxt is an open-source JavaScript framework based on Vue.js. The latest version is currently Nuxt 3. Nuxt 3 is an upgrade from the Nuxt framework based on Vite, Vue 3, and Nitro with support from Typescript. Nuxt simplifies the development of web applications under Server-side rendering (SSR) and Static Site Generation (SSG) methods, in addition to other methods such as CSR, ISR, ESR, and [&hellip;]<\/p>\n","protected":false},"author":42,"featured_media":7713,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"footnotes":""},"categories":[4,71],"tags":[115,116,118],"class_list":["post-7666","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","category-it-tec","tag-nuxt","tag-nuxt3","tag-vuejs"],"_links":{"self":[{"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/posts\/7666","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/comments?post=7666"}],"version-history":[{"count":0,"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/posts\/7666\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/media\/7713"}],"wp:attachment":[{"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/media?parent=7666"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/categories?post=7666"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.briswell-vn.com\/en\/wp-json\/wp\/v2\/tags?post=7666"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}