new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Nuxt · Getting started · all subjects

build

50 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Nuxt uses Vite as default build tool

Nuxt is configured to use Vite by default as the build tool, supporting hot module replacement (HMR) in development and code bundling for production with best-practices built-in.

Nuxt automatic code splitting

Nuxt automatically splits code into smaller chunks to help reduce the initial load time of applications.

Vite glob imports default to lazy loading

Glob imports are lazy by default, meaning each matching asset is included in the build output but loads on demand. Add eager: true if the URLs must be available synchronously.

Example: Vite import.meta.glob with eager loading

To load all glob matches up front and make URLs available synchronously: ```ts const images = import.meta.glob<string>('./assets/img/*.{png,jpg,svg}', { query: '?url', import: 'default', eager: true, }) ``` Every matching asset is still included in the build output. Eager imports load all matches up front and can increase the initial JavaScript size or inline small assets.

Build tools process assets in app/assets/

Nuxt uses Vite (default) or webpack to build and bundle the application. The main function of these build tools is to process JavaScript files, but they can be extended through plugins (for Vite) or loaders (for webpack) to process other kinds of assets like stylesheets, fonts, or SVGs. This step transforms the original file, mainly for performance or caching purposes such as stylesheet minification or browser cache invalidation.

Static string src paths are rewritten at build time

When an src is a static string literal in your template, the build tool rewrites it into a runtime helper that resolves the final URL. A public path such as /img/nuxt.png is wrapped so that app.baseURL is applied when the page renders, and a bundled path such as ~/assets/img/nuxt.png additionally becomes an import that resolves to the hashed output file.

Dynamic src paths do not get rewritten

A bound :src whose value is assembled at runtime is opaque to the build tool, so the rewriting does not happen. The string is used exactly as written. For example, <img :src="`~/assets/img/${name}.png`"> does not work because the path is built at runtime, so Vite never sees it as an import.

Example: Vite dynamic import for known assets

When the possible files are known, list their imports explicitly: ```vue <script setup lang="ts"> const props = defineProps<{ theme: 'light' | 'dark' }>() const logos = { light: () => import('./assets/img/logo-light.png?url'), dark: () => import('./assets/img/logo-dark.png?url'), } const logoUrl = (await logos[props.theme]()).default </script> <template> <img :src="logoUrl" alt="Nuxt" > </template> ``` Each import has a literal path, so Vite can find both files at build time while loading only the selected module at runtime.

Example: Vite variable dynamic import for many files

When many files share a directory and extension, use a variable dynamic import: ```ts async function getImageUrl (name: string) { const image = await import(`./assets/img/${name}.png?url`) return image.default } ``` Only the filename can be dynamic in this example. Keeping the directory and extension in the import lets Vite find the possible files at build time.

Example: Vite import.meta.glob for pattern matching

For a broader pattern or an explicit map of available files, use import.meta.glob: ```ts const images = import.meta.glob<string>('./assets/img/*.{png,jpg,svg}', { query: '?url', import: 'default', }) async function getImageUrl (name: string) { const load = images[`./assets/img/${name}.png`] if (!load) { throw new Error(`Unknown image: ${name}`) } return await load() } ```

Build tool changes in Nuxt 3

Nuxt 3 moves from webpack 4 and Babel to Vite or webpack 5 and esbuild.

E2E url(path) API returns full URL with port

import { url } from '@nuxt/test-utils/e2e' const pageUrl = url('/page') // 'http://localhost:6840/page'

E2E test setup requires setup() function in describe block

In each describe block using @nuxt/test-utils/e2e helper methods, call setup() before any tests. The setup() function performs tasks in beforeAll, beforeEach, afterEach, and afterAll hooks to set up the Nuxt test environment.

E2E $fetch(url) API returns HTML of server-rendered page

import { $fetch } from '@nuxt/test-utils/e2e' const html = await $fetch('/')

E2E fetch(url) API returns response object

