Skip to content
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
12 changes: 12 additions & 0 deletions .changeset/quick-wombats-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"wrangler": minor
---

feat: Make DX improvements in `wrangler dev --remote`

Workers + Assets projects have, in certain situations, a relatively degraded `wrangler dev --remote` developer experience, as opposed to Workers proper projects. This is due to the fact that, for Workers + Assets, we need to make extra API calls to:

1. check for asset files changes
2. upload the changed assets, if any

This commit improves the `wrangler dev --remote` DX for Workers + Assets, for use cases when the User Worker/assets change while the API calls for previous changes are still in flight. For such use cases, we have put an exit early strategy in place, that drops the event handler execution of the previous changes, in favour of the handler triggered by the new changes.
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,29 @@ export class RemoteRuntimeController extends RuntimeController {
async #previewToken(
props: Omit<CreateRemoteWorkerInitProps, "name"> &
Partial<Pick<CreateRemoteWorkerInitProps, "name">> &
Parameters<typeof getWorkerAccountAndContext>[0]
Parameters<typeof getWorkerAccountAndContext>[0] & { bundleId: number }
): Promise<CfPreviewToken | undefined> {
if (!this.#session) {
return;
}

try {
/*
* Since `getWorkerAccountAndContext`, `createRemoteWorkerInit` and
* `createWorkerPreview` are all async functions, it is technically
* possible that new `bundleComplete` events are trigerred while those
* functions are still executing. In such cases we want to drop the
* current bundle and exit early, to avoid unnecessarily executing any
* further expensive API calls.
*
* For this purpose, we want perform a check before each of these
* functions, to ensure no new `bundleComplete` was triggered.
*/
// If we received a new `bundleComplete` event before we were able to
// dispatch a `reloadComplete` for this bundle, ignore this bundle.
if (props.bundleId !== this.#currentBundleId) {
return;
}
const { workerAccount, workerContext } = await getWorkerAccountAndContext(
{
accountId: props.accountId,
Expand All @@ -89,6 +105,11 @@ export class RemoteRuntimeController extends RuntimeController {
? this.#session.id
: this.#session.host.split(".")[0]);

// If we received a new `bundleComplete` event before we were able to
// dispatch a `reloadComplete` for this bundle, ignore this bundle.
if (props.bundleId !== this.#currentBundleId) {
return;
}
const init = await createRemoteWorkerInit({
bundle: props.bundle,
modules: props.modules,
Expand All @@ -105,6 +126,11 @@ export class RemoteRuntimeController extends RuntimeController {
compatibilityFlags: props.compatibilityFlags,
});

// If we received a new `bundleComplete` event before we were able to
// dispatch a `reloadComplete` for this bundle, ignore this bundle.
if (props.bundleId !== this.#currentBundleId) {
return;
}
const workerPreviewToken = await createWorkerPreview(
init,
workerAccount,
Expand Down Expand Up @@ -175,6 +201,13 @@ export class RemoteRuntimeController extends RuntimeController {
const { bindings } = await convertBindingsToCfWorkerInitBindings(
config.bindings
);

// If we received a new `bundleComplete` event before we were able to
// dispatch a `reloadComplete` for this bundle, ignore this bundle.
if (id !== this.#currentBundleId) {
return;
}

const token = await this.#previewToken({
bundle,
modules: bundle.modules,
Expand All @@ -201,6 +234,7 @@ export class RemoteRuntimeController extends RuntimeController {
host: config.dev.origin?.hostname,
sendMetrics: config.sendMetrics,
configPath: config.config,
bundleId: id,
});

// If we received a new `bundleComplete` event before we were able to
Expand Down
Loading