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

feat: preview mode add keyboard shortcuts #12968

Merged
merged 3 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 3 additions & 1 deletion packages/vite/src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { ServerOptions } from './server'
import type { LogLevel } from './logger'
import { createLogger } from './logger'
import { VERSION } from './constants'
import { bindShortcuts } from './shortcuts'
import { bindPreviewShortcuts, bindShortcuts } from './shortcuts'
import { resolveConfig } from '.'

const cli = cac('vite')
Expand Down Expand Up @@ -291,6 +291,7 @@ cli
},
)

// preview
cli
.command('preview [root]', 'locally preview production build')
.option('--host [host]', `[string] specify hostname`)
Expand Down Expand Up @@ -332,6 +333,7 @@ cli
},
})
server.printUrls()
bindPreviewShortcuts(server)
} catch (e) {
createLogger(options.logLevel).error(
colors.red(`error when starting preview server:\n${e.stack}`),
Expand Down
82 changes: 82 additions & 0 deletions packages/vite/src/node/shortcuts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import colors from 'picocolors'
import type { ViteDevServer } from './server'
import { isDefined } from './utils'
import type { PreviewServer } from './preview'
import { openBrowser } from './server/openBrowser'

export type BindShortcutsOptions = {
/**
Expand Down Expand Up @@ -119,3 +121,83 @@ const BASE_SHORTCUTS: CLIShortcut[] = [
},
},
]

type PreviewShortcuts = {
key: string
description: string
action: (server: PreviewServer) => void
}

export function bindPreviewShortcuts(server: PreviewServer): void {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's factorise this code a bit with something like that:

type CLIShortcut<Server> = {
  key: string
  description: string
  action: (server: Server) => void
}

function bindShortcuts<Server>(server: Server, shortcuts: CLIShortcut<Server>[]): void {
  // almost exactly this code below
}

export function bindPreviewShortcuts(server: PreviewServer): void {
  bindShortcuts(server, previewShortcuts)
}

type PreviewShortcut = CLIShortcut<PreviewServer>

And then rename the other usage in this file to add a dev prefix

if (!server.httpServer || !process.stdin.isTTY || process.env.CI) {
return
}
server.config.logger.info(
colors.dim(colors.green(' ➜')) +
colors.dim(' press ') +
colors.bold('h') +
colors.dim(' to show help'),
)
let actionRunning = false
const onInput = async (input: string) => {
// ctrl+c or ctrl+d
if (input === '\x03' || input === '\x04') {
try {
server.httpServer.close()
} finally {
process.exit(1)
}
}
if (actionRunning) return
if (input === 'h') {
server.config.logger.info(
[
'',
colors.bold(' Shortcuts'),
...previewShortcuts.map(
(shortcut) =>
colors.dim(' press ') +
colors.bold(shortcut.key) +
colors.dim(` to ${shortcut.description}`),
),
].join('\n'),
)
}

const shortcut = previewShortcuts.find((shortcut) => shortcut.key === input)
if (!shortcut) return
actionRunning = true
shortcut.action(server)
actionRunning = false
}

process.stdin.setRawMode(true)

process.stdin.on('data', onInput).setEncoding('utf8').resume()

server.httpServer.on('close', () => {
process.stdin.off('data', onInput).pause()
})
}

const previewShortcuts: PreviewShortcuts[] = [
{
key: 'o',
description: 'open in browser',
action(server) {
const url = server.resolvedUrls.local[0]
openBrowser(url, true, server.config.logger)
},
},
{
key: 'q',
description: 'quit',
action(server) {
try {
server.httpServer.close()
} finally {
process.exit()
}
},
},
]