import { fetch } from '@nuxt/test-utils/e2e' const res = await fetch('/') const { body, headers } = res

E2E getServerLogs() returns captured server output lines

getServerLogs from @nuxt/test-utils/e2e returns lines captured from server subprocess stdout/stderr since last startServer() or clearServerLogs() call. Only populated when captureServerLogs is true (default). Example: expect(getServerLogs().some(line => line.includes('[test]'))).toBe(true)

E2E clearServerLogs() clears captured log lines

clearServerLogs from @nuxt/test-utils/e2e clears the captured server log lines. Useful between requests to assert only on logs from a specific operation.

E2E createPage(url) creates Playwright browser instance

createPage from @nuxt/test-utils/e2e creates a configured Playwright browser instance and optionally points it at a path from the running server. All Playwright API methods are available on the returned page variable. Example: const page = await createPage('/page')

Playwright test runner provides first-class Nuxt support

Nuxt provides first-class support for testing within the Playwright test runner. Use expect and test from @nuxt/test-utils/playwright instead of directly from @playwright/test.

Playwright test with goto and expect from @nuxt/test-utils/playwright

import { expect, test } from '@nuxt/test-utils/playwright' test('test', async ({ page, goto }) => { await goto('/', { waitUntil: 'hydration' }) await expect(page.getByRole('heading')).toHaveText('Welcome to Playwright!') })

Target host end-to-end testing example

import { createPage, setup } from '@nuxt/test-utils/e2e' import { describe, expect, it } from 'vitest' describe('login page', async () => { await setup({ host: 'http://localhost:8787', }) it('displays the email and password fields', async () => { const page = await createPage('/login') expect(await page.getByTestId('email').isVisible()).toBe(true) expect(await page.getByTestId('password').isVisible()).toBe(true) }) })

Run specific test suites with vitest --project flag

Use 'npx vitest --project unit' to run only unit tests, 'npx vitest --project nuxt' to run only Nuxt tests, 'npx vitest' to run all tests, and 'npx vitest --watch' for watch mode.

Nuxt tests run in a global happy-dom or jsdom environment with initialized Nuxt app

When running tests in the Nuxt environment, they execute in either happy-dom or jsdom. Before tests run, a global Nuxt app is initialized, including running plugins and app.vue code. Tests must not mutate global state unless it is reset afterwards.

mountSuspended helper mounts Vue components in Nuxt environment

mountSuspended from @nuxt/test-utils/runtime allows mounting any Vue component within the Nuxt environment, enabling async setup and access to injections from Nuxt plugins. It wraps mount from @vue/test-utils. The options object accepts @vue/test-utils mount options plus: route (initial route, or false to skip route change; default '/').

mountSuspended example with auto-imported component

import { mountSuspended } from '@nuxt/test-utils/runtime' import { SomeComponent } from '#components' it('can mount some component', async () => { const component = await mountSuspended(SomeComponent) expect(component.text()).toMatchInlineSnapshot( '"This is an auto-imported component"', ) })

mountSuspended example mounting app.vue

import { mountSuspended } from '@nuxt/test-utils/runtime' import App from '~/app.vue' it('can also mount an app', async () => { const component = await mountSuspended(App, { route: '/test' }) expect(component.html()).toMatchInlineSnapshot(` "<div>This is an auto-imported component</div> <div> I am a global component </div> <div>/</div> <a href="/test"> Test link </a>" `) })

renderSuspended helper renders components with Testing Library

renderSuspended from @nuxt/test-utils/runtime renders any Vue component within the Nuxt environment using @testing-library/vue, allowing async setup and access to injections from Nuxt plugins. Must be used with Testing Library utilities like screen and fireEvent. Testing Library relies on testing globals for cleanup, which should be enabled in Vitest config. The component is rendered inside a <div id="test-wrapper"></div>. The options object accepts @testing-library/vue render options plus: route (initial route, or false to skip route change; default '/').

