Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
title: Workers will use the new module registry by default on November 1
description: JavaScript Workers with compatibility dates on or after November 1, 2026 will use URL-based module resolution and import.meta by default.
products:
- workers
date: 2026-10-17
---

import { TypeScriptExample, WranglerConfig } from "~/components";

Starting November 1, 2026, JavaScript Workers with a [compatibility date](/workers/configuration/compatibility-dates/) of `2026-11-01` or later will use the new module registry by default. You will no longer need the `new_module_registry` flag for these dates. Python Workers keep using the legacy registry.

The module registry finds and loads JavaScript modules in your Worker. We [announced the new registry in September 2026](https://blog.cloudflare.com/workers-module-registry-nodejs/). It improves compatibility with JavaScript standards and Node.js. In Workers using [Node.js compatibility](/workers/runtime-apis/nodejs/), you can use `require()` to load ES modules. The module and its dependencies must not use top-level `await`.

You can also use `import.meta` to get information about the current module and find the URL of another module without loading it:

<TypeScriptExample filename="src/index.ts">

```ts
export default {
fetch(): Response {
return Response.json({
moduleUrl: import.meta.url,
isEntrypoint: import.meta.main,
helperUrl: import.meta.resolve("./helper.js"),
});
},
} satisfies ExportedHandler;
```

</TypeScriptExample>

When deployed with `src/index.ts` as the unbundled entrypoint, `isEntrypoint` is `true`. `helperUrl` is a URL within your Worker bundle. Resolving the URL does not check whether the module exists or load it over the network. Build tools may transform `import.meta`. To try this example directly, refer to [build settings for cf](/cf/wrangler/reference/#build-settings) or [unbundled deployments with Wrangler](/workers/wrangler/configuration/#bundling).

Existing Workers keep their current behavior until you change their compatibility date or flags. To try the new registry before November 1, keep your current date and add `new_module_registry` to your existing flags. With [`cf`](/cf/get-started/), set `worker.compatibilityFlags` in [`cloudflare.config.ts`](/cf/projects/cloudflare-config/). With Wrangler, set `compatibility_flags`:

<WranglerConfig
cfConfig={`import { defineConfig } from "cf/config";

export default defineConfig({
worker: {
name: "my-worker",
entrypoint: "./src/index.ts",
compatibilityDate: "2026-10-17",
compatibilityFlags: ["new_module_registry"],
},
});`}
>

```toml
compatibility_flags = ["new_module_registry"]
```

</WranglerConfig>

With `cf`, run `cf dev` to test locally, then `cf deploy` to publish the change. For an existing Wrangler project, follow the [migration guide](/cf/wrangler/migrate/) before switching to `cf`.

Before updating, check your dependencies for invalid import attributes and changes to `require()` behavior. The new registry rejects invalid import attributes. Calls to `require()` also fail if the module or any of its dependencies use top-level `await`. To keep the legacy registry with a compatibility date of `2026-11-01` or later, add `legacy_module_registry` to the same flags list instead of `new_module_registry`.

For migration details, refer to the [new module registry compatibility flag](/workers/configuration/compatibility-flags/#new-module-registry), [bundling documentation](/workers/wrangler/bundling/#runtime-module-loading), and [Node.js compatibility documentation](/workers/runtime-apis/nodejs/).
22 changes: 22 additions & 0 deletions src/content/compatibility-flags/new-module-registry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
name: "New module registry"
sort_date: "2026-11-01"
enable_date: "2026-11-01"
enable_flag: "new_module_registry"
disable_flag: "legacy_module_registry"
---

For compatibility dates on or after November 1, 2026, JavaScript Workers use the new module registry by default. For earlier dates, add `new_module_registry` to opt in. Add `legacy_module_registry` to retain the legacy registry with a later compatibility date. Python Workers continue to use the legacy registry.

The registry resolves and loads the modules uploaded with your Worker and the runtime's built-in modules. It provides `import.meta.url`, `import.meta.main`, and `import.meta.resolve()`, and resolves module specifiers as URLs. Different query strings or fragments create separate module instances, even when they refer to the same source.

Review these differences before changing your compatibility date:

- Import attributes are validated. Unknown attribute keys, unsupported types, and types that do not match the imported module throw errors.
- `require()` of an ES module returns its namespace unless it exports a value named `"module.exports"`. Workers' built-in `node:` modules return their default export. The `__cjsUnwrapDefault` marker in existing bundles still unwraps the default export.
- `require()` rejects module graphs containing top-level `await`, even if the graph has already finished evaluating. Use dynamic `import()` for these modules.
- The legacy-registry flags `export_commonjs_default`, `require_returns_default_export`, `throw_on_unrecognized_import_assertion`, and `disable_top_level_await_in_require` do not control the new registry.

The registry does not download modules from arbitrary URLs or install npm dependencies. Your build tooling still determines which modules are uploaded and may transform imports or `import.meta` before deployment. Refer to [Bundling](/workers/wrangler/bundling/#runtime-module-loading) and [Node.js compatibility](/workers/runtime-apis/nodejs/).

For background and examples, refer to [How we rebuilt Cloudflare Workers' module registry for Node.js compatibility](https://blog.cloudflare.com/workers-module-registry-nodejs/).
6 changes: 6 additions & 0 deletions src/content/docs/workers/wrangler/bundling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ You can provide `rules` and set `find_additional_modules` in your configuration
Furthermore, we have an escape hatch in the form of [Custom Builds](/workers/wrangler/custom-builds/), which lets you run your own build before Wrangler's built-in one.
:::

## Runtime module loading

The runtime's module registry resolves and loads the modules that your build uploads. For compatibility dates on or after November 1, 2026, JavaScript Workers use the [new module registry](/workers/configuration/compatibility-flags/#new-module-registry) by default. With earlier dates, add `new_module_registry` to opt in. Use `legacy_module_registry` to opt out with a later date.

The new registry supports `import.meta.url`, `import.meta.main`, and `import.meta.resolve()`, URL-based module resolution, and validated import attributes. Your bundler may transform these expressions before the runtime receives your code. To preserve your module graph, use [unbundled deployments](/workers/wrangler/configuration/#bundling) or configure [additional modules](#find-additional-modules).

## Including non-JavaScript modules

{/* Changes to this section should also be applied to /workers/vite-plugin/reference/non-javascript-modules */}
Expand Down
Loading