From d38f5bb1d826e043038ca9b8629625c295e44a6b Mon Sep 17 00:00:00 2001 From: Andy Jessop Date: Mon, 2 Dec 2024 11:27:36 +0100 Subject: [PATCH 1/5] Better messaging on nodejs_compat within Vitest Pool Workers --- .../testing/vitest-integration/isolation-and-concurrency.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx index 57def403d33da0..5cddb9cbd5cd43 100644 --- a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx +++ b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx @@ -56,12 +56,12 @@ In this model, a single `workerd` process is started with a single Worker for al Each Worker has its own module cache. As Workers are reused between test runs, their module caches are also reused. Vitest invalidates parts of the module cache at the start of each test run based on changed files. -The Workers Vitest pool works by running code inside a Cloudflare Worker that Vitest would usually run inside a [Node.js worker thread](https://nodejs.org/api/worker_threads.html). To make this possible, the pool requires the [`nodejs_compat`](/workers/configuration/compatibility-flags/#nodejs-compatibility-flag) and [`export_commonjs_default`](/workers/configuration/compatibility-flags/#commonjs-modules-do-not-export-a-module-namespace) compatibility flags to be enabled. The pool also configures `workerd` to use Node-style module resolution and polyfills required `node:*` modules not provided by `nodejs_compat`. +The Workers Vitest pool works by running code inside a Cloudflare Worker that Vitest would usually run inside a [Node.js worker thread](https://nodejs.org/api/worker_threads.html). To make this possible, the pool **automatically injects** the [`nodejs_compat`](/workers/configuration/compatibility-flags/#nodejs-compatibility-flag) and [`export_commonjs_default`](/workers/configuration/compatibility-flags/#commonjs-modules-do-not-export-a-module-namespace) compatibility flags to be enabled. The pool also configures `workerd` to use Node-style module resolution and polyfills required `node:*` modules not provided by `nodejs_compat`. :::caution -Using the pool may cause your Worker to behave differently when deployed than during testing, as Node-style resolution and additional polyfills will be available to your Worker's source code and dependencies too. +Using Vitest Pool Workers may cause your Worker to behave differently when deployed than during testing as the `nodejs_compat` flag is enabled by default. This means that Node.js-specific APIs and modules are available when running your tests. However, Cloudflare Workers do not support these Node.js APIs in the production environment unless you specify this flag in your Worker configuration. ::: From b39990df04824bd581d82ba0a104fe91e1702203 Mon Sep 17 00:00:00 2001 From: Andy Jessop Date: Mon, 2 Dec 2024 11:34:12 +0100 Subject: [PATCH 2/5] chore: Worker capitalisation --- .../testing/vitest-integration/isolation-and-concurrency.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx index 5cddb9cbd5cd43..e6247e48fbd809 100644 --- a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx +++ b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx @@ -56,7 +56,7 @@ In this model, a single `workerd` process is started with a single Worker for al Each Worker has its own module cache. As Workers are reused between test runs, their module caches are also reused. Vitest invalidates parts of the module cache at the start of each test run based on changed files. -The Workers Vitest pool works by running code inside a Cloudflare Worker that Vitest would usually run inside a [Node.js worker thread](https://nodejs.org/api/worker_threads.html). To make this possible, the pool **automatically injects** the [`nodejs_compat`](/workers/configuration/compatibility-flags/#nodejs-compatibility-flag) and [`export_commonjs_default`](/workers/configuration/compatibility-flags/#commonjs-modules-do-not-export-a-module-namespace) compatibility flags to be enabled. The pool also configures `workerd` to use Node-style module resolution and polyfills required `node:*` modules not provided by `nodejs_compat`. +The Workers Vitest pool works by running code inside a Cloudflare Worker that Vitest would usually run inside a [Node.js Worker thread](https://nodejs.org/api/worker_threads.html). To make this possible, the pool **automatically injects** the [`nodejs_compat`](/workers/configuration/compatibility-flags/#nodejs-compatibility-flag) and [`export_commonjs_default`](/workers/configuration/compatibility-flags/#commonjs-modules-do-not-export-a-module-namespace) compatibility flags to be enabled. The pool also configures `workerd` to use Node-style module resolution and polyfills required `node:*` modules not provided by `nodejs_compat`. :::caution From b681bb95f8edd15939f88f44fd934182643392e6 Mon Sep 17 00:00:00 2001 From: Andy Jessop Date: Tue, 17 Dec 2024 10:27:22 +0100 Subject: [PATCH 3/5] chore: update wording to reflect no_nodejs_compat_v2 flag --- .../testing/vitest-integration/isolation-and-concurrency.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx index e6247e48fbd809..417a769d9e7ced 100644 --- a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx +++ b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx @@ -56,7 +56,7 @@ In this model, a single `workerd` process is started with a single Worker for al Each Worker has its own module cache. As Workers are reused between test runs, their module caches are also reused. Vitest invalidates parts of the module cache at the start of each test run based on changed files. -The Workers Vitest pool works by running code inside a Cloudflare Worker that Vitest would usually run inside a [Node.js Worker thread](https://nodejs.org/api/worker_threads.html). To make this possible, the pool **automatically injects** the [`nodejs_compat`](/workers/configuration/compatibility-flags/#nodejs-compatibility-flag) and [`export_commonjs_default`](/workers/configuration/compatibility-flags/#commonjs-modules-do-not-export-a-module-namespace) compatibility flags to be enabled. The pool also configures `workerd` to use Node-style module resolution and polyfills required `node:*` modules not provided by `nodejs_compat`. +The Workers Vitest pool works by running code inside a Cloudflare Worker that Vitest would usually run inside a [Node.js Worker thread](https://nodejs.org/api/worker_threads.html). To make this possible, the pool **automatically injects** the [`nodejs_compat`](/workers/configuration/compatibility-flags/#nodejs-compatibility-flag), [`no_nodejs_compat_v2`] and [`export_commonjs_default`](/workers/configuration/compatibility-flags/#commonjs-modules-do-not-export-a-module-namespace) compatibility flags. This is the minimal compatibility setup that still allows Vitest to run correctly, but without pulling in polyfills and globals that aren't required. If you already have a Node.js compatibility flag defined in your configuration, Vitest Pool Workers will not try to add those flags. :::caution From f41763d89ac863a302d82eb6e30c055b16883f09 Mon Sep 17 00:00:00 2001 From: Andy Jessop Date: Thu, 19 Dec 2024 09:05:57 +0100 Subject: [PATCH 4/5] update docs with example --- .../isolation-and-concurrency.mdx | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx index 417a769d9e7ced..f0caacb207869c 100644 --- a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx +++ b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx @@ -63,5 +63,49 @@ The Workers Vitest pool works by running code inside a Cloudflare Worker that Vi Using Vitest Pool Workers may cause your Worker to behave differently when deployed than during testing as the `nodejs_compat` flag is enabled by default. This means that Node.js-specific APIs and modules are available when running your tests. However, Cloudflare Workers do not support these Node.js APIs in the production environment unless you specify this flag in your Worker configuration. +If you do not have a `nodejs_compat` or `nodejs_compat_v2` flag in your configuration and you import a Node.js module in your Worker code, your tests may pass, but you will find that you will not be able to deploy this Worker as the upload call (either via the REST API or via Wrangler) will throw an error. + +However, if you use Node.js globals that are not supported by the runtime, your Worker upload will be successful, but you may see errors in production code. Let's create a contrived example to illustrate the issue. + +The `wrangler.toml` does not specify either `nodejs_compat` or `nodejs_compat_v2`: + +```toml +name = "test" +main = "src/index.ts" +compatibility_date = "2024-12-16" +# no nodejs_compat flags here +``` + +In our `src/index.ts` file, we use the `process` object, which is a Node.js global, unavailable in the Workerd runtime: + +```typescript +export default { + async fetch(request, env, ctx): Promise { + process.env.TEST = 'test'; + return new Response(process.env.TEST); + }, +} satisfies ExportedHandler; +``` + +The test simple assertion that the Worker managed to use `process`. + +```typescript +it('responds with "test"', async () => { + const response = await SELF.fetch('https://example.com/'); + expect(await response.text()).toMatchInlineSnapshot(`"test"`); +}); +``` + +Now, if we run `npm run test`, we see that the tests will _pass_: + +``` + ✓ test/index.spec.ts (1) + ✓ responds with "test" + + Test Files 1 passed (1) + Tests 1 passed (1) +``` + +And we can run `wrangler dev` and `wrangler deploy` without issues. It _looks like_ our code is fine. However, this code will fail in production as `process` is not available in the Workerd runtime. ::: From cd39881dc8725858be9a521e5b62734d6444ba32 Mon Sep 17 00:00:00 2001 From: Andy Jessop Date: Thu, 19 Dec 2024 09:10:09 +0100 Subject: [PATCH 5/5] punctuation --- .../vitest-integration/isolation-and-concurrency.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx index f0caacb207869c..19602851cd7fc6 100644 --- a/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx +++ b/src/content/docs/workers/testing/vitest-integration/isolation-and-concurrency.mdx @@ -63,7 +63,7 @@ The Workers Vitest pool works by running code inside a Cloudflare Worker that Vi Using Vitest Pool Workers may cause your Worker to behave differently when deployed than during testing as the `nodejs_compat` flag is enabled by default. This means that Node.js-specific APIs and modules are available when running your tests. However, Cloudflare Workers do not support these Node.js APIs in the production environment unless you specify this flag in your Worker configuration. -If you do not have a `nodejs_compat` or `nodejs_compat_v2` flag in your configuration and you import a Node.js module in your Worker code, your tests may pass, but you will find that you will not be able to deploy this Worker as the upload call (either via the REST API or via Wrangler) will throw an error. +If you do not have a `nodejs_compat` or `nodejs_compat_v2` flag in your configuration and you import a Node.js module in your Worker code, your tests may pass, but you will find that you will not be able to deploy this Worker, as the upload call (either via the REST API or via Wrangler) will throw an error. However, if you use Node.js globals that are not supported by the runtime, your Worker upload will be successful, but you may see errors in production code. Let's create a contrived example to illustrate the issue. @@ -87,7 +87,7 @@ export default { } satisfies ExportedHandler; ``` -The test simple assertion that the Worker managed to use `process`. +The test is a simple assertion that the Worker managed to use `process`. ```typescript it('responds with "test"', async () => { @@ -108,4 +108,6 @@ Now, if we run `npm run test`, we see that the tests will _pass_: And we can run `wrangler dev` and `wrangler deploy` without issues. It _looks like_ our code is fine. However, this code will fail in production as `process` is not available in the Workerd runtime. +To fix the issue, we either need to avoid using Node.js APIs, or add the `nodejs_compat` flag to our Wrangler configuration. + :::