renderSuspended example

import { renderSuspended } from '@nuxt/test-utils/runtime' import { SomeComponent } from '#components' import { screen } from '@testing-library/vue' it('can render some component', async () => { await renderSuspended(SomeComponent) expect(screen.getByText('This is an auto-imported component')).toBeDefined() })

mockNuxtImport mocks Nuxt auto-import functionality

mockNuxtImport from @nuxt/test-utils/runtime allows mocking Nuxt auto-imports like useState. It can only be used once per mocked import per test file because it is a macro transformed to vi.mock, which is hoisted. Can accept the import name as a string or the import itself. Supports explicit typing for type safety and access to original implementation via the factory function parameter.

mockNuxtImport basic example

import { mockNuxtImport } from '@nuxt/test-utils/runtime' mockNuxtImport('useState', () => { return () => { return { value: 'mocked storage' } } }) // your tests here

mockNuxtImport with type and original implementation

import { mockNuxtImport } from '@nuxt/test-utils/runtime' mockNuxtImport<typeof useState>('useState', (original) => { return (...args) => { return { ...original('some-key'), value: 'mocked state' } } }) // or specify the target to mock mockNuxtImport(useState, (original) => { return (...args) => { return { ...original('some-key'), value: 'mocked state' } } })

mockNuxtImport with vi.hoisted for different implementations per test

import { vi } from 'vitest' import { mockNuxtImport } from '@nuxt/test-utils/runtime' const { useStateMock } = vi.hoisted(() => { return { useStateMock: vi.fn(() => { return { value: 'mocked storage' } }), } }) mockNuxtImport('useState', () => { return useStateMock }) // Then, inside a test useStateMock.mockImplementation(() => { return { value: 'something else' } })

mockComponent mocks Nuxt components by name or path

mockComponent from @nuxt/test-utils/runtime allows mocking Nuxt components. First argument can be the component name in PascalCase or the relative path of the component (including alias). Second argument is a factory function that returns the mocked component. Cannot reference local variables in the factory function since they are hoisted; import needed dependencies inside the factory.

mockComponent examples

import { mockComponent } from '@nuxt/test-utils/runtime' mockComponent('MyComponent', { props: { value: String, }, setup (props) { // ... }, }) // relative path or alias also works mockComponent('~/components/my-component.vue', () => { // or a factory function return defineComponent({ setup (props) { // ... }, }) }) // or you can use SFC for redirecting to a mock component mockComponent('MyComponent', () => import('./MockComponent.vue'))

mockComponent with async imports

import { mockComponent } from '@nuxt/test-utils/runtime' mockComponent('MyComponent', async () => { const { ref, h } = await import('vue') return defineComponent({ setup (props) { const counter = ref(0) return () => h('div', null, counter.value) }, }) })

registerEndpoint creates mocked Nitro endpoints

registerEndpoint from @nuxt/test-utils/runtime allows creating Nitro endpoints that return mocked data, useful for testing components that make API requests. First argument is the endpoint name (e.g. '/test/'). Second argument is either a factory function returning mocked data (defaults to GET) or an object with handler, method (optional, e.g. 'GET', 'POST'), and once (optional, if true the handler is only used for the first matching request).

registerEndpoint examples

import { registerEndpoint } from '@nuxt/test-utils/runtime' // Basic GET endpoint registerEndpoint('/test/', () => ({ test: 'test-field', })) // POST endpoint with options registerEndpoint('/test/', { method: 'POST', handler: () => ({ test: 'test-field' }), })

Set baseURL empty for test endpoints using environment overrides

If component requests go to an external API, configure baseURL and make it empty using Nuxt Environment Override Config ($test) so all requests go to the Nitro server where endpoints are registered with registerEndpoint.

@nuxt/test-utils/runtime and /e2e cannot be used in same test file

@nuxt/test-utils/runtime and @nuxt/test-utils/e2e need to run in different testing environments and cannot be used in the same file. Split tests into separate files, specify environment per-file with // @vitest-environment nuxt comment, or name runtime unit test files with .nuxt.spec.ts extension.

Using @vue/test-utils standalone without Nuxt runtime

To use @vue/test-utils on its own for unit testing components that do not rely on Nuxt composables, auto-imports, or context, install vitest, @vue/test-utils, happy-dom, and @vitejs/plugin-vue. Create vitest.config.ts with plugins: [vue()] and test.environment: 'happy-dom'. This approach does not include Nuxt test utilities.

End-to-end testing frameworks supported

Nuxt supports end-to-end testing with Vitest, Jest, Cucumber, and Playwright as test runners.

How to configure build tools in Nuxt 3

To configure Nuxt's build tools in Nuxt 3, use the new top-level `vite`, `webpack`, and `postcss` keys in your `nuxt.config`.

Nuxt 2 build configuration no longer applies

Most of the previous `build` configuration in `nuxt.config` is now ignored in Nuxt 3, including any custom babel configuration.

Default build tools in Nuxt 3

Nuxt 3 uses the following build tools by default: Vite or webpack, Rollup, PostCSS, and esbuild.

Migration steps for build tooling from Nuxt 2 to Nuxt 3

When migrating from Nuxt 2 to Nuxt 3, perform these steps: (1) Remove `@nuxt/typescript-build` and `@nuxt/typescript-runtime` from your dependencies and modules. (2) Remove any unused babel dependencies from your project. (3) Remove any explicit core-js dependencies. (4) Migrate `require` to `import`.

noScripts default behavior strips scripts in production only

When the noScripts feature is enabled, its default setting is features.noScripts: 'production', which strips scripts from rendered HTML only in production builds. Scripts remain in development builds.

Vite Environment API migration in Nuxt 5

Nuxt 5 migrates to Vite 6's Environment API. The `experimental.viteEnvironmentApi` option has been removed and is always enabled. Deprecated environment-specific `extendViteConfig()` with `server` and `client` options. Changed plugin registration: Vite plugins registered with `addVitePlugin()` targeting one environment (by passing `server: false` or `client: false`) will not have their `config` or `configResolved` hooks called. Use `configEnvironment` hook and `applyToEnvironment` method instead for environment-specific configuration.

Vite 8 migration breaks esbuild and Rollup

Nuxt 5 upgrades to Vite 8, which replaces esbuild and Rollup with Rolldown as the underlying bundler. `vite.esbuild` and `vite.optimizeDeps.esbuildOptions` are deprecated in favour of `vite.oxc` and `vite.optimizeDeps.rolldownOptions`. `build.rollupOptions` is deprecated in favour of `build.rolldownOptions`. CommonJS interop behaviour has changed.

experimental.externalVue removed in Nuxt 5

The `experimental.externalVue` option has been removed. Vue compiler dependencies (`@babel/parser`, `@vue/compiler-core`, `@vue/compiler-dom`, `@vue/compiler-ssr`, `estree-walker`) are now always replaced with mock proxies in the server bundle when `vue.runtimeCompiler` is not enabled. This reduces default server bundle size by approximately 860KB (~59%). If `vue.runtimeCompiler: true` is set, the real compiler packages are included as before.

@vitejs/plugin-vue-jsx now optional in Nuxt 5

`@vitejs/plugin-vue-jsx` is no longer installed by default. It is now an optional peer dependency loaded on demand only when a `.jsx` or `.tsx` file is encountered. If your project uses JSX/TSX, install `@vitejs/plugin-vue-jsx` with `npm install -D @vitejs/plugin-vue-jsx`, `yarn add -D @vitejs/plugin-vue-jsx`, `pnpm add -D @vitejs/plugin-vue-jsx`, or `bun add -D @vitejs/plugin-vue-jsx`. Nuxt will prompt you to install it automatically on first JSX/TSX file processing.

Give your agent this brain