-
Notifications
You must be signed in to change notification settings - Fork 856
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
Conversation
🦋 Changeset detectedLatest commit: 645d19e The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
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 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) { |
There was a problem hiding this comment.
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
8b255a0
to
16226f6
Compare
There was a problem hiding this 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
?
There was a problem hiding this 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
package-lock.json
Outdated
@@ -503,6 +503,10 @@ | |||
"fixtures/workers-chat-demo": { | |||
"version": "1.0.0" | |||
}, | |||
"fixtures/wrangler-dev-api-app": { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
Oh, please add a changeset! |
There was a problem hiding this 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"); |
There was a problem hiding this comment.
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"));
package-lock.json
Outdated
@@ -503,6 +503,10 @@ | |||
"fixtures/workers-chat-demo": { | |||
"version": "1.0.0" | |||
}, | |||
"fixtures/wrangler-dev-api-app": { |
There was a problem hiding this comment.
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?
packages/wrangler/src/api/dev.ts
Outdated
logger.warn( | ||
`unstable_dev() is experimental\nunstable_dev()'s behaviour will likely change in future releases` | ||
); | ||
logger.loggerLevel = "error"; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
packages/wrangler/src/dev.tsx
Outdated
await waitUntilExit(); | ||
const devReactElement = render(await getDevReactElement(config)); | ||
rerender = devReactElement.rerender; | ||
return { devReactElement, watcher }; |
There was a problem hiding this comment.
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();
}
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. |
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 |
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. |
…o invoke wrangler dev Update packages/wrangler/src/dev/remote.tsx Co-authored-by: Pete Bacon Darwin <[email protected]> address PR feedback
There was a problem hiding this 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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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/"); |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)); |
There was a problem hiding this comment.
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 😢
Added a warning:

Things for follow-up releases:
unstable_dev
should return an object so you can just do:@wrangler/core
and@wrangler/renderer
(or something) so prop-drilling to reach the core isn't necessaryFollow-up issues for tracking: