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: support bundling the raw Pages _worker.js before deploying #2404

Merged
merged 5 commits into from
Jan 12, 2023

Conversation

petebacondarwin
Copy link
Contributor

@petebacondarwin petebacondarwin commented Dec 13, 2022

What this PR solves / how to test:

Adds support to wrangler pages to pass the raw _worker.js file through the normal Wrangler bundler,
which improves support for D1 bindings with web frameworks that generate this file, such as SvelteKit.

You can test whether this is working by creating a Pages project with a _worker.js that imports from another
JS file. E.g.

_worker.js

import value from "./dep";

export default {
  async fetch() {
    return new Response(value);
  },
};

dep.js

export default "TEST";

Associated docs issues/PR:

  • TBD

Author has included the following, where applicable:

  • Tests
  • Changeset

Reviewer has performed the following, where applicable:

  • Checked for inclusion of relevant tests
  • Checked for inclusion of a relevant changeset
  • Checked for creation of associated docs updates
  • Manually pulled down the changes and spot-tested

FIxes #2153

@petebacondarwin petebacondarwin requested review from a team as code owners December 13, 2022 17:31
@changeset-bot
Copy link

changeset-bot bot commented Dec 13, 2022

🦋 Changeset detected

Latest commit: ff4f52c

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

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

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 Dec 13, 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.devprod.cloudflare.dev/runs/3901445415/npm-package-wrangler-2404

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

npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/prs/2404/npm-package-wrangler-2404

Or you can use npx with this latest build directly:

npx https://prerelease-registry.devprod.cloudflare.dev/runs/3901445415/npm-package-wrangler-2404 dev path/to/script.js
Additional artifacts:
npm install https://prerelease-registry.devprod.cloudflare.dev/runs/3901445415/npm-package-cloudflare-pages-shared-2404

@penalosa
Copy link
Contributor

This could definitely do with some docs changes, maybe as an addendum to https://developers.cloudflare.com/workers/wrangler/bundling/? Are the wrangler pages ... commands documented anywhere?

@codecov
Copy link

codecov bot commented Dec 13, 2022

Codecov Report

Merging #2404 (ff4f52c) into main (fe8c691) will increase coverage by 0.02%.
The diff coverage is 43.28%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2404      +/-   ##
==========================================
+ Coverage   72.97%   72.99%   +0.02%     
==========================================
  Files         156      156              
  Lines        9709     9735      +26     
  Branches     2556     2565       +9     
==========================================
+ Hits         7085     7106      +21     
- Misses       2624     2629       +5     
Impacted Files Coverage Δ
packages/wrangler/src/pages/dev.ts 19.02% <5.55%> (ø)
...ckages/wrangler/src/pages/functions/buildWorker.ts 44.59% <52.94%> (+0.59%) ⬆️
packages/wrangler/src/pages/publish.tsx 65.36% <64.28%> (-0.71%) ⬇️
...ckages/wrangler/src/pages/functions/buildPlugin.ts 20.00% <100.00%> (+7.17%) ⬆️
packages/wrangler/src/git-client.ts 81.25% <0.00%> (+4.16%) ⬆️
...ackages/wrangler/src/__tests__/helpers/mock-bin.ts 100.00% <0.00%> (+5.26%) ⬆️

@petebacondarwin
Copy link
Contributor Author

By the way, I found that quite often the "integration" tests failed simply because they overran the default 5 seconds. It was completely non-deterministic and depended upon the workload on the machine and other random factors. I bumped up the timeouts on all the ones that tended to flake out to 10 secs.

@GregBrimble
Copy link
Contributor

Pete, you're my hero. I'll try review this today.

@@ -78,6 +79,11 @@ export function Options(yargs: Argv) {
description:
"The location of the single Worker script if not using functions",
},
"bundle-worker": {
Copy link
Contributor

Choose a reason for hiding this comment

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

We will make this default at some point pretty soon. So I'm tempted to make this an env var or deprecated/experimental or whatever so we can remove it easily when we force it. What do you think, @petebacondarwin ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, to keep in line with wrangler publish we should keep this and call it bundle. The usage in wrangler publish is that this defaults to true but can be turned off with no-bundle or bundle=false.

So I would rather not hide it away - I think there may be valid cases where people choose not to run the bundler on the generated _worker.js.

Comment on lines 14 to 15
command line argument to `wrangler pages dev` and `wrangler pages publish`. For
backward compatibility this flag defaults to `false` if not provided.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
command line argument to `wrangler pages dev` and `wrangler pages publish`. For
backward compatibility this flag defaults to `false` if not provided.
command line argument to `wrangler pages dev` and `wrangler pages publish`.

If you're happy, I'd like to drop that line from the release notes since I will be doing this by default soon enough.

let workerFileContents = _workerJS;
if (bundleWorker) {
const outfile = join(tmpdir(), `./bundledWorker-${Math.random()}.mjs`);
await buildRawWorker({
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we not need to listen for onEnd to complete here and in the checkWorker() call?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think onEnd() is only really helpful when watch: true, right?
Without watching the call to buildRawWorker() will only resolve after the build completes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For watch mode, the returned promise resolves after the first build but then we need a way to be notified after subsequent builds.

@petebacondarwin petebacondarwin force-pushed the bundle-pages-worker branch 4 times, most recently from 515659b to 4a7831c Compare December 18, 2022 16:29
martindisch added a commit to martindisch/weather-v3 that referenced this pull request Dec 23, 2022
@petebacondarwin petebacondarwin force-pushed the bundle-pages-worker branch 4 times, most recently from 43bfe20 to c14ec54 Compare January 10, 2023 21:13
Copy link
Contributor

@JacobMGEvans JacobMGEvans left a comment

Choose a reason for hiding this comment

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

I'm guessing based on the nature of these changes it had to be little beefy PR. I would appreciate some of your time for a pair review on this one.

@petebacondarwin
Copy link
Contributor Author

I'm guessing based on the nature of these changes it had to be little beefy PR. I would appreciate some of your time for a pair review on this one.

This is not as beefy as it looks. But that is my fault because I have wrapped a bunch of test changes into the PR that are not actually necessary for this PR. At the time of writing I had to make these changes to get the flaky fixture tests to pass, but I think with switching them to Vitest they probably are less flaky now.

So you can mostly ignore the changes to all the fixtures/**/*.test.ts files on a first read.

After that, there is the addition of the --bundle arg, which gets passed down the line to the bundling code.
And finally there is some clean up of where the pages functions actually need to bundle stuff, which deduplicates some esbuild plugins into shared functions.

@petebacondarwin petebacondarwin force-pushed the bundle-pages-worker branch 2 times, most recently from fa796e3 to c5a915c Compare January 11, 2023 07:47
@petebacondarwin
Copy link
Contributor Author

I have split the PR into two commits to make it easier to see the main change from the test refactor.

@Skye-31
Copy link
Contributor

Skye-31 commented Jan 11, 2023

@petebacondarwin
Could we consider warning/providing an error for the user when bundle: false && d1Databases.length in pages dev?

@petebacondarwin
Copy link
Contributor Author

@petebacondarwin Could we consider warning/providing an error for the user when bundle: false && d1Databases.length in pages dev?

I would be happy with that. But in a follow up PR.

@CarmenPopoviciu
Copy link
Contributor

LGTM! Only those 3 wording nits and this is good to go AFAIAC 🎉

@JacobMGEvans
Copy link
Contributor

I'm guessing based on the nature of these changes it had to be little beefy PR. I would appreciate some of your time for a pair review on this one.

This is not as beefy as it looks. But that is my fault because I have wrapped a bunch of test changes into the PR that are not actually necessary for this PR. At the time of writing I had to make these changes to get the flaky fixture tests to pass, but I think with switching them to Vitest they probably are less flaky now.

So you can mostly ignore the changes to all the fixtures/**/*.test.ts files on a first read.

After that, there is the addition of the --bundle arg, which gets passed down the line to the bundling code. And finally there is some clean up of where the pages functions actually need to bundle stuff, which deduplicates some esbuild plugins into shared functions.

Thanks for the explanation. Considering the fixtures, there is a lot less to the PR.

Copy link
Contributor

@JacobMGEvans JacobMGEvans left a comment

Choose a reason for hiding this comment

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

PR is already approved. Nothing I mentioned is blocking.

Comment on lines +263 to +264
let runBuild = async () => {
await checkRawWorker(workerScriptPath, () => scriptReadyResolve());
Copy link
Contributor

Choose a reason for hiding this comment

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

Codecov is mentioning these lines are uncovered by tests? Is this covered in the fixtures rather than the wrangler package tests (Codecov doesnt collect fixtures tests I think)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah this is covered by fixtures tests.

@@ -278,47 +295,39 @@ export const Handler = async ({
});
} else if (usingFunctions) {
// Try to use Functions
const outfile = join(tmpdir(), `./functionsWorker-${Math.random()}.mjs`);
scriptPath = outfile;
scriptPath = join(tmpdir(), `./functionsWorker-${Math.random()}.mjs`);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not part of your PR, but wouldnt it make more sense to have this idempotent by hashing someting dynamic and unique to the functionsWorker?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't really matter what the name is as long as it is unlikely to collide with another concurrent build. This was the simplest solution.

We now use helper functions to setup and teardown a long-lived wrangler process.
This means that we can remove the `--forceExit` option from the jest setup.
Previously, if you provided a `_worker.js` file, then Pages would simply check the
file for disallowed imports and then deploy the file as-is.

Not bundling the `_worker.js` file means that it cannot containing imports to other
JS files, but also prevents Wrangler from adding shims such as the one for the D1 alpha
release.

This change adds the ability to tell Wrangler to pass the `_worker.js` through the
normal Wrangler bundling process before deploying by setting the `--bundle`
command line argument to `wrangler pages dev` and `wrangler pages publish`.

This is in keeping with the same flag for `wrangler publish`.

Currently bundling is opt-in, flag defaults to `false` if not provided.
@petebacondarwin petebacondarwin merged commit 3f82434 into cloudflare:main Jan 12, 2023
@github-actions github-actions bot mentioned this pull request Jan 12, 2023
@lrapoport-cf
Copy link
Contributor

This could definitely do with some docs changes, maybe as an addendum to https://developers.cloudflare.com/workers/wrangler/bundling/? Are the wrangler pages ... commands documented anywhere?

@petebacondarwin is there a docs PR that should be linked to this?

@petebacondarwin
Copy link
Contributor Author

This could definitely do with some docs changes, maybe as an addendum to https://developers.cloudflare.com/workers/wrangler/bundling/? Are the wrangler pages ... commands documented anywhere?

@petebacondarwin is there a docs PR that should be linked to this?

Ah sorry. I missed this comment.
The pages commands are documented here: https://developers.cloudflare.com/workers/wrangler/commands/#pages
I will create a PR to update them.

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.

🚀 Feature Request: Support imports in _worker.js
7 participants