Skip to content

feat: export a dev function that folks can use in their own scripts to invoke wrangler dev #1350

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

Merged
merged 6 commits into from
Jul 1, 2022

Conversation

rozenmd
Copy link
Contributor

@rozenmd rozenmd commented Jun 24, 2022

Added a warning:
image

Things for follow-up releases:

  • unstable_dev should return an object so you can just do:
    const worker = await wrangler.unstable_dev(...)
    const resp =  await worker.fetch()
  • we should make miniflare notify wrangler that it's ready for requests (the remote dev worker supports this already)
  • (for future us to deal with): split wrangler into @wrangler/core and @wrangler/renderer (or something) so prop-drilling to reach the core isn't necessary

Follow-up issues for tracking:

@rozenmd rozenmd self-assigned this Jun 24, 2022
@changeset-bot
Copy link

changeset-bot bot commented Jun 24, 2022

🦋 Changeset detected

Latest commit: 645d19e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
wrangler Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Jun 24, 2022

A wrangler prerelease is available for testing. You can install this latest build in your project with:

npm install --save-dev https://prerelease-registry.developers.workers.dev/runs/2596257088/npm-package-wrangler-1350

You can reference the automatically updated head of this PR with:

npm install --save-dev https://prerelease-registry.developers.workers.dev/prs/1350/npm-package-wrangler-1350

Or you can use npx with this latest build directly:

npx https://prerelease-registry.developers.workers.dev/runs/2596257088/npm-package-wrangler-1350 dev path/to/script.js

const exitCode = (e instanceof FatalError && e.code) || 1;
process.exit(exitCode);
});
if (require.main) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Until we have a architecture or abstraction for the API layer I think it would be good to have simple comments expressing what/why things like this are being implemented, i.e. the code looks like a CLI but there is library API package logic sprinkled seemingly randomly

@rozenmd rozenmd force-pushed the dev-as-an-api branch 4 times, most recently from 8b255a0 to 16226f6 Compare June 29, 2022 09:41
@rozenmd rozenmd marked this pull request as ready for review June 29, 2022 09:43
Copy link
Contributor

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

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

We should not have a package-lock.json in any of the subfolders of the monorepo,
Can you delete the one in wrangler-dev-api-app?

Copy link
Contributor

@threepointone threepointone left a comment

Choose a reason for hiding this comment

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

This is looking pretty great. Dropped some notes, would like to bikeshed the isApi param for a bit

@@ -503,6 +503,10 @@
"fixtures/workers-chat-demo": {
"version": "1.0.0"
},
"fixtures/wrangler-dev-api-app": {
Copy link
Contributor

Choose a reason for hiding this comment

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

the changes in this file are concerning, seems like a lot and I'm not sure why

Copy link
Contributor

Choose a reason for hiding this comment

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

@rozenmd - I see you managed to reduce the churn. What did you do to make that happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good call out @threepointone - seems like the fixture's own package-lock made this one funky. Pulled in the one from master and re-ran npm i to fix it up.

@threepointone
Copy link
Contributor

Oh, please add a changeset!

Copy link
Contributor

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

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

I added lots of suggestions. Nothing blocking this, since you are actively iterating on this.
But do take a look and see what you think.

import wrangler from "wrangler";

//since the script is invoked from the directory above, need to specify index.js is in src/
await wrangler.unstable_dev("src/index.js");
Copy link
Contributor

Choose a reason for hiding this comment

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

If you wanted to be super resilient here you could do something much more complicated:

import * as path from 'path';
import * as url from 'url';
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));

await wrangler.unstable_dev(path.resolve(__dirname, "./index.js"));

@@ -503,6 +503,10 @@
"fixtures/workers-chat-demo": {
"version": "1.0.0"
},
"fixtures/wrangler-dev-api-app": {
Copy link
Contributor

Choose a reason for hiding this comment

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

@rozenmd - I see you managed to reduce the churn. What did you do to make that happen?

logger.warn(
`unstable_dev() is experimental\nunstable_dev()'s behaviour will likely change in future releases`
);
logger.loggerLevel = "error";
Copy link
Contributor

Choose a reason for hiding this comment

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

Out of curiosity, why are you overriding the loggerLevel here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The logger gives irrelevant information otherwise (for API users): ⎔ Starting a local server...

Copy link
Contributor

Choose a reason for hiding this comment

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

As a follow up: For API users they should be able to provide their own Logger instance, which they can then implement as they see fit.

@@ -7,6 +7,7 @@
"wrangler": "./bin/wrangler.js",
"wrangler2": "./bin/wrangler.js"
},
"main": "wrangler-dist/cli.js",
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than conflating the two, I wonder if we should actually have two generated entry-points for wrangler?

wrangler-dist/index.js
wrangler-dist/cli.js

The first would only contain the unstable_dev() function (for now).
The second would only contain the binary that is run when Wrangler is used as a CLI.

Then "main" would just point at the index.js.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, we could even bundle the API entry-point as index.mjs and then have a "module" property here for futureproofing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can this be an immediate follow-up task @petebacondarwin ?

