{
  "doc": {
    "id": "app/write-tests/component-testing/component-framework-configuration",
    "title": "Configure component tests",
    "description": "Configure Cypress for component testing with dev servers, bundlers, custom index files, and spec patterns.",
    "section": "app",
    "source_path": "/llm/markdown/app/write-tests/component-testing/component-framework-configuration.md",
    "version": "066c46e056f0f322a0670d2d3aa4e6adaebfe717",
    "updated_at": "2026-09-10T13:30:12.426Z",
    "headings": [
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#component-testing-configuration",
        "text": "Component Testing Configuration",
        "level": 1
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#dev-server-and-bundler",
        "text": "Dev Server and Bundler",
        "level": 2
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#how-it-works-at-runtime",
        "text": "How it works at runtime",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#recommended-configuration",
        "text": "Recommended configuration",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#supported-framework-and-bundler-values",
        "text": "Supported framework and bundler values",
        "level": 4
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#automatic-bundler-configuration-detection",
        "text": "Automatic bundler configuration detection",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#vite",
        "text": "Vite",
        "level": 4
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#webpack",
        "text": "Webpack",
        "level": 4
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#overriding-bundler-configuration",
        "text": "Overriding bundler configuration",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#vite-overrides",
        "text": "Vite overrides",
        "level": 4
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#webpack-overrides",
        "text": "Webpack overrides",
        "level": 4
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#resolving-import-path-aliases",
        "text": "Resolving import path aliases",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#meta-frameworks-that-own-the-bundler-config",
        "text": "Meta-frameworks that own the bundler config",
        "level": 4
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#aliases-defined-in-tsconfig-json",
        "text": "Aliases defined in tsconfig.json",
        "level": 4
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#function-syntax-advanced",
        "text": "Function syntax (advanced)",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#devserverpublicpathroute",
        "text": "devServerPublicPathRoute",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#custom-index-file",
        "text": "Custom Index File",
        "level": 2
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#fully-custom-dev-server",
        "text": "Fully Custom Dev Server",
        "level": 2
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#spec-pattern-for-component-tests",
        "text": "Spec Pattern for Component Tests",
        "level": 2
      },
      {
        "id": "app/write-tests/component-testing/component-framework-configuration#additional-config",
        "text": "Additional Config",
        "level": 2
      }
    ]
  },
  "content": {
    "type": "root",
    "children": [
      {
        "type": "heading",
        "depth": 1,
        "children": [
          {
            "type": "text",
            "value": "Component Testing Configuration"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When you launch Cypress for the first time in a project, the app will automatically guide you through setup and configuration. The Launchpad detects your UI framework and bundler, lists the required dependencies needed for you to install, and scaffolds a `cypress.config` file with a `component.devServer` block."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The sections below explain what that configuration does and how to customize it. For framework-specific options (such as Angular monorepos or Next.js), also see the overview guide for your UI library:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/component-testing/react/overview.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "React"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/component-testing/vue/overview.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Vue"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/component-testing/angular/overview.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Angular"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/component-testing/svelte/overview.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Svelte"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Dev Server and Bundler"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Component tests run inside a real browser, but unlike end-to-end tests they do not visit your production or staging app. Instead, Cypress starts a dev server that compiles and serves your component specs on demand."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The dev server is responsible for:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": true,
        "start": 1,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Compiling each spec file (and your support file) with the same transforms your app uses in development (JSX/TSX, Vue SFCs, CSS modules, path aliases, and so on)."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Serving those compiled files over HTTP so Cypress App can load them."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Shutting down cleanly when you close the Cypress App or finish a test run."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Cypress ships with built-in dev server implementations for Vite and Webpack. You do not need to install `@cypress/vite-dev-server` or `@cypress/webpack-dev-server` separately, they are bundled with the Cypress App."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "How it works at runtime"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When you open or run component tests, Cypress:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": true,
        "start": 1,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Reads `component.devServer` from your Cypress config file."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Starts the matching dev server (Vite or Webpack) on an available port."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Sets `baseUrl` to `http://localhost:<port>`."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Loads your component index HTML (by default `cypress/support/component-index.html`) and dynamically imports your support file (if configured) and the active spec, then hands control to Cypress."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Recommended configuration"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The recommended way to configure component testing is to use the `component.devServer` object. Specify your UI framework and bundler and Cypress will wire up the correct dev server implementation for you:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.ts"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  component: {\n    devServer: {\n      framework: 'react', // your UI framework\n      bundler: 'vite', // 'vite' or 'webpack'\n    },\n  },\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  component: {\n    devServer: {\n      framework: 'react', // your UI framework\n      bundler: 'vite', // 'vite' or 'webpack'\n    },\n  },\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This is the configuration that Cypress App scaffolds during project setup. It is all most projects need."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Supported `framework` and `bundler` values"
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`framework`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Supported `bundler` values"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Notes"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`react`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`vite`, `webpack`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": []
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`vue`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`vite`, `webpack`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": []
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`svelte`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`vite`, `webpack`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": []
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`next`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`webpack`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Uses Next.js-specific Webpack presets. See "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/component-testing/react/overview.md#Nextjs",
                    "children": [
                      {
                        "type": "text",
                        "value": "React overview — Next.js"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": "."
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`angular`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`webpack`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Supports an `options.projectConfig` override. See "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/component-testing/angular/overview.md#Options-API",
                    "children": [
                      {
                        "type": "text",
                        "value": "Angular overview"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": "."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Community framework definitions (packages named `cypress-ct-*` or `@org/cypress-ct-*`) can also be used as the `framework` value when paired with a supported bundler. See "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/component-testing/custom-frameworks.md",
            "children": [
              {
                "type": "text",
                "value": "Custom Frameworks"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Automatic bundler configuration detection"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When you use the `component.devServer` object, Cypress tries to reuse the same bundler configuration you already use to develop your app. You usually do not need to duplicate your entire Vite or Webpack config in your Cypress config file."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Vite"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you omit `viteConfig`, Cypress searches upward from your project root for a `vite.config.ts|js|mjs|cjs|mts|cts` file."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When a config file is found, Cypress loads it and merges in Cypress-specific settings (plugins, public path, spec entries, and file-system allow rules)."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If no config file is found, Cypress shows an error asking you to add a `vite.config` file or pass a `viteConfig` option explicitly."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Webpack"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you omit `webpackConfig`, Cypress searches upward from your project root for a `webpack.config.ts|js|mjs|cjs|mts|cts` file."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "For meta-frameworks like Next.js and Angular, Cypress applies framework-specific presets before merging your config. For React, Vue, and Svelte, Cypress merges your detected Webpack config with a Cypress-specific overlay."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If no Webpack config can be detected and no framework preset applies, Cypress shows an error asking you to add a `webpack.config` file or pass a `webpackConfig` option explicitly."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Overriding bundler configuration"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Pass `viteConfig` or `webpackConfig` when you need to customize what Cypress uses. For example, to add plugins, tweak aliases, or point to a config file outside the project root."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Both options accept either a config object or an async function that returns a config object."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Vite overrides"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.ts"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineConfig } = require('cypress')\nconst customViteConfig = require('./vite.config.custom')\n\nmodule.exports = defineConfig({\n  component: {\n    devServer: {\n      framework: 'react',\n      bundler: 'vite',\n      // Use a specific Vite config object\n      viteConfig: customViteConfig,\n      // Or compute one at runtime\n      viteConfig: async () => {\n        const base = await import('./vite.config')\n        return {\n          ...base.default,\n          // test-only overrides\n        }\n      },\n    },\n  },\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'\nimport customViteConfig from './vite.config.custom'\n\nexport default defineConfig({\n  component: {\n    devServer: {\n      framework: 'react',\n      bundler: 'vite',\n      // Use a specific Vite config object\n      viteConfig: customViteConfig,\n      // Or compute one at runtime\n      viteConfig: async () => {\n        const base = await import('./vite.config')\n        return {\n          ...base.default,\n          // test-only overrides\n        }\n      },\n    },\n  },\n})"
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Webpack overrides"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.ts"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineConfig } = require('cypress')\nconst webpackConfig = require('./webpack.config')\n\nmodule.exports = defineConfig({\n  component: {\n    devServer: {\n      framework: 'react',\n      bundler: 'webpack',\n      webpackConfig,\n      webpackConfig: async () => {\n        const base = await import('./webpack.config')\n        return {\n          ...base.default,\n          // test-only overrides\n        }\n      },\n    },\n  },\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'\nimport webpackConfig from './webpack.config'\n\nexport default defineConfig({\n  component: {\n    devServer: {\n      framework: 'react',\n      bundler: 'webpack',\n      webpackConfig,\n      webpackConfig: async () => {\n        const base = await import('./webpack.config')\n        return {\n          ...base.default,\n          // test-only overrides\n        }\n      },\n    },\n  },\n})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Resolving import path aliases"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If your components import modules through path aliases (for example `import Button from '@/components/Button'` or `import { api } from '~/lib/api'`), those aliases must be resolvable by the bundler Cypress uses, otherwise the spec fails to compile with a \"module not found\" (or \"failed to resolve import\") error."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Cypress does not define any aliases of its own. It resolves them exactly the way your dev server does, using the bundler config it detects or the one you pass in:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Vite: aliases come from the `resolve.alias` of the `vite.config` Cypress detects, or the `viteConfig` you pass to `devServer`."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Webpack: aliases come from the `resolve.alias` of the `webpack.config` Cypress detects, or the `webpackConfig` you pass to `devServer`."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "So if your aliases are declared in a standalone `vite.config` or `webpack.config` at (or above) your project root, Cypress picks them up automatically and no extra configuration is needed."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Meta-frameworks that own the bundler config"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Some meta-frameworks (such as Nuxt) configure Vite internally rather than through a standalone `vite.config` file. Cypress only reads a discoverable `vite.config`/`webpack.config`. It does not execute `nuxt.config` (or similar) to extract the bundler settings those frameworks generate at runtime. As a result, framework-provided aliases like Nuxt's `@/` and `~/` are not visible to Cypress and must be declared explicitly via `viteConfig`:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.ts"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineConfig } = require('cypress')\nconst { fileURLToPath } = require('url')\n\nmodule.exports = defineConfig({\n  component: {\n    devServer: {\n      framework: 'vue',\n      bundler: 'vite',\n      viteConfig: {\n        resolve: {\n          alias: {\n            '@': fileURLToPath(new URL('./', import.meta.url)),\n            '~': fileURLToPath(new URL('./', import.meta.url)),\n          },\n        },\n      },\n    },\n  },\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'\nimport { fileURLToPath } from 'url'\n\nexport default defineConfig({\n  component: {\n    devServer: {\n      framework: 'vue',\n      bundler: 'vite',\n      viteConfig: {\n        resolve: {\n          alias: {\n            '@': fileURLToPath(new URL('./', import.meta.url)),\n            '~': fileURLToPath(new URL('./', import.meta.url)),\n          },\n        },\n      },\n    },\n  },\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The aliases you pass are merged with Cypress's own Vite settings, so you only need to declare the ones your components rely on. The same applies to Webpack meta-frameworks: declare the aliases under `webpackConfig.resolve.alias`."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Aliases defined in `tsconfig.json`"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Aliases declared only under `compilerOptions.paths` in `tsconfig.json` are a TypeScript type-checking feature. Neither Vite nor Webpack reads them when bundling, so Cypress does not resolve them either. To make `tsconfig` paths work at bundle time, add the matching plugin to the config you give Cypress:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Vite: use "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://www.npmjs.com/package/vite-tsconfig-paths",
                    "children": [
                      {
                        "type": "text",
                        "value": "`vite-tsconfig-paths`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " in your `vite.config` (or in the `viteConfig` you pass to `devServer`)."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Webpack: use "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://www.npmjs.com/package/tsconfig-paths-webpack-plugin",
                    "children": [
                      {
                        "type": "text",
                        "value": "`tsconfig-paths-webpack-plugin`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " under `resolve.plugins` in your `webpack.config` (or the `webpackConfig` you pass to `devServer`)."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This is the same plugin your app already needs to resolve `tsconfig` paths at build time, so reusing your existing bundler config is usually enough."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Function syntax (advanced)"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you need direct access to the dev server API — for example, to pass options that are not exposed on the object syntax — use the function syntax and import the dev server from the appropriate package:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'\nimport { devServer as viteDevServer } from '@cypress/vite-dev-server'\n\nexport default defineConfig({\n  component: {\n    devServer(cypressDevServerConfig) {\n      return viteDevServer({\n        ...cypressDevServerConfig,\n        framework: 'react',\n        viteConfig: async () => {\n          const config = await import('./vite.config')\n          return config.default\n        },\n      })\n    },\n  },\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'\nimport { devServer as webpackDevServer } from '@cypress/webpack-dev-server'\n\nexport default defineConfig({\n  component: {\n    devServer(cypressDevServerConfig) {\n      return webpackDevServer({\n        ...cypressDevServerConfig,\n        framework: 'react',\n        webpackConfig: require('./webpack.config.js'),\n      })\n    },\n  },\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The function receives a `cypressDevServerConfig` object with:"
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Property"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Description"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`specs`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Spec files Cypress is about to run"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypressConfig`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "The resolved Cypress configuration"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`devServerEvents`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Event emitter for compile lifecycle events"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "It must return (or resolve to) an object with:"
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Property"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Description"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`port`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Port the dev server is listening on"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`close`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Optional callback to shut the server down"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You can store additional dev server options on `component.devServerConfig` when using the function syntax. This field is passed as the second argument to your `devServer` function."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "devServerPublicPathRoute"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The `devServerPublicPathRoute` option controls the URL path prefix Cypress uses to load compiled specs and assets. It defaults to `/__cypress/src`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In most projects the default works well. You may need to change it if component tests reference assets from your app's public directory and those paths must match your Vite `base` setting. For Vite 5+, set an empty string to align with Vite's default public path:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.ts"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  component: {\n    devServerPublicPathRoute: '',\n    devServer: {\n      framework: 'react',\n      bundler: 'vite',\n    },\n  },\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  component: {\n    devServerPublicPathRoute: '',\n    devServer: {\n      framework: 'react',\n      bundler: 'vite',\n    },\n  },\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Use caution when overriding this value — an incorrect public path can cause specs or assets to fail to load. See the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/references/configuration.md#component",
            "children": [
              {
                "type": "text",
                "value": "configuration reference"
              }
            ]
          },
          {
            "type": "text",
            "value": " for details."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Custom Index File"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "By default, Cypress renders your components into an HTML file located at `cypress/support/component-index.html`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The index file allows you to add in global assets, such as styles, fonts, and external scripts."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You can provide an alternative path to the file using the `indexHtmlFile` option in the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/references/configuration.md#component",
            "children": [
              {
                "type": "text",
                "value": "component config"
              }
            ]
          },
          {
            "type": "text",
            "value": " options:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "{\n  component: {\n    devServer: {\n      framework: 'react',\n      bundler: 'vite',\n    },\n    indexHtmlFile: '/custom/path/to/component-index.html',\n  },\n}"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Fully Custom Dev Server"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If your project uses a bundler other than Vite or Webpack, or you need complete control over compilation, pass a custom function to `component.devServer`. This is how community integrations and preview-server setups work."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The function receives a single `DevServerOptions` argument and must return (or resolve to) a `ResolvedDevServerConfig` describing how Cypress should connect to and stop the server."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "interface DevServerOptions {\n  specs: Cypress.Spec[]\n  cypressConfig: Cypress.PluginConfigOptions\n  devServerEvents: NodeJS.EventEmitter\n}\n\ninterface ResolvedDevServerConfig {\n  port: number // port the dev server is listening on\n  close?: (done?: () => void) => void // called by Cypress to shut the server down\n}"
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.js"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "cypress.config.ts"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  component: {\n    async devServer({ specs, cypressConfig, devServerEvents }) {\n      const { port, close } = await startDevServer(\n        specs,\n        cypressConfig,\n        devServerEvents\n      )\n\n      return {\n        port,\n        close,\n      }\n    },\n  },\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  component: {\n    async devServer({\n      specs,\n      cypressConfig,\n      devServerEvents,\n    }: DevServerOptions) {\n      const { port, close } = await startDevServer(\n        specs,\n        cypressConfig,\n        devServerEvents\n      )\n\n      return {\n        port,\n        close,\n      }\n    },\n  },\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Any requests triggered during a test using the `devServerPublicPathRoute` as defined in the `cypressConfig` will be forwarded to your server. Cypress will trigger a request for `[devServerPublicPathRoute]/index.html` when a test is started. Your server needs to reply with the html-file referenced in `cypressConfig.indexHtmlFile` and inject a script to load the support files and the actual test."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "function createServer(cypressConfig, bundleDir, port = 1234) {\n  const app = express()\n\n  // read kickstart script - see below for an example\n  const clientScript = readFileSync(\n    path.join(__dirname, './client-script.js'),\n    'utf8'\n  )\n\n  app.get(\n    cypressConfig.devServerPublicPathRoute + '/index.html',\n    async (_req, res) => {\n      // read custom index.html file\n      const html = await fs.readFile(\n        path.join(cypressConfig.repoRoot, cypressConfig.indexHtmlFile),\n        { encoding: 'utf8' }\n      )\n\n      // inject kickstart-script\n      const output = html.replace(\n        '</head>',\n        `<script type=\"module\">${clientScript}</script></head>`\n      )\n      res.send(output)\n    }\n  )\n\n  // you need to establish some url-to-path-mapping, if your bundler outputs\n  // the full directory structure you can map this one to one\n  app.use(cypressConfig.devServerPublicPathRoute, express.static(bundleDir))\n\n  app.listen(port)\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "For a real-world example, you can refer to "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress/blob/466155c2125476374d9f9549530f67d0c6354a41/npm/vite-dev-server/src/plugins/cypress.ts#L82-L92",
            "children": [
              {
                "type": "text",
                "value": "this loader"
              }
            ]
          },
          {
            "type": "text",
            "value": " used by the Vite Dev Server."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The client script must retrieve information on the currently active test from the Cypress instance of the parent frame and load the corresponding bundle. If a support file is defined, it should be injected at the top of your test bundle or loaded before the test script."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const CypressInstance = (window.Cypress = parent.Cypress)\nconst devServerPublicPathRoute = CypressInstance.config(\n  'devServerPublicPathRoute'\n)\n\n// `onSpecWindow` expects an array of functions that each return a dynamic\n// `import()`. Cypress invokes them in order, so the support file (if any)\n// must be added before the spec.\nconst importsToLoad = []\n\n// If you do not bundle your support file along with the tests,\n// you need to add a separate import statement for the support file.\nconst supportFilePath = CypressInstance.config('supportFile')\nif (supportFilePath) {\n  const relative = supportFilePath.replace(\n    CypressInstance.config('projectRoot'),\n    ''\n  )\n  importsToLoad.push(() => import(`${devServerPublicPathRoute}${relative}`))\n}\n\n// load the spec - you can extend the load function to also load css\nconst { relative } = CypressInstance.spec\nimportsToLoad.push(() => import(`${devServerPublicPathRoute}/${relative}`))\n\n// trigger loading the imports\nCypressInstance.onSpecWindow(window, importsToLoad)\n\n// then start the test process\nCypressInstance.action('app:window:before:load', window)"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "For a more complete example you can check out the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress/blob/develop/npm/vite-dev-server/client/initCypressTests.js",
            "children": [
              {
                "type": "text",
                "value": "kickstart script used in the vite-devserver."
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The `devServerEvents` event emitter is used to communicate compile lifecycle events between your server and Cypress:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Emit `dev-server:compile:success` to notify Cypress that a build finished and tests can run."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Listen for `dev-server:specs:changed` to be notified when Cypress updates the set of active spec files (e.g. when a new spec is added), so you can recompile the new entry points."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// signal to Cypress that compilation is done\ndevServerEvents.emit('dev-server:compile:success')\n\n// recompile when the active spec list changes\ndevServerEvents.on('dev-server:specs:changed', ({ specs }) => {\n  recompile(specs)\n})"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Spec Pattern for Component Tests"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "By default, Cypress looks for spec files anywhere in your project with an extension of `.cy.js`, `.cy.jsx`, `.cy.ts`, or `.cy.tsx`. However, you can change this behavior for component tests with a custom `specPattern` value. In the following example, we've configured Cypress to look for spec files with those same extensions, but only in the `src` folder or any of its subdirectories."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "{\n  component: {\n    devServer: {\n      framework: 'react',\n      bundler: 'vite',\n    },\n    specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',\n  },\n}"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Additional Config"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "For more information on all the available configuration options, see the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/references/configuration.md",
            "children": [
              {
                "type": "text",
                "value": "configuration reference"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      }
    ]
  },
  "token_estimate": 3457
}