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

vike cli #1434

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
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
6 changes: 3 additions & 3 deletions examples/react-minimal/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite build && vite preview"
"dev": "vike",
"build": "vike build",
"preview": "vike build && vike preview"
},
"dependencies": {
"@vitejs/plugin-react": "^4.2.1",
Expand Down
2 changes: 2 additions & 0 deletions vike/TODO
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- node/cli/{bin.ts,bin-entry.js} => node/cli/{entry.ts,bin.js}

- userAgent for vike-{vue,solid}
- improve vike.dev/head
- Remove `pageContext.data.title` from boilerplates
Expand Down
2 changes: 2 additions & 0 deletions vike/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint doesn't seem to support `package.json#exports`.
export * from './dist/esm/node/api/index.mjs'
5 changes: 4 additions & 1 deletion vike/client/client-routing-runtime/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Utils needed by Client Routing.

// We assume all runtime entries will load this utils.ts file
// We call onLoad() here in order to make sure it's always called, even if only a subset of client/client-routing-runtime/** is loaded.
// - (Otherwise we'd need to call onLoad() in both client/client-routing-runtime/index.ts and client/client-routing-runtime/entry.ts)
// - (Calling onLoad() here is also future-proof in case we move `import { navigate } from 'vike/client/router'` to `import { navigate } from 'vike/navigate';` or `import { navigate } from 'vike/client';`.)
// - (Also, calling onLoad() here avoids node/** to mistakenly load a client/** file, as the assertIsBrowser() call inside onLoad() will throw an error.)
import { onLoad } from './onLoad.js'
onLoad()

Expand Down
2 changes: 1 addition & 1 deletion vike/client/server-routing-runtime/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Utils needed by Server Routing.

// We assume all runtime entries will load this utils.ts file
// We call onLoad() here in order to make sure it's always called, even if only a subset of client/server-routing-runtime/** is loaded.
import { onLoad } from './onLoad.js'
onLoad()

Expand Down
39 changes: 39 additions & 0 deletions vike/node/api/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export { build }

import { resolveConfig } from './resolveConfig.js'
import { isVikeCli } from './isVikeCli.js'
import { build as buildVite } from 'vite'
import pc from '@brillout/picocolors'

async function build() {
const { viteConfig, vikeConfigResolved, viteConfigResolved: resolvedConfig } = await resolveConfig({}, 'build')

const clientOutput = await buildVite(viteConfig).catch((error) => {
if (!isVikeCli) {
throw error
}
resolvedConfig.logger.error(pc.red(`error during build:\n${error.stack}`), { error })
process.exit(1)
})

const serverOutput = await buildVite({
...viteConfig,
build: {
...viteConfig.build,
ssr: true
}
}).catch((error) => {
if (!isVikeCli) {
throw error
}
resolvedConfig.logger.error(pc.red(`error during build:\n${error.stack}`), { error })
process.exit(1)
})

if (vikeConfigResolved.prerender) {
const { runPrerenderFromAutoRun } = await import('../prerender/runPrerender.js')
await runPrerenderFromAutoRun(viteConfig)
}

return { clientOutput, serverOutput }
}
16 changes: 16 additions & 0 deletions vike/node/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export { build_ as build }
export { serve_ as serve }
export { preview_ as preview }
export { prerender_ as prerender }

import type { build } from './build.js'
import type { serve } from './serve.js'
import type { preview } from './preview.js'
import type { prerender } from './prerender.js'
import { assertIsNotBrowser } from '../../utils/assertIsNotBrowser.js'
assertIsNotBrowser()

const build_: typeof build = async (...args) => (await import('./build.js')).build(...args)
const serve_: typeof serve = async (...args) => (await import('./serve.js')).serve(...args)
const preview_: typeof preview = async (...args) => (await import('./preview.js')).preview(...args)
const prerender_: typeof prerender = async (...args) => (await import('./prerender.js')).prerender(...args)
7 changes: 7 additions & 0 deletions vike/node/api/isVikeCli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { isVikeCli }
export { setIsVikeCli }

let isVikeCli = false
function setIsVikeCli() {
isVikeCli = true
}
1 change: 1 addition & 0 deletions vike/node/api/prerender.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { runPrerenderFromAPI as prerender } from '../prerender/runPrerender.js'
24 changes: 24 additions & 0 deletions vike/node/api/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export { preview }

import { resolveConfig } from './resolveConfig.js'
import { isVikeCli } from './isVikeCli.js'
import { preview as previewVite } from 'vite'
import pc from '@brillout/picocolors'

async function preview() {
// Adds vike to viteConfig if not present
const { viteConfig, viteConfigResolved: resolvedConfig } = await resolveConfig({}, 'preview')
if (!isVikeCli) return previewVite(viteConfig)

try {
const server = await previewVite(viteConfig)
server.printUrls()
server.bindCLIShortcuts({ print: true })
return server
} catch (e: any) {
resolvedConfig.logger.error(pc.red(`error when starting preview server:\n${e.stack}`), {
error: e
})
process.exit(1)
}
}
53 changes: 53 additions & 0 deletions vike/node/api/resolveConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
export { resolveConfig }

import pc from '@brillout/picocolors'
import type { InlineConfig } from 'vite'
import { resolveConfig as resolveViteConfig } from 'vite'
import { getConfigVike } from '../shared/getConfigVike.js'
import { isVikeCli } from './isVikeCli.js'

async function resolveConfig(viteConfig: InlineConfig, command: 'build' | 'serve' | 'preview') {
//TODO: do we need this?
let nodeEnv = 'development'
if (['build', 'preview'].includes(command)) {
nodeEnv = 'production'
}

const viteConfigResolved = await resolveViteConfig(
viteConfig,
command === 'preview' ? 'serve' : command,
'custom',
nodeEnv,
command === 'preview'
).catch((error) => {
if (!isVikeCli) {
throw error
}
console.error(pc.red(`error resolving config:\n${error.stack}`), {
error
})
process.exit(1)
})

// Add vike to plugins if not present
if (!viteConfigResolved.plugins.some((p) => p.name.startsWith('vike:'))) {
// We using a dynamic import because the script calling the VIke API may not live in the same place as vite.config.js, thus have vike/plugin may resolved to two different node_modules/vike directories
const { plugin } = await import('../plugin/index.js')

viteConfig ??= {}
viteConfig.plugins ??= []
viteConfig.plugins.push(plugin())

return resolveConfig(viteConfig, command)
}

const vikeConfigResolved = await getConfigVike(viteConfigResolved)

//TODO: add vite plugins from extension to viteConfig.plugins

return {
viteConfig,
vikeConfigResolved,
viteConfigResolved
}
}
38 changes: 38 additions & 0 deletions vike/node/api/serve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export { serve }

import { resolveConfig } from './resolveConfig.js'
import { isVikeCli } from './isVikeCli.js'
import { startTime } from '../cli/bin.js'
import { projectInfo } from '../../utils/projectInfo.js'
import { createServer } from 'vite'
import pc from '@brillout/picocolors'

const { projectName, projectVersion } = projectInfo

async function serve() {
// Adds vike to viteConfig if not present
const { viteConfig, viteConfigResolved: resolvedConfig } = await resolveConfig({}, 'serve')
if (!isVikeCli) return createServer(viteConfig)

try {
const server = await createServer(viteConfig)
await server.listen()
const info = server.config.logger.info
const startupDurationString = pc.dim(
`ready in ${pc.reset(pc.bold(String(Math.ceil(performance.now() - startTime))))} ms`
)
const hasExistingLogs = process.stdout.bytesWritten > 0 || process.stderr.bytesWritten > 0
info(`\n ${pc.cyan(`${pc.bold(projectName)} v${projectVersion}`)} ${startupDurationString}\n`, {
clear: !hasExistingLogs
})

server.printUrls()
server.bindCLIShortcuts({ print: true })
return server
} catch (e: any) {
resolvedConfig.logger.error(pc.red(`error when starting dev server:\n${e.stack}`), {
error: e
})
process.exit(1)
}
}
65 changes: 25 additions & 40 deletions vike/node/cli/bin.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,34 @@
import { cac } from 'cac'
import { resolve } from 'path'
import { runPrerenderFromCLI, runPrerender_forceExit } from '../prerender/runPrerender.js'
import { projectInfo, assertUsage, assertWarning } from './utils.js'
import pc from '@brillout/picocolors'
import { projectInfo, assertUsage, assertIsNotBrowser } from './utils.js'
import { setIsVikeCli } from '../api/isVikeCli.js'
import { serve, build, preview } from '../api/index.js'
assertIsNotBrowser()

setIsVikeCli()

const cli = cac(projectInfo.projectName)
export const startTime = performance.now()

cli.command('prerender', 'Pre-render the HTML of your pages').action(async () => {
const { runPrerenderFromCLIStandalone } = await import('../prerender/runPrerender.js')
await runPrerenderFromCLIStandalone()
})

cli
.command('prerender', 'Pre-render the HTML of your pages', { allowUnknownOptions: true })
.option('--configFile <path>', '[string] Path to vite.config.js')
.action(async (options) => {
assertOptions()
const { partial, noExtraDir, base, parallel, outDir, configFile } = options
const root = options.root && resolve(options.root)
await runPrerenderFromCLI({ partial, noExtraDir, base, root, parallel, outDir, configFile })
runPrerender_forceExit()
.command('', 'Start the development server')
.alias('serve')
.alias('dev')
.action(async () => {
await serve()
})

function assertOptions() {
// Using process.argv because cac convert names to camelCase
const rawOptions = process.argv.slice(3)
Object.values(rawOptions).forEach((option) => {
assertUsage(
!option.startsWith('--') ||
[
'--root',
'--partial',
'--noExtraDir',
'--clientRouter',
'--base',
'--parallel',
'--outDir',
'--configFile'
].includes(option),
'Unknown option: ' + option
)
assertWarning(
false,
`You set ${pc.cyan(option)}, but passing options to ${pc.cyan(
'$ vike prerender'
)} is deprecated: use the config file instead. See https://vike.dev/command-prerender.`,
{ onlyOnce: true }
)
})
}
cli.command('build', 'Build for production').action(async () => {
await build()
})

cli.command('preview', 'Start a preview server using production build').action(async () => {
await preview()
})

// Listen to unknown commands
cli.on('command:*', () => {
Expand All @@ -53,7 +38,7 @@ cli.on('command:*', () => {
cli.help()
cli.version(projectInfo.projectVersion)

cli.parse(process.argv.length === 2 ? [...process.argv, '--help'] : process.argv)
cli.parse()

process.on('unhandledRejection', (rejectValue) => {
throw rejectValue
Expand Down
21 changes: 11 additions & 10 deletions vike/node/cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// TODO/v1-release: remove this file

import { prerender as prerenderOriginal } from '../prerender/index.js'
import { assertWarning } from './utils.js'
export const prerender: typeof prerenderOriginal = (options) => {
assertWarning(
false,
"`import { prerender } from 'vike/cli'` is deprecated in favor of `import { prerender } from 'vike/prerender'``",
{ onlyOnce: true, showStackTrace: true }
)
return prerenderOriginal(options)
}
export { runPrerenderFromAPI as prerender } from '../prerender/runPrerender.js'

import { assertWarning } from '../../utils/assert.js'
import pc from '@brillout/picocolors'
assertWarning(
false,
`${pc.cyan("import { prerender } from 'vike/cli'")} is deprecated in favor of ${pc.cyan(
"import { prerender } from 'vike/api'"
)}`,
{ onlyOnce: true }
)
7 changes: 0 additions & 7 deletions vike/node/cli/onLoad.ts

This file was deleted.

5 changes: 1 addition & 4 deletions vike/node/cli/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// We assume all runtime entries will load this utils.ts file
import { onLoad } from './onLoad.js'
onLoad()

export * from '../../utils/assert.js'
export * from '../../utils/assertIsNotBrowser.js'
export * from '../../utils/projectInfo.js'
4 changes: 2 additions & 2 deletions vike/node/plugin/plugins/autoFullBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export { autoFullBuild }
import { build } from 'vite'
import type { InlineConfig, Plugin, ResolvedConfig } from 'vite'
import { assertWarning } from '../utils.js'
import { runPrerenderFromAutoFullBuild, runPrerender_forceExit } from '../../prerender/runPrerender.js'
import { runPrerenderFromAutoRun, runPrerender_forceExit } from '../../prerender/runPrerender.js'
import { getConfigVike } from '../../shared/getConfigVike.js'
import type { ConfigVikeResolved } from '../../../shared/ConfigVike.js'
import { isViteCliCall, getViteConfigFromCli } from '../shared/isViteCliCall.js'
Expand Down Expand Up @@ -95,7 +95,7 @@ async function triggerFullBuild(
}

if (configVike.prerender && !configVike.prerender.disableAutoRun) {
await runPrerenderFromAutoFullBuild({ viteConfig: configInline })
await runPrerenderFromAutoRun(configInline)
forceExit = true
}
}
Expand Down
4 changes: 3 additions & 1 deletion vike/node/plugin/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Utils needed by Vike's Vite plugin.

// We assume all runtime entries will load this utils.ts file
// We call onLoad() here in order to make sure it's always called, even if only a subset of node/plugin/** is loaded.
// - (Calling onLoad() in node/plugin/index.ts wouldn't be enough: for example if node/runtime/** mistakenly loads a node/plugin/** file.)
// - (It isn't 100% guaranteed that onLoad() is called: it isn't called when the loaded module doesn't use utils.ts but it's unlikely.)
import { onLoad } from './onLoad.js'
onLoad()

Expand Down
12 changes: 12 additions & 0 deletions vike/node/prerender/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
// TODO/v1-release: remove this file

export { runPrerenderFromAPI as prerender } from './runPrerender.js'

import { assertWarning } from './utils.js'
import pc from '@brillout/picocolors'
assertWarning(
false,
`${pc.cyan("import { prerender } from 'vike/prerender'")} is deprecated in favor of ${pc.cyan(
"import { prerender } from 'vike/api'"
)}`,
{ onlyOnce: true }
)
Loading
Loading