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

can't use env in Netlify edge runtime #254

Closed
1 task done
jamesarosen opened this issue May 5, 2024 · 1 comment · Fixed by #255
Closed
1 task done

can't use env in Netlify edge runtime #254

jamesarosen opened this issue May 5, 2024 · 1 comment · Fixed by #255
Labels
needs triage Issue needs to be triaged

Comments

@jamesarosen
Copy link

jamesarosen commented May 5, 2024

Astro Info

Astro                    v4.7.1
Node                     v18.19.1
System                   macOS (arm64)
Package Manager          npm
Output                   server
Adapter                  @astrojs/netlify
Integrations             none

If this issue only occurs in one browser, which browser is a problem?

No response

Describe the Bug

When using Netlify's Edge Runtime, Astro compiles import.meta.env.FOO to process.env.FOO, but process.env doesn't exist for that runtime.

How I found this

astro build adds the Astro component runtime to the site's middleware stack if both (a) the middleware and (b) a .astro Page or Component import the same shared library from src/lib/, even if that library has nothing to do with Astro or HTML.

In b09bfe5a, the middleware.ts shares nothing with the *.astro files. process.env does not appear in the compiled middleware.mjs. The compiled middleware.mjs is 56710 bytes. It includes the cookie and astro/dist/core modules.

In 4551a260, the middleware.ts and Card.astro share an import, though the import is pure JS and unrelated to Astro. This import causes the compiled middleware.mjs to gain 66721 bytes, 1600 new lines, and the cssesc, kleur, html-escaper, and clsx packages. Most notably, it adds a process.env reference that breaks the Netlify build.

In 4fba3cf5, I show that just adding an import.meta.env.NODE_ENV reference to the middleware is enough to break the Netlify build.

I get this in my site's logs, though the line numbers don't match up with what's compiled here:

7:23:50 AM: > grep -C 5 -n -e "process.env" .netlify/edge-functions/middleware/middleware.mjs
7:23:50 AM: 172-    }
7:23:50 AM: 173-  }
7:23:50 AM: 174-});
7:23:50 AM: 175-
7:23:50 AM: 176-// .netlify/functions-internal/ssr/_astro-internal_middleware.mjs
7:23:50 AM: 177:var NODE_ENV = process.env.NODE_ENV;
7:23:50 AM: 178-var onRequest$1 = async (context, next) => {
7:23:50 AM: 179-  const response = await next();
7:23:50 AM: 180-  response.headers.set("middleware", "true");
7:23:50 AM: 181-  response.headers.set("NODE_ENV", NODE_ENV);
... snip
7:23:51 AM: Local version of types is up-to-date: 663522976e5ecd0008f2a7e3
7:23:51 AM: Using global installation of Deno CLI
7:23:51 AM: Using global installation of Deno CLI
7:23:51 AM: TypeError: Cannot read properties of undefined (reading 'env')
7:23:51 AM:     at file:///opt/build/repo/.netlify/edge-functions/middleware/middleware.mjs:177:24
7:23:51 AM: ​
7:23:51 AM: Bundling of edge function failed                              
7:23:51 AM: ────────────────────────────────────────────────────────────────
7:23:51 AM: ​
7:23:51 AM:   Error message
7:23:51 AM:   Could not load edge function at '/opt/build/repo/.netlify/edge-functions/middleware/middleware.mjs'. More on the Edge Functions API at https://ntl.fyi/edge-api.

What's the expected result?

The the middleware doesn't reference any Astro components or pages, the compiled middleware code should not be affected by *.astro files importing the same files that it does. The runtimes should be isolated.

According to the Netlify Edge Functions docs, Astro should probably compile those references to Netlify.env.get.

Link to Minimal Reproducible Example

https://github.com/jamesarosen/astro-broken-middleware-demo

Participation

  • I am willing to submit a pull request for this issue.
@github-actions github-actions bot added the needs triage Issue needs to be triaged label May 5, 2024
@jamesarosen jamesarosen changed the title astro build "infects" middleware with component runtime can't use env in Netlify edge runtime May 5, 2024
@pieh
Copy link

pieh commented May 6, 2024

It's unclear to me if it's best way to solve this, but this can be addressed with following:

In

import { onRequest } from "${fileURLToPath(entrypoint).replaceAll('\\', '/')}";
import { createContext, trySerializeLocals } from 'astro/middleware';
export default async (request, context) => {
const ctx = createContext({
request,
params: {}
});
ctx.locals = { netlify: { context } }
const next = () => {
const { netlify, ...otherLocals } = ctx.locals;
request.headers.set("x-astro-locals", trySerializeLocals(otherLocals));
request.headers.set("x-astro-middleware-secret", "${middlewareSecret}");
return context.next();
};
return onRequest(ctx, next);
}
export const config = {
name: "Astro Middleware",
generator: "@astrojs/netlify@${packageVersion}",
path: "/*", excludedPath: ["/_astro/*", "/.netlify/images/*"]
};

have import process from 'node:process' and somewhere in global scope of written file assign that process to global space - i.e. globalThis.process = process

and finally adjust bundling config (

await build({
entryPoints: [fileURLToPath(new URL('./entry.mjs', middlewareOutputDir()))],
target: 'es2022',
platform: 'neutral',
mainFields: ['module', 'main'],
outfile: fileURLToPath(new URL('./middleware.mjs', middlewareOutputDir())),
allowOverwrite: true,
format: 'esm',
bundle: true,
minify: false,
});
) to allow importing node:process as with current configuration it would fail (likely due to neutral platform being used). In my quick test I just added node:process as external and this resulted in successful deploy with being able to use both import.meta.env and process.env in my test middleware.

Wether this is best way to actually fix it or not is a bit TBD, but seems like what is needed is to make process available on global.

Another way (might be more idiomatic way to provide global than above) is to use inject feature of esbuild ( https://esbuild.github.io/api/#inject )

@bluwy bluwy transferred this issue from withastro/astro May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs triage Issue needs to be triaged
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants