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

Allow marking externals in Pages Functions #5172

Merged
merged 1 commit into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/unlucky-kangaroos-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"wrangler": minor
---

feat: Allow marking external modules (with `--external`) to avoid bundling them when building Pages Functions

It's useful for Pages Plugins which want to declare a peer dependency.
3 changes: 3 additions & 0 deletions fixtures/pages-functions-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@
},
"engines": {
"node": ">=16.13"
},
"dependencies": {
"is-odd": "^3.0.1"
}
}
7 changes: 7 additions & 0 deletions fixtures/pages-functions-app/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ describe("Pages Functions", () => {
expect(response.status).toBe(502);
});

it("should work with peer externals", async ({ expect }) => {
const response = await fetch(`http://${ip}:${port}/mounted-plugin/ext`);
const text = await response.text();
expect(text).toMatchInlineSnapshot(`"42 is even"`);
expect(response.status).toBe(200);
});

it("should mount a Plugin even if in a parameterized route", async ({
expect,
}) => {
Expand Down
5 changes: 5 additions & 0 deletions fixtures/pages-plugin-example/functions/ext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import isOdd from "is-odd";

export const onRequest: PagesFunction = () => {
return new Response(`42 is ${isOdd(42) ? "odd" : "even"}`);
};
3 changes: 2 additions & 1 deletion fixtures/pages-plugin-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
"public/"
],
"scripts": {
"build": "wrangler pages functions build --plugin --outdir=dist",
"build": "wrangler pages functions build --plugin --outdir=dist --external=is-odd",
"check:type": "tsc"
},
"devDependencies": {
"is-odd": "^3.0.1",
"wrangler": "workspace:*"
}
}
3 changes: 3 additions & 0 deletions fixtures/pages-plugin-mounted-on-root-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@
},
"engines": {
"node": ">=16.13"
},
"dependencies": {
"is-odd": "^3.0.1"
}
}
6 changes: 5 additions & 1 deletion packages/wrangler/src/deployment-bundle/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export type BundleOptions = {
local: boolean;
projectRoot: string | undefined;
defineNavigatorUserAgent: boolean;
external?: string[];
};

