> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/vitejs/vite/llms.txt
> Use this file to discover all available pages before exploring further.

# Backend Integration

> Integrate Vite with traditional backend frameworks like Rails, Laravel, and more

<Tip>
  If you want to serve the HTML using a traditional backend (e.g. Rails, Laravel) but use Vite for serving assets, check for existing integrations listed in [Awesome Vite](https://github.com/vitejs/awesome-vite#integrations-with-backends).

  If you need a custom integration, you can follow the steps in this guide to configure it manually.
</Tip>

## Configuration Steps

<Steps>
  <Step title="Configure Vite entry and manifest">
    In your Vite config, configure the entry and enable build manifest:

    ```js vite.config.js theme={null}
    import { defineConfig } from 'vite'

    export default defineConfig({
      server: {
        cors: {
          // the origin you will be accessing via browser
          origin: 'http://my-backend.example.com',
        },
      },
      build: {
        // generate .vite/manifest.json in outDir
        manifest: true,
        rollupOptions: {
          // overwrite default .html entry
          input: '/path/to/main.js',
        },
      },
    })
    ```

    <Note>
      If you haven't disabled the [module preload polyfill](/config/build-options#build-polyfillmodulepreload), you also need to import the polyfill in your entry:

      ```js theme={null}
      // add the beginning of your app entry
      import 'vite/modulepreload-polyfill'
      ```
    </Note>
  </Step>

  <Step title="Set up development scripts">
    For development, inject the following in your server's HTML template (substitute `http://localhost:5173` with the local URL Vite is running at):

    ```html theme={null}
    <!-- if development -->
    <script type="module" src="http://localhost:5173/@vite/client"></script>
    <script type="module" src="http://localhost:5173/main.js"></script>
    ```

    In order to properly serve assets, you have two options:

    * Make sure the server is configured to proxy static assets requests to the Vite server
    * Set [`server.origin`](/config/server-options#server-origin) so that generated asset URLs will be resolved using the back-end server URL instead of a relative path

    This is needed for assets such as images to load properly.

    <Warning>
      If you are using React with `@vitejs/plugin-react`, you'll also need to add this before the above scripts, since the plugin is not able to modify the HTML you are serving (substitute `http://localhost:5173` with the local URL Vite is running at):

      ```html theme={null}
      <script type="module">
        import RefreshRuntime from 'http://localhost:5173/@react-refresh'
        RefreshRuntime.injectIntoGlobalHook(window)
        window.$RefreshReg$ = () => {}
        window.$RefreshSig$ = () => (type) => type
        window.__vite_plugin_react_preamble_installed__ = true
      </script>
      ```
    </Warning>
  </Step>

  <Step title="Generate manifest for production">
    For production, after running `vite build`, a `.vite/manifest.json` file will be generated alongside other asset files. An example manifest file looks like this:

    ```json .vite/manifest.json theme={null}
    {
      "_shared-B7PI925R.js": {
        "file": "assets/shared-B7PI925R.js",
        "name": "shared",
        "css": ["assets/shared-ChJ_j-JJ.css"]
      },
      "_shared-ChJ_j-JJ.css": {
        "file": "assets/shared-ChJ_j-JJ.css",
        "src": "_shared-ChJ_j-JJ.css"
      },
      "logo.svg": {
        "file": "assets/logo-BuPIv-2h.svg",
        "src": "logo.svg"
      },
      "baz.js": {
        "file": "assets/baz-B2H3sXNv.js",
        "name": "baz",
        "src": "baz.js",
        "isDynamicEntry": true
      },
      "views/bar.js": {
        "file": "assets/bar-gkvgaI9m.js",
        "name": "bar",
        "src": "views/bar.js",
        "isEntry": true,
        "imports": ["_shared-B7PI925R.js"],
        "dynamicImports": ["baz.js"]
      },
      "views/foo.js": {
        "file": "assets/foo-BRBmoGS9.js",
        "name": "foo",
        "src": "views/foo.js",
        "isEntry": true,
        "imports": ["_shared-B7PI925R.js"],
        "css": ["assets/foo-5UjPuW-k.css"]
      }
    }
    ```
  </Step>

  <Step title="Use the manifest to render links">
    You can use this file to render links or preload directives with hashed filenames.

    Here is an example HTML template to render the proper links. The syntax here is for explanation only, substitute with your server templating language:

    ```html theme={null}
    <!-- if production -->

    <!-- for cssFile of manifest[name].css -->
    <link rel="stylesheet" href="/{{ cssFile }}" />

    <!-- for chunk of importedChunks(manifest, name) -->
    <!-- for cssFile of chunk.css -->
    <link rel="stylesheet" href="/{{ cssFile }}" />

    <script type="module" src="/{{ manifest[name].file }}"></script>

    <!-- for chunk of importedChunks(manifest, name) -->
    <link rel="modulepreload" href="/{{ chunk.file }}" />
    ```
  </Step>
</Steps>

## Manifest Structure

The manifest has a `Record<name, chunk>` structure where each chunk follows the `ManifestChunk` interface:

```ts theme={null}
interface ManifestChunk {
  /**
   * The input file name of this chunk / asset if known
   */
  src?: string
  /**
   * The output file name of this chunk / asset
   */
  file: string
  /**
   * The list of CSS files imported by this chunk
   */
  css?: string[]
  /**
   * The list of asset files imported by this chunk, excluding CSS files
   */
  assets?: string[]
  /**
   * Whether this chunk or asset is an entry point
   */
  isEntry?: boolean
  /**
   * The name of this chunk / asset if known
   */
  name?: string
  /**
   * Whether this chunk is a dynamic entry point
   */
  isDynamicEntry?: boolean
  /**
   * The list of statically imported chunks by this chunk
   */
  imports?: string[]
  /**
   * The list of dynamically imported chunks by this chunk
   */
  dynamicImports?: string[]
}
```

### Manifest Entry Types

Each entry in the manifest represents one of the following:

<Accordion title="Entry chunks">
  Generated from files specified in [`build.rollupOptions.input`](https://rollupjs.org/configuration-options/#input). These chunks have `isEntry: true` and their key is the relative src path from project root.
</Accordion>

<Accordion title="Dynamic entry chunks">
  Generated from dynamic imports. These chunks have `isDynamicEntry: true` and their key is the relative src path from project root.
</Accordion>

<Accordion title="Non-entry chunks">
  Their key is the base name of the generated file prefixed with `_`.
</Accordion>

<Accordion title="Asset chunks">
  Generated from imported assets like images, fonts. Their key is the relative src path from project root.
</Accordion>

<Accordion title="CSS files">
  When [`build.cssCodeSplit`](/config/build-options#build-csscodesplit) is `false`, a single CSS file is generated with the key `style.css`. When `build.cssCodeSplit` is not `false`, the key is generated similar to JS chunks (i.e. entry chunks will not have `_` prefix and non-entry chunks will have `_` prefix).
</Accordion>

## Rendering Tags in Production

Specifically, a backend generating HTML should include the following tags given a manifest file and an entry point. Note that following this order is recommended for optimal performance:

1. A `<link rel="stylesheet">` tag for each file in the entry point chunk's `css` list (if it exists)
2. Recursively follow all chunks in the entry point's `imports` list and include a `<link rel="stylesheet">` tag for each CSS file of each imported chunk's `css` list (if it exists)
3. A tag for the `file` key of the entry point chunk. This can be `<script type="module">` for JavaScript, `<link rel="stylesheet">` for CSS
4. Optionally, `<link rel="modulepreload">` tag for the `file` of each imported JavaScript chunk, again recursively following the imports starting from the entry point chunk

### Example: Entry Point `views/foo.js`

Following the example manifest above, for the entry point `views/foo.js` the following tags should be included in production:

```html theme={null}
<link rel="stylesheet" href="assets/foo-5UjPuW-k.css" />
<link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" />
<script type="module" src="assets/foo-BRBmoGS9.js"></script>
<!-- optional -->
<link rel="modulepreload" href="assets/shared-B7PI925R.js" />
```

### Example: Entry Point `views/bar.js`

For the entry point `views/bar.js`:

```html theme={null}
<link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" />
<script type="module" src="assets/bar-gkvgaI9m.js"></script>
<!-- optional -->
<link rel="modulepreload" href="assets/shared-B7PI925R.js" />
```

<Accordion title="Pseudo implementation of importedChunks">
  An example pseudo implementation of `importedChunks` in TypeScript (This will need to be adapted for your programming language and templating language):

  ```ts theme={null}
  import type { Manifest, ManifestChunk } from 'vite'

  export default function importedChunks(
    manifest: Manifest,
    name: string,
  ): ManifestChunk[] {
    const seen = new Set<string>()

    function getImportedChunks(chunk: ManifestChunk): ManifestChunk[] {
      const chunks: ManifestChunk[] = []
      for (const file of chunk.imports ?? []) {
        const importee = manifest[file]
        if (seen.has(file)) {
          continue
        }
        seen.add(file)

        chunks.push(...getImportedChunks(importee))
        chunks.push(importee)
      }

      return chunks
    }

    return getImportedChunks(manifest[name])
  }
  ```
</Accordion>
