Skip to content

Commit

Permalink
feat(vite): enable watch mode for preview (#14412)
Browse files Browse the repository at this point in the history
  • Loading branch information
vicb authored Jan 18, 2023
1 parent 5adfc09 commit bd2b5ca
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 44 deletions.
5 changes: 5 additions & 0 deletions docs/generated/packages/vite/executors/build.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@
"force": {
"description": "Force the optimizer to ignore the cache and re-bundle",
"type": "boolean"
},
"watch": {
"description": "Enable re-building when files change.",
"type": "object",
"default": null
}
},
"definitions": {},
Expand Down
51 changes: 48 additions & 3 deletions packages/vite/src/executors/build/build.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { copyAssets } from '@nrwl/js';
import { existsSync } from 'fs';
import { resolve } from 'path';

export default async function viteBuildExecutor(
export default async function* viteBuildExecutor(
options: ViteBuildExecutorOptions,
context: ExecutorContext
) {
Expand All @@ -24,7 +24,7 @@ export default async function viteBuildExecutor(
}
);

await runInstance(buildConfig);
const watcherOrOutput = await runInstance(buildConfig);

const libraryPackageJson = resolve(projectRoot, 'package.json');
const rootPackageJson = resolve(context.root, 'package.json');
Expand All @@ -49,11 +49,56 @@ export default async function viteBuildExecutor(
);
}

return { success: true };
if ('on' in watcherOrOutput) {
// watcherOrOutput is a RollupWatcher.
// event is a RollupWatcherEvent.
const emitter = makeEmitter();
let success = true;
watcherOrOutput.on('event', (event: any) => {
if (event.code === 'START') {
success = true;
} else if (event.code === 'ERROR') {
success = false;
} else if (event.code === 'END') {
emitter.push({ success });
}
// result must be closed when present.
// see https://rollupjs.org/guide/en/#rollupwatch
event.result?.close();
});
yield* emitter;
} else {
yield { success: true };
}
}

function runInstance(options: InlineConfig) {
return build({
...options,
});
}

/**
* Helper to create an async iterator.
* Calling push on the returned object emits the value.
*/
function makeEmitter() {
const events = [];
let resolve: (value: unknown) => void | null;

return {
push: (event) => {
events.push(event);
resolve?.(event);
resolve = null;
},
[Symbol.asyncIterator]: () => ({
next: async () => {
if (events.length == 0) {
await new Promise((r) => (resolve = r));
}
return { value: events.shift(), done: false };
},
}),
};
}
1 change: 1 addition & 0 deletions packages/vite/src/executors/build/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export interface ViteBuildExecutorOptions {
logLevel?: 'info' | 'warn' | 'error' | 'silent';
mode?: string;
ssr?: boolean | string;
watch?: object | null;
}
5 changes: 5 additions & 0 deletions packages/vite/src/executors/build/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@
"force": {
"description": "Force the optimizer to ignore the cache and re-bundle",
"type": "boolean"
},
"watch": {
"description": "Enable re-building when files change.",
"type": "object",
"default": null
}
},
"definitions": {},
Expand Down
100 changes: 59 additions & 41 deletions packages/vite/src/executors/preview-server/preview-server.impl.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ExecutorContext, parseTargetString, runExecutor } from '@nrwl/devkit';
import { InlineConfig, mergeConfig, preview } from 'vite';
import { InlineConfig, mergeConfig, preview, PreviewServer } from 'vite';
import {
getNxTargetOptions,
getViteSharedConfig,
Expand All @@ -22,20 +22,12 @@ export default async function* vitePreviewServerExecutor(
// Merge the options from the build and preview-serve targets.
// The latter takes precedence.
const mergedOptions = {
...{ watch: {} },
...buildTargetOptions,
...options,
};

// Launch the build target.
const target = parseTargetString(options.buildTarget, context.projectGraph);
const build = await runExecutor(target, mergedOptions, context);
for await (const result of build) {
if (!result.success) {
return result;
}
}

// Launch the server.
// Retrieve the server configuration.
const serverConfig: InlineConfig = mergeConfig(
getViteSharedConfig(mergedOptions, options.clearScreen, context),
{
Expand All @@ -48,41 +40,67 @@ export default async function* vitePreviewServerExecutor(
console.warn('WARNING: preview is not meant to be run in production!');
}

try {
const server = await preview(serverConfig);
server.printUrls();
let server: PreviewServer | undefined;

const processOnExit = async () => {
const { httpServer } = server;
// closeAllConnections was added in Node v18.2.0
httpServer.closeAllConnections && httpServer.closeAllConnections();
httpServer.close(() => {
process.off('SIGINT', processOnExit);
process.off('SIGTERM', processOnExit);
process.off('exit', processOnExit);
});
};
const processOnExit = async () => {
await closeServer(server);
process.off('SIGINT', processOnExit);
process.off('SIGTERM', processOnExit);
process.off('exit', processOnExit);
};

process.on('SIGINT', processOnExit);
process.on('SIGTERM', processOnExit);
process.on('exit', processOnExit);

process.on('SIGINT', processOnExit);
process.on('SIGTERM', processOnExit);
process.on('exit', processOnExit);
// Launch the build target.
const target = parseTargetString(options.buildTarget, context.projectGraph);
const build = await runExecutor(target, mergedOptions, context);

const resolvedUrls = [
...server.resolvedUrls.local,
...server.resolvedUrls.network,
];
for await (const result of build) {
if (result.success) {
try {
if (!server) {
server = await preview(serverConfig);
}
server.printUrls();

const resolvedUrls = [
...server.resolvedUrls.local,
...server.resolvedUrls.network,
];

yield {
success: true,
baseUrl: resolvedUrls[0] ?? '',
};
} catch (e) {
console.error(e);
yield {
success: false,
baseUrl: '',
};
yield {
success: true,
baseUrl: resolvedUrls[0] ?? '',
};
} catch (e) {
console.error(e);
yield {
success: false,
baseUrl: '',
};
}
} else {
yield {
success: false,
baseUrl: '',
};
}
}

await new Promise(() => {});
}

function closeServer(server?: PreviewServer): Promise<void> {
return new Promise((resolve) => {
if (!server) {
resolve();
} else {
const { httpServer } = server;
// closeAllConnections was added in Node v18.2.0
httpServer.closeAllConnections && httpServer.closeAllConnections();
httpServer.close(() => resolve());
}
});
}
1 change: 1 addition & 0 deletions packages/vite/src/utils/options-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export function getViteBuildOptions(
manifest: options.manifest,
ssrManifest: options.ssrManifest,
ssr: options.ssr,
watch: options.watch,
};
}

Expand Down

1 comment on commit bd2b5ca

@vercel
Copy link

@vercel vercel bot commented on bd2b5ca Jan 18, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-git-master-nrwl.vercel.app
nx-dev-nrwl.vercel.app
nx.dev
nx-five.vercel.app

Please sign in to comment.