/**
Expand Down Expand Up @@ -122,6 +123,7 @@ export async function bundleWorker(
local,
projectRoot,
defineNavigatorUserAgent,
external,
}: BundleOptions
): Promise<BundleResult> {
// We create a temporary directory for any one-off files we
Expand Down Expand Up @@ -284,7 +286,9 @@ export async function bundleWorker(
}
: {}),
inject,
external: bundle ? ["__STATIC_CONTENT_MANIFEST"] : undefined,
external: bundle
? ["__STATIC_CONTENT_MANIFEST", ...(external ? external : [])]
: undefined,
format: entry.format === "modules" ? "esm" : "iife",
target: COMMON_ESBUILD_OPTIONS.target,
sourcemap: sourcemap ?? true,
Expand Down
10 changes: 10 additions & 0 deletions packages/wrangler/src/pages/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ export function Options(yargs: CommonYargsArgv) {
deprecated: true,
hidden: true,
},
external: {
describe: "A list of module imports to exclude from bundling",
type: "string",
array: true,
},
});
}

Expand All @@ -146,6 +151,7 @@ export const Handler = async (args: PagesBuildArgs) => {
nodejsCompat,
legacyNodeCompat,
defineNavigatorUserAgent,
external,
} = validatedArgs;

try {
Expand All @@ -172,6 +178,7 @@ export const Handler = async (args: PagesBuildArgs) => {
routesOutputPath,
local: false,
defineNavigatorUserAgent,
external,
});
} catch (e) {
if (e instanceof FunctionsNoRoutesError) {
Expand Down Expand Up @@ -213,6 +220,7 @@ export const Handler = async (args: PagesBuildArgs) => {
legacyNodeCompat,
workerScriptPath,
defineNavigatorUserAgent,
external,
} = validatedArgs;

/**
Expand Down Expand Up @@ -243,6 +251,7 @@ export const Handler = async (args: PagesBuildArgs) => {
watch,
nodejsCompat,
defineNavigatorUserAgent,
externalModules: external,
});
}
} else {
Expand All @@ -268,6 +277,7 @@ export const Handler = async (args: PagesBuildArgs) => {
routesOutputPath,
local: false,
defineNavigatorUserAgent,
external,
});
} catch (e) {
if (e instanceof FunctionsNoRoutesError) {
Expand Down
4 changes: 4 additions & 0 deletions packages/wrangler/src/pages/buildFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export async function buildFunctions({
`./functionsRoutes-${Math.random()}.mjs`
),
defineNavigatorUserAgent,
external,
}: Partial<
Pick<
PagesBuildArgs,
Expand All @@ -51,6 +52,7 @@ export async function buildFunctions({
| "watch"
| "plugin"
| "buildOutputDirectory"
| "external"
>
> & {
functionsDirectory: string;
Expand Down Expand Up @@ -120,6 +122,7 @@ export async function buildFunctions({
functionsDirectory: absoluteFunctionsDirectory,
local,
defineNavigatorUserAgent,
external,
});
} else {
bundle = await buildWorkerFromFunctions({
Expand All @@ -137,6 +140,7 @@ export async function buildFunctions({
legacyNodeCompat,
nodejsCompat,
defineNavigatorUserAgent,
external,
});
}

Expand Down
2 changes: 2 additions & 0 deletions packages/wrangler/src/pages/functions/buildPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export function buildPluginFromFunctions({
functionsDirectory,
local,
defineNavigatorUserAgent,
external,
}: Options) {
const entry: Entry = {
file: resolve(getBasePath(), "templates/pages-template-plugin.ts"),
Expand Down Expand Up @@ -51,6 +52,7 @@ export function buildPluginFromFunctions({
nodejsCompat: true,
define: {},
doBindings: [], // Pages functions don't support internal Durable Objects
external,
plugins: [
buildNotifierPlugin(onEnd),
{
Expand Down
24 changes: 18 additions & 6 deletions packages/wrangler/src/pages/functions/buildWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export type Options = {
functionsDirectory: string;
local: boolean;
defineNavigatorUserAgent: boolean;
external?: string[];
};

export function buildWorkerFromFunctions({
Expand All @@ -49,6 +50,7 @@ export function buildWorkerFromFunctions({
functionsDirectory,
local,
defineNavigatorUserAgent,
external,
}: Options) {
const entry: Entry = {
file: resolve(getBasePath(), "templates/pages-template-worker.ts"),
Expand Down Expand Up @@ -76,6 +78,7 @@ export function buildWorkerFromFunctions({
__FALLBACK_SERVICE__: JSON.stringify(fallbackService),
},
doBindings: [], // Pages functions don't support internal Durable Objects
external,
plugins: [
buildNotifierPlugin(onEnd),
{
Expand Down Expand Up @@ -170,7 +173,7 @@ export type RawOptions = {
outdir?: string;
directory: string;
bundle?: boolean;
external?: string[];
externalModules?: string[];
minify?: boolean;
sourcemap?: boolean;
watch?: boolean;
Expand All @@ -182,6 +185,7 @@ export type RawOptions = {
local: boolean;
additionalModules?: CfModule[];
defineNavigatorUserAgent: boolean;
external?: string[];
};

/**
Expand All @@ -197,7 +201,7 @@ export function buildRawWorker({
outdir,
directory,
bundle = true,
external,
externalModules,
minify = false,
sourcemap = false,
watch = false,
Expand All @@ -208,14 +212,15 @@ export function buildRawWorker({
local,
additionalModules = [],
defineNavigatorUserAgent,
external,
}: RawOptions) {
const entry: Entry = {
file: workerScriptPath,
directory: resolve(directory),
format: "modules",
moduleRoot: resolve(directory),
};
const moduleCollector = external
const moduleCollector = externalModules
? noopModuleCollector
: createModuleCollector({ entry, findAdditionalModules: false });

Expand All @@ -230,18 +235,23 @@ export function buildRawWorker({
nodejsCompat,
define: {},
doBindings: [], // Pages functions don't support internal Durable Objects
external,
plugins: [
...plugins,
buildNotifierPlugin(onEnd),
...(external
...(externalModules
? [
// In some cases, we want to enable bundling in esbuild so that we can flatten a shim around the entrypoint, but we still don't want to actually bundle in all the chunks that a Worker references.
// This plugin allows us to mark those chunks as external so they are not inlined.
{
name: "external-fixer",
setup(pluginBuild) {
pluginBuild.onResolve({ filter: /.*/ }, async (args) => {
if (external.includes(resolve(args.resolveDir, args.path))) {
if (
externalModules.includes(
resolve(args.resolveDir, args.path)
)
) {
return { path: args.path, external: true };
}
});
Expand Down Expand Up @@ -296,7 +306,9 @@ export async function traverseAndBuildWorkerJSDirectory({
const bundleResult = await buildRawWorker({
workerScriptPath: entrypoint,
bundle: true,
external: additionalModules.map((m) => join(workerJSDirectory, m.name)),
externalModules: additionalModules.map((m) =>
join(workerJSDirectory, m.name)
),
outfile,
directory: buildOutputDirectory,
local: false,
Expand Down
21 changes: 21 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.