Copy link
Contributor

Choose a reason for hiding this comment

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

👍 all my comments can be follow-ups

Copy link
Contributor

Choose a reason for hiding this comment

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

Does sound like additional scope to me.

local.current = spawn("node", localServerOptions, {
cwd: path.dirname(scriptPath),
});
//TODO: instead of being lucky with spawn's timing, have miniflare-cli notify wrangler that it's ready in packages/wrangler/src/miniflare-cli/index.ts, after the mf.startScheduler promise resolves
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

await waitUntilExit();
const devReactElement = render(await getDevReactElement(config));
rerender = devReactElement.rerender;
return { devReactElement, watcher };
Copy link
Contributor

@petebacondarwin petebacondarwin Jun 29, 2022

Choose a reason for hiding this comment

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

How about we return our own waitForExit function here that does the watcher.close() for us?
E.g.

async function waitForExit() {
  try {
    await devReactElement.waitUntilExit();
  } finally {
    watcher?.close();
  }
}
return { waitForExit };

Then in the caller we don't need to know about the watcher:

export async function devHandler(args: ArgumentsCamelCase<DevArgs>) {
  const { waitForExit } = await startDev(args);
  await waitUntilExit();
}

@petebacondarwin
Copy link
Contributor

Last comment! I am not convinced this should have a changeset until it is in a place where we want people to start playing with it. That should be very soon, but not as a result of this PR landing, IMO.

@rozenmd
Copy link
Contributor Author

rozenmd commented Jun 29, 2022

I think we do want people playing with it @petebacondarwin, hence the changeset. Any scripts they write will break (slightly) in future releases (especially after we move to worker.fetch instead of undici.fetch), but that's what the unstable_ prefix and scary warning are for.

@JacobMGEvans
Copy link
Contributor

I think we do want people playing with it @petebacondarwin, hence the changeset. Any scripts they write will break (slightly) in future releases (especially after we move to worker.fetch instead of undici.fetch), but that's what the unstable_ prefix and scary warning are for.

Any changes to the API would require us to update the tests which we can take snippets from then added to future changesets and referenced easily for updating their code.

@rozenmd rozenmd changed the base branch from main to deprecate-preview June 30, 2022 13:14
Base automatically changed from deprecate-preview to main June 30, 2022 14:37
Copy link
Contributor

@threepointone threepointone left a comment

Choose a reason for hiding this comment

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

approving, but a few notes for before you land it. let's goooo

);

return new Promise<{ stop: () => void }>((resolve) => {
//lmao
Copy link
Contributor

Choose a reason for hiding this comment

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

lmao is now part of the spec

congrats on getting this to work, let's land it and see if we can simplify it in another pr

);

return new Promise<{ stop: () => void }>((resolve) => {
//lmao
Copy link
Contributor

Choose a reason for hiding this comment

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

lmao is now part of the spec

congrats on getting this to work, let's land it and see if we can simplify it in another pr


console.log("Invoked worker: ", text);

await worker.stop();
Copy link
Contributor

Choose a reason for hiding this comment

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

🎉

//since the script is invoked from the directory above, need to specify index.js is in src/
const worker = await wrangler.unstable_dev("src/index.js");

const resp = await undici.fetch("http://localhost:8787/");
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be nice to hide the undici library, and also the underlying port, side of this and provide:

worker.fetch()

This method could take a path (or even a full URL if you wanted to simulate a custom route). This would also mitigate the case where port 8787 was not available and we ended up jumping on a different port, which I think we can do?

"version": "1.0.0",
"description": "",
"scripts": {
"dev": "node --no-warnings ./src/wrangler-dev.mjs"
Copy link
Contributor

Choose a reason for hiding this comment

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

Now we have worker.stop() we could easily add a unit test here that is very similar to wrangler-dev.mjs.

Copy link
Contributor

Choose a reason for hiding this comment

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

Something along the lines of:

import undici from "undici";
import wrangler from "wrangler";

describe("worker", () => {
	it("should invoke the worker and exit", async () => {
		//since the script is invoked from the directory above, need to specify index.js is in src/
		const worker = await wrangler.unstable_dev("src/index.js");

		const resp = await undici.fetch("http://localhost:8787/");
		const text = await resp.text();

		expect(text).toMatchInlineSnapshot(
			`"http://localhost:8787/ Fri Jul 01 2022 11:41:21 GMT+0100 (British Summer Time)"`
		);

		await worker.stop();
	});
});

@@ -254,7 +254,11 @@ function useLocalWorker({
cwd: path.dirname(scriptPath),
});
//TODO: instead of being lucky with spawn's timing, have miniflare-cli notify wrangler that it's ready in packages/wrangler/src/miniflare-cli/index.ts, after the mf.startScheduler promise resolves
onReady && onReady();
if (onReady) {
await new Promise((resolve) => setTimeout(resolve, 200));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this isn't necessary when running a script within the mono-repo, but when you run the preview build via npx, it's needed 😢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants