Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cloudflare-client-process-banner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/cloudflare': patch
---

Fixes the `globalThis.process` shim being prepended to client-side scripts. The shim is now only added to the server output.
17 changes: 14 additions & 3 deletions packages/integrations/cloudflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -661,12 +661,23 @@ export default function createIntegration({

vite.build ||= {};
vite.build.rolldownOptions ||= {};
vite.build.rolldownOptions.output ||= {};
vite.build.rolldownOptions.external = ['sharp'];

// Scoped to the server environments: top-level `build` options are inherited by the
// client environment, which must not ship this shim to browsers. See https://github.com/withastro/astro/issues/18182
// A user-provided top-level banner takes precedence and is inherited by the server environments as-is.
// @ts-expect-error
vite.build.rolldownOptions.output.banner ||=
'globalThis.process ??= {}; globalThis.process.env ??= {};';
if (!vite.build.rolldownOptions.output?.banner) {
for (const name of ['ssr', 'prerender']) {
vite.environments ??= {};
const environment = (vite.environments[name] ??= {}) as Record<string, any>;
environment.build ??= {};
environment.build.rolldownOptions ??= {};
environment.build.rolldownOptions.output ??= {};
environment.build.rolldownOptions.output.banner ||=
'globalThis.process ??= {}; globalThis.process.env ??= {};';
}
}

// Cloudflare env is only available per request. This isn't feasible for code that access env vars
// in a global way, so we shim their access as `process.env.*`. This is not the recommended way for users to access environment variables. But we'll add this for compatibility for chosen variables. Mainly to support `@astrojs/db`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
<body>
<h1>Static Site</h1>
<p>This is a fully static Astro site using the Cloudflare adapter.</p>
<script>
document.querySelector("h1")?.setAttribute("data-ready", "");
</script>
</body>
</html>
15 changes: 13 additions & 2 deletions packages/integrations/cloudflare/test/server-entry.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
import { describe, it } from 'node:test';
import { before, describe, it } from 'node:test';
import { type Fixture, loadFixture } from './test-utils.ts';
import assert from 'node:assert/strict';
import { existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';

describe('Server entry', () => {
let fixture: Fixture;
it('should load the custom entry when using legacy entrypoint', async () => {

before(async () => {
fixture = await loadFixture({
root: './fixtures/server-entry',
output: 'server',
});

await fixture.build();
});

it('should load the custom entry when using legacy entrypoint', async () => {
const itExits = existsSync(fileURLToPath(new URL('server/custom.mjs', fixture.config.outDir)));

assert.ok(itExits);
});

it('prepends the process shim banner to the server entry', async () => {
const entry = await fixture.readFile('/server/custom.mjs');
assert.ok(
entry.startsWith('globalThis.process ??= {};'),
'Expected the process shim at the top of the server entry',
);
});
});
17 changes: 15 additions & 2 deletions packages/integrations/cloudflare/test/static.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
import { describe, it } from 'node:test';
import { before, describe, it } from 'node:test';
import { type Fixture, loadFixture } from './test-utils.ts';
import assert from 'node:assert/strict';
import { existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';

describe('Static output', () => {
let fixture: Fixture;
it('should not output a _worker.js directory for fully static sites', async () => {

before(async () => {
fixture = await loadFixture({
root: './fixtures/static',
});

await fixture.build();
});

it('should not output a _worker.js directory for fully static sites', async () => {
const workerExists = existsSync(fileURLToPath(new URL('_worker.js', fixture.config.outDir)));

assert.ok(!workerExists, '_worker.js directory should not exist for static sites');
});

it('does not prepend the process shim banner to client scripts', async () => {
Comment thread
astro-factory[bot] marked this conversation as resolved.
const html = await fixture.readFile('/client/index.html');
assert.ok(html.includes('data-ready'), 'Expected the client script to be in the output');
assert.ok(!html.includes('globalThis.process'));
for (const file of await fixture.glob('client/_astro/*.js')) {
const js = await fixture.readFile('/' + file);
assert.ok(!js.includes('globalThis.process'), `${file} should not contain the process shim`);
}
});
});
Loading