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(cli): build watch mode #1449

Merged
merged 12 commits into from
Apr 5, 2021
Merged
152 changes: 114 additions & 38 deletions packages/vite/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import Rollup, {
RollupOutput,
ExternalOption,
GetManualChunk,
GetModuleInfo
GetModuleInfo,
WatcherOptions,
RollupWatcher,
RollupError
} from 'rollup'
import { buildReporterPlugin } from './plugins/reporter'
import { buildHtmlPlugin } from './plugins/html'
Expand Down Expand Up @@ -176,6 +179,11 @@ export interface BuildOptions {
* @default 500
*/
chunkSizeWarningLimit?: number
/**
* Rollup watch options
* https://rollupjs.org/guide/en/#watchoptions
*/
watch?: WatcherOptions | null
}

export interface LibraryOptions {
Expand Down Expand Up @@ -214,6 +222,7 @@ export function resolveBuildOptions(raw?: BuildOptions): ResolvedBuildOptions {
ssrManifest: false,
brotliSize: true,
chunkSizeWarningLimit: 500,
watch: null,
...raw
}

Expand Down Expand Up @@ -279,7 +288,7 @@ const paralellBuilds: RollupBuild[] = []
*/
export async function build(
inlineConfig: InlineConfig = {}
): Promise<RollupOutput | RollupOutput[]> {
): Promise<RollupOutput | RollupOutput[] | RollupWatcher> {
parallelCallCounts++
try {
return await doBuild(inlineConfig)
Expand All @@ -294,7 +303,7 @@ export async function build(

async function doBuild(
inlineConfig: InlineConfig = {}
): Promise<RollupOutput | RollupOutput[]> {
): Promise<RollupOutput | RollupOutput[] | RollupWatcher> {
const config = await resolveConfig(inlineConfig, 'build', 'production')
const options = config.build
const ssr = !!options.ssr
Expand Down Expand Up @@ -355,29 +364,39 @@ async function doBuild(
}

const rollup = require('rollup') as typeof Rollup
const rollupOptions: RollupOptions = {
input,
preserveEntrySignatures: ssr
? 'allow-extension'
: libOptions
? 'strict'
: false,
...options.rollupOptions,
plugins,
external,
onwarn(warning, warn) {
onRollupWarning(warning, warn, config)
}
}

try {
const bundle = await rollup.rollup({
input,
preserveEntrySignatures: ssr
? 'allow-extension'
: libOptions
? 'strict'
: false,
...options.rollupOptions,
plugins,
external,
onwarn(warning, warn) {
onRollupWarning(warning, warn, config)
}
})

paralellBuilds.push(bundle)
const outputBuildError = (e: RollupError) => {
config.logger.error(
chalk.red(`${e.plugin ? `[${e.plugin}] ` : ''}${e.message}`)
)
if (e.id) {
const loc = e.loc ? `:${e.loc.line}:${e.loc.column}` : ''
config.logger.error(`file: ${chalk.cyan(`${e.id}${loc}`)}`)
}
if (e.frame) {
config.logger.error(chalk.yellow(e.frame))
}
}

try {
const pkgName = libOptions && getPkgName(config.root)

const generate = (output: OutputOptions = {}) => {
return bundle[options.write ? 'write' : 'generate']({
const buildOuputOptions = (output: OutputOptions = {}): OutputOptions => {
return {
dir: outDir,
format: ssr ? 'cjs' : 'es',
exports: ssr ? 'named' : 'auto',
Expand Down Expand Up @@ -406,7 +425,79 @@ async function doBuild(
? createMoveToVendorChunkFn(config)
: undefined,
...output
}
}

// resolve lib mode outputs
const outputs = resolveBuildOutputs(
options.rollupOptions?.output,
libOptions,
config.logger
)

// watch file changes with rollup
if (config.build.watch) {
config.logger.info(chalk.cyanBright(`watching for file changes...`))

const output: OutputOptions[] = []
if (Array.isArray(outputs)) {
for (const _output of outputs) {
stafyniaksacha marked this conversation as resolved.
Show resolved Hide resolved
output.push(buildOuputOptions(_output))
}
} else {
output.push(buildOuputOptions(outputs))
}

const watcherOptions = config.build.watch
const watcher = rollup.watch({
...rollupOptions,
output,
watch: {
...watcherOptions,
chokidar: {
ignored: [
'**/node_modules/**',
'**/.git/**',
...(watcherOptions?.chokidar?.ignored || [])
],
ignoreInitial: true,
ignorePermissionErrors: true,
...watcherOptions.chokidar
}
}
})

watcher.on('event', (event) => {
if (event.code === 'BUNDLE_START') {
// clean previous files
if (options.write) {
emptyDir(outDir)
if (fs.existsSync(config.publicDir)) {
copyDir(config.publicDir, outDir)
}
}
} else if (event.code === 'BUNDLE_END') {
event.result.close()
config.logger.info(chalk.cyanBright(`built in ${event.duration}ms.`))
} else if (event.code === 'ERROR') {
outputBuildError(event.error)
}
})

// stop watching
watcher.close()
Copy link
Member

Choose a reason for hiding this comment

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

Why is close called immediately?

Copy link
Member

Choose a reason for hiding this comment

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


return watcher
}

// write or generate files with rollup
const bundle = await rollup.rollup(rollupOptions)
paralellBuilds.push(bundle)

const generate = (output: OutputOptions = {}) => {
return bundle[options.write ? 'write' : 'generate'](
buildOuputOptions(output)
)
}

if (options.write) {
Expand Down Expand Up @@ -434,12 +525,6 @@ async function doBuild(
}
}

// resolve lib mode outputs
const outputs = resolveBuildOutputs(
options.rollupOptions?.output,
libOptions,
config.logger
)
if (Array.isArray(outputs)) {
const res = []
for (const output of outputs) {
Expand All @@ -450,16 +535,7 @@ async function doBuild(
return await generate(outputs)
}
} catch (e) {
config.logger.error(
chalk.red(`${e.plugin ? `[${e.plugin}] ` : ``}${e.message}`)
)
if (e.id) {
const loc = e.loc ? `:${e.loc.line}:${e.loc.column}` : ``
config.logger.error(`file: ${chalk.cyan(`${e.id}${loc}`)}`)
}
if (e.frame) {
config.logger.error(chalk.yellow(e.frame))
}
outputBuildError(e)
throw e
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ cli
`[boolean] force empty outDir when it's outside of root`
)
.option('-m, --mode <mode>', `[string] set env mode`)
.option('--watch', `[boolean] rebuilds when modules have changed on disk`)
Shinigami92 marked this conversation as resolved.
Show resolved Hide resolved
.action(async (root: string, options: BuildOptions & GlobalCLIOptions) => {
const { build } = await import('./build')
const buildOptions = cleanOptions(options) as BuildOptions
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/server/middlewares/static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function serveRawFsMiddleware(): Connect.NextHandleFunction {
if (url.startsWith(FS_PREFIX)) {
url = url.slice(FS_PREFIX.length)
if (isWin) url = url.replace(/^[A-Z]:/i, '')

req.url = url
serveFromRoot(req, res, next)
} else {
Expand Down