@nuxtjs/composition-api

repository·main·Indexed 20 days ago

https://github.com/nuxt-community/composition-api

A module that provides the Vue Composition API for Nuxt 2, bridging the gap between the Composition API pattern and Nuxt-specific features. It includes support for the Nuxt fetch hook (v2.12+), access to Nuxt context (router, app, store), vue-meta integration via useMeta, and SSR-friendly refs with ssrRef. The package is written in TypeScript and supports <script setup> via unplugin-vue2-script-setup. Users are recommended to migrate to Nuxt Bridge for native Composition API support.

Tokens
14.9K
Snippets
54
Records
73
Agent score
72%

What's inside @nuxtjs/composition-api

  1. What is Nuxt Composition API

    main
    The @nuxtjs/composition-api module provides a way to use the Vue Composition API within Nuxt 2 applications. It extends the standard Composition API with Nuxt-specific features, enabling seamless integration with Nuxt's lifecycle and ecosystem.
  2. Avoid shared server state with global refs

    main

    When running in production mode, any ref declared in the global state of your application (such as within Nuxt plugins or state/store files used as a Vuex replacement) is persisted across different user requests.

    To avoid leaking data from one user request to another, do not declare reactive refs in the global scope of your application. Instead, ensure state is scoped to the request lifecycle (e.g., within a component or a function called during the request).

  3. Important setup notes for @nuxtjs/composition-api

    main

    When setting up the module, keep the following in mind:

    • Automatic Plugin Installation: The module automatically installs @vue/composition-api as a plugin. You do not need to enable it separately.
    • Direct Imports: For convenience, you can import @vue/composition-api methods and hooks directly from @nuxtjs/composition-api instead of installing the Vue package separately.
    • IDE Support: If you are using script setup, follow the instructions for unplugin-vue2-script-setup to ensure better IDE auto-complete.
  4. How useStatic behaves during SSR (Server-Side Rendering)

    main

    If a route is not pre-generated (which includes running in dev mode), useStatic follows these rules:

    1. On Hard-Reload: The server executes the factory function and inlines the result into nuxtState. This prevents the client from re-running the same API request. The result is cached between requests.
    2. On Client Navigation: The client executes the factory function directly.

    In both scenarios, the return value of useStatic is a reactive ref that starts as null and is filled once the factory function or JSON fetch resolves.

  5. How useStatic behaves during SSG (Static Site Generation)

    main

    When using nuxt build && nuxt generate --no-build to generate the whole app or specific routes, useStatic provides the following optimizations:

    1. At Generation Time: The result of the useStatic factory function is saved to a JSON file and copied into the /dist directory.
    2. On Hard-Reload: The JSON data is inlined into the page and cached.
    3. On Client Navigation: The client fetches the JSON file. Once fetched, it is cached for subsequent navigations.

    Fallback Behavior: If the JSON file does not exist (e.g., the page was not pre-generated), the original factory function will execute on the client-side.

    WARNING

    If you are pre-generating only specific pages, you may need to increase generate.interval in your Nuxt configuration.

  6. Key features of @nuxtjs/composition-api

    main

    The module provides several enhancements for using the Composition API in Nuxt:

    • Nuxt Fetch Support: Support for the Nuxt fetch feature (available in Nuxt v2.12+).
    • Nuxt Context Access: Easy access to router, app, and store directly within the setup() function.
    • Meta Integration: Ability to interact directly with vue-meta properties within setup().
    • SSR-friendly Refs: Includes ssrRef, a drop-in replacement for ref that handles automatic SSR stringification and hydration.
    • TypeScript Support: The package is written in TypeScript.
    • Script Setup Support: Supports <script setup> via unplugin-vue2-script-setup configuration.
  7. Features of @nuxtjs/composition-api

    main

    The module provides several key capabilities for Nuxt 2 developers:

    • Fetch: Support for the Nuxt fetch() hook (available in Nuxt v2.12+).
    • Context: Provides easy access to Nuxt's router, app, and store directly within the setup() function.
    • Head: Allows direct interaction with vue-meta properties from within setup().
    • Automatic hydration: Includes ssrRef, a drop-in replacement for ref that handles automatic SSR stringification and hydration.
    • SSR support: Enables the use of the Composition API in Server-Side Rendering environments.
    • TypeScript: The module is written in TypeScript for better type safety and developer experience.
  8. Configure keys for ssrPromise

    main

    To ensure that reactive values match between the server and the client, ssrPromise requires a unique key.

    • Automatic Configuration: If you have added @nuxtjs/composition-api/module to your Nuxt buildModules, a Babel plugin is automatically injected to handle key generation.
    • Manual Configuration: If you are not using the Nuxt module or need custom behavior, you can:
      1. Specify a key manually within the ssrPromise call.
      2. Add @nuxtjs/composition-api/dist/babel-plugin to your Babel plugins configuration.

    Warning: Without a unique key, ssrPromise is only suitable for one-off operations. For repeated use, you must provide your own unique key to avoid collisions.

  9. Use useMeta to manage head and meta properties

    main

    The useMeta() helper allows you to interact with Nuxt head properties directly within the setup() function or the onGlobalSetup method. This enables you to dynamically set or reactively update the page title and other meta tags using the Composition API.

    Requirements

    To enable useMeta, you must satisfy two conditions:

    1. Include an empty head: {} object within your component definition.
    2. Use the defineComponent function exported from @nuxtjs/composition-api instead of the standard Vue defineComponent.

    Usage Patterns

    • Direct Assignment: Destructure properties like title from useMeta() and assign values to their .value property.
    • Initial Configuration: Pass an object to useMeta() to set initial meta values.
    • Reactive/Computed Meta: Pass a function to useMeta() that returns a meta object. This allows the head properties to react to changes in local state (e.g., a ref).
    import { defineComponent, useMeta, ref } from '@nuxtjs/composition-api'
    
    export default defineComponent({
      // Required to activate useMeta
      head: {},
      setup() {
        // 1. Destructuring and direct assignment
        const { title } = useMeta()
        title.value = 'My page'
    
        // 2. Providing an initial value
        const { title: initialTitle } = useMeta({ title: 'My page' })
    
        // 3. Setting multiple meta tags at once
        useMeta({ title: 'My page' })
    
        // 4. Using a function for reactive/computed meta
        const message = ref('Hello')
        useMeta(() => ({ title: message.value }))
      },
    })
  10. Use unique keys with 'Keyed' functions in global composables

    main

    Several helper functions in @nuxtjs/composition-api—specifically shallowSsrRef, ssrPromise, ssrRef, and useAsync—use a key to pass JSON-encoded information from the server to the client. By default, the library generates a key based on the line number where the function is called.

    If you use these functions inside a global composable, every call to that composable will share the same line number, causing them to share the same key. This results in state leakage where updating one instance affects all others. To prevent this, you must provide a unique key as the second optional parameter (e.g., using a route path) for every unique call.

    // INCORRECT: Shared key due to same line number in global composable
    function useMyFeature() {
      const feature = ssrRef('')
      return feature
    }
    
    const a = useMyFeature()
    const b = useMyFeature()
    b.value = 'changed'
    // On client-side, a's value will also be initialized to 'changed'
    
    // CORRECT: Providing a unique key (e.g., a path)
    function useMyFeature(path: string) {
      const content = useAsync(
        () => fetch(`https://api.com/slug/${path}`).then(r => r.json()),
        path // 'path' acts as the unique key
      )
    
      return {
        content,
      }
    }