Nuxt Bridge

repository·main·Indexed 43 days ago

https://github.com/nuxt/bridge

A compatibility layer that enables Nuxt 3 features within Nuxt 2 projects to facilitate a gradual migration path. It allows developers to use Nuxt 3 features as a module without a full immediate rewrite, though it does not support Internet Explorer or the useAsyncData and useFetch composables.

Tokens
17.1K
Snippets
67
Records
81
Agent score
54%

What's inside Nuxt Bridge

  1. What is Nuxt Bridge and when to use it

    main

    Nuxt Bridge is a forward-compatibility layer designed to reduce the friction of migrating from Nuxt 2 to Nuxt 3. It allows you to use many Nuxt 3 features within a Nuxt 2 project by enabling it as a module.

    When to use it:

    • If you have an existing Nuxt 2 project and want to gradually transition to Nuxt 3.
    • If you want to experience Nuxt 3 features without a full rewrite immediately.

    When NOT to use it:

    • If you are starting a fresh project, skip Bridge and install Nuxt 3 directly.

    Limitations:

    • The useAsyncData and useFetch composables are not available in Bridge.
    • It does not support Internet Explorer (requires browsers supporting ES6 module dynamic import).
  2. Set up a Nuxt Bridge development environment

    main

    To contribute to or develop Nuxt Bridge locally, follow these steps:

    1. Clone the repository.
    2. Ensure you have the latest LTS version of Node.js installed.
    3. Enable Corepack to use pnpm and yarn:
      corepack enable
    4. Install dependencies:
      pnpm install
    5. Activate passive development:
      pnpm dev:prepare
    6. Run the playground:
      pnpm dev
    corepack enable
    pnpm install
    pnpm dev:prepare
    pnpm dev
  3. How Nuxt Bridge handles SSR and SPA rendering

    main

    Nuxt Bridge determines whether to use the SSR (Server-Side Rendering) or SPA (Single Page Application) renderer based on several factors:

    1. Environment Variables: If process.env.NUXT_NO_SSR is set, it defaults to the SPA renderer.
    2. Route Rules: If the current route has ssr: false configured in routeRules, it uses the SPA renderer.
    3. Request Headers: If the request contains the x-nuxt-no-ssr header, it uses the SPA renderer.

    SSR Renderer: Uses vue-bundle-renderer to render the application to a string, incorporating the client manifest for asset management.

    SPA Renderer: Renders a minimal placeholder (<div id="__nuxt"></div>) and replicates unhead behavior to handle meta tags in a client-side compatible way.

  4. Understand the ViteBuildContext structure

    main

    The ViteBuildContext is the object that holds the environment state for Vite within Nuxt Bridge. It provides access to the Nuxt instance, the Vite configuration, and the running dev servers.

    Properties:

    • nuxt: The Nuxt instance.
    • config: The ViteOptions used for the build.
    • clientServer: The ViteDevServer instance for the client-side.
    • ssrServer: The ViteDevServer instance for the server-side (SSR).
    • builder: Contains an array of plugins with their name, src, and mode ('client' or 'server').
  5. Schema differences between Nuxt Bridge and Nuxt 2

    main

    When migrating from Nuxt 2 to Nuxt Bridge, be aware of the following configuration schema changes and property renames:

    Renamed Properties

    • transition is now pageTransition
    • export is now generate
    • gzip is now compressor
    • build.crossorigin is now render.crossorigin
    • render.csp.unsafeInlineCompatiblity (typo in Nuxt 2) is now render.csp.unsafeInlineCompatibility
    • publicPath is now _publicPath (to preserve the original value)

    New or Modified Behaviors

    • Build Options: build.indicator and build.loadingScreen are available.
    • Babel: options.build.babel.presets is an array. Note that @nuxtjs/babel-preset-app is deprecated in favor of @nuxt/babel-preset-app.
    • Rendering: render.etag.hash should be a function.
    • Consola: The consola level is automatically set to 0 if build.quiet is true.
    • Deprecations: devModules is deprecated.

    Directory Guards

    The following directory mappings are enforced:

    • rootDir maps to buildDir and generate.dir
    • srcDir maps to buildDir and generate.dir
  6. Manage document head with Head components

    main

    Nuxt Bridge provides a set of Vue components to declaratively manage the HTML <head>, <html>, and <body> tags. These components use useHead under the hood to inject metadata, scripts, links, and styles into the document. Most components accept standard HTML attributes (like id, class, lang) via globalProps and specific attributes relevant to their tag type.

    <template>
      <div>
        <Head>
          <Title>My Page Title</Title>
          <Meta name="description" content="A description of my page" />
          <Link rel="stylesheet" href="/styles.css" />
          <Script src="/script.js" />
        </Head>
        <h1>Hello World</h1>
      </div>
    </template>
  7. Understand `AsyncDataRequestStatus` states

    main

    The status property returned by useAsyncData is a reactive reference that indicates the current state of the request. The possible values are:

    • 'idle': The request has not started yet (e.g., if immediate: false was used).
    • 'pending': The asynchronous handler is currently executing.
    • 'success': The handler resolved successfully.
    • 'error': The handler failed.
  8. Configure ESLint for Nuxt Bridge

    main

    Nuxt Bridge uses a flat configuration for ESLint (eslint.config.mjs) that integrates TypeScript, Vue 2, and various stylistic plugins. It uses neostandard, typescript-eslint, and eslint-plugin-vue (specifically the flat/vue2-recommended config) to enforce code quality.

    Key features include:

    • TypeScript Support: Uses tseslint for parsing and recommended rules.
    • Vue 2 Support: Configured with vue-eslint-parser and eslint-plugin-vue for .vue files.
    • Global Variables: Automatically includes browser, node, es2021, NodeJS, and $fetch globals.
    • Import Resolution: Uses eslint-plugin-import-x with a TypeScript resolver pointing to ./tsconfig.json.
    import { defineConfig } from 'eslint/config'
    
    export default defineConfig(
      // ... configuration blocks
    )
  9. Configure Nuxt Bridge via the bridge key

    main

    In a Nuxt Bridge project, you can enable or configure Bridge features within your nuxt.config.ts using the bridge property. This property is part of the Nuxt2Config interface extended by Bridge. You can set it to false to disable Bridge or provide a partial BridgeConfig object to toggle specific engines like Nitro, Vite, or CAPI.

    export default defineNuxtConfig({
      bridge: {
        vite: true,
        nitro: true,
        typescript: { esbuild: true }
      }
    })
  10. Configure `useAsyncData` options

    main

    You can customize the behavior of useAsyncData using the AsyncDataOptions object:

    • server (boolean, default: true): Whether to fetch the data on the server side.
    • lazy (boolean, default: false): If true, the navigation is not blocked while the data is being fetched. Use useLazyAsyncData as a shorthand.
    • default (function, default: () => null): A factory function to set the initial value of data before the handler resolves.
    • getCachedData (function): A function to retrieve cached data. If it returns undefined, a new fetch is triggered.
    • transform (function): A function to modify the result of the handler after it resolves.
    • pick (array of strings): An array of keys to extract from the handler's result.
    • watch (array of WatchSource): Reactive sources that, when changed, trigger an automatic refresh of the data.
    • immediate (boolean, default: true): Whether to execute the handler immediately.
    • deep (boolean, default: true): Whether to return the data in a deep reactive ref. Set to false for a shallowRef to improve performance.
    • dedupe (string, default: 'cancel'): Strategy to handle multiple simultaneous requests for the same key. Options are 'cancel' (cancels previous request) or 'defer' (returns the existing pending promise).
    const { data } = await useAsyncData('user', () => $fetch('/api/user'), {
      server: true,
      lazy: false,
      transform: (user) => ({ name: user.name }),
      pick: ['name'],
      watch: [someReactiveSource],
      dedupe: 'cancel'
    })