Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make vite dev server open on a free port #15756

Merged
merged 7 commits into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions npm/vite-dev-server/cypress.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"pluginsFile": "cypress/plugins.js",
"video": false,
"testFiles": "**/*.spec.*",
"componentFolder": "cypress/components",
"supportFile": "cypress/support/support.js"
Expand Down
5 changes: 3 additions & 2 deletions npm/vite-dev-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"watch": "tsc -w"
},
"dependencies": {
"debug": "4.3.2"
"debug": "^4.3.2",
"get-port": "^5.1.1"
},
"devDependencies": {
"@cypress/react": "0.0.0-development",
Expand All @@ -27,7 +28,7 @@
"vue": "3.0.9"
},
"peerDependencies": {
"vite": ">= 2"
"vite": ">= 2.1.3"
},
"files": [
"dist",
Expand Down
18 changes: 2 additions & 16 deletions npm/vite-dev-server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,9 @@
import { EventEmitter } from 'events'
import { debug as debugFn } from 'debug'
import { start as createDevServer } from './startServer'
import { UserConfig } from 'vite'
import { Server } from 'http'
import { start as createDevServer, StartDevServer } from './startServer'
const debug = debugFn('cypress:vite-dev-server:vite')

interface Options {
specs: any[] // Cypress.Cypress['spec'][] // Why isn't this working? It works for webpack-dev-server
config: Record<string, string>
devServerEvents: EventEmitter
[key: string]: unknown
}

export interface StartDevServer {
/* this is the Cypress options object */
options: Options
/* support passing a path to the user's webpack config */
viteConfig?: UserConfig // TODO: implement taking in the user's vite configuration. Right now we don't
}
export { StartDevServer }

export interface ResolvedDevServerConfig {
port: number
Expand Down
3 changes: 1 addition & 2 deletions npm/vite-dev-server/src/makeCypressPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { EventEmitter } from 'events'
import { resolve } from 'path'
import { readFile } from 'fs'
import { promisify } from 'util'
Expand All @@ -24,7 +23,7 @@ export const makeCypressPlugin = (
if (env) {
return {
define: {
'import.meta.env.__cypress_supportPath': JSON.stringify(resolve(projectRoot, supportFilePath)),
'import.meta.env.__cypress_supportPath': JSON.stringify(supportFilePath ? resolve(projectRoot, supportFilePath) : undefined),
'import.meta.env.__cypress_originAutUrl': JSON.stringify('__cypress/iframes/'),
},
}
Expand Down
68 changes: 35 additions & 33 deletions npm/vite-dev-server/src/startServer.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,49 @@
import Debug from 'debug'
import { StartDevServer } from '.'
import { createServer, ViteDevServer, InlineConfig } from 'vite'
import { createServer, ViteDevServer, InlineConfig, UserConfig } from 'vite'
import { dirname, resolve } from 'path'
import getPort from 'get-port'
import { makeCypressPlugin } from './makeCypressPlugin'
import { EventEmitter } from 'events'

const debug = Debug('cypress:vite-dev-server:start')

// TODO: Pull in types for Options so we can infer these
const serverConfig = (projectRoot: string, supportFilePath: string, devServerEvents: EventEmitter): InlineConfig => {
return {
root: resolve(__dirname, projectRoot),
base: '/__cypress/src/',
plugins: [makeCypressPlugin(projectRoot, supportFilePath, devServerEvents)],
server: {
port: 0,
},
resolve: {
alias: {
// Necessary to avoid a "prefixIdentifiers" issue from slots mounting
// Could be resolved in test-utils
'@vue/compiler-core': resolve(dirname(require.resolve('@vue/compiler-core')), 'dist', 'compiler-core.cjs.js'),
},
},
}
interface Options {
specs: Cypress.Cypress['spec'][]
config: Record<string, string>
devServerEvents: EventEmitter
[key: string]: unknown
}

export interface StartDevServer {
/* this is the Cypress options object */
options: Options
/* support passing a path to the user's webpack config */
viteConfig?: UserConfig // TODO: implement taking in the user's vite configuration. Right now we don't
}

const resolveServerConfig = ({ viteConfig, options }: StartDevServer) => {
const defaultServerConfig = serverConfig(
options.config.projectRoot,
options.config.supportFile,
options.devServerEvents,
)
const resolveServerConfig = async ({ viteConfig, options }: StartDevServer): Promise<InlineConfig> => {
const { projectRoot, supportFile } = options.config

const requiredOptions = {
base: defaultServerConfig.base,
root: defaultServerConfig.root,
const requiredOptions: InlineConfig = {
base: '/__cypress/src/',
root: projectRoot,
}

const finalConfig = { ...defaultServerConfig, ...viteConfig, ...requiredOptions }
const finalConfig: InlineConfig = { ...viteConfig, ...requiredOptions }

finalConfig.plugins = [...(viteConfig.plugins || []), makeCypressPlugin(projectRoot, supportFile, options.devServerEvents)]

// This alias is necessary to avoid a "prefixIdentifiers" issue from slots mounting
// only cjs compiler-core accepts using prefixIdentifiers in slots which vue test utils use.
// Could we resolve this usage in test-utils?
finalConfig.resolve = finalConfig.resolve || {}
finalConfig.resolve.alias = {
...finalConfig.resolve.alias,
'@vue/compiler-core': resolve(dirname(require.resolve('@vue/compiler-core')), 'dist', 'compiler-core.cjs.js'),
},

finalConfig.server = finalConfig.server || {}

finalConfig.plugins = [...(viteConfig.plugins || []), defaultServerConfig.plugins[0]]
finalConfig.server.port = defaultServerConfig.server.port
finalConfig.server.port = await getPort({ port: 3000, host: 'localhost' }),

debug(`the resolved server config is ${JSON.stringify(finalConfig, null, 2)}`)

Expand All @@ -55,7 +57,7 @@ export async function start (devServerOptions: StartDevServer): Promise<ViteDevS
}

debug('starting vite dev server')
const resolvedConfig = resolveServerConfig(devServerOptions)
const resolvedConfig = await resolveServerConfig(devServerOptions)

return createServer(resolvedConfig)
}