Skip to content

Allow PUBLIC_* environment variables in adapter-node configuration #13907

@BastiDood

Description

@BastiDood

Describe the problem

The Node.js adapter natively supports special environment variables for configuring the runtime behavior of the Node.js server. Unfortunately, only the non-PUBLIC_*-prefixed versions of these environment variables are supported.

const expected = new Set([
'SOCKET_PATH',
'HOST',
'PORT',
'ORIGIN',
'XFF_DEPTH',
'ADDRESS_HEADER',
'PROTOCOL_HEADER',
'HOST_HEADER',
'PORT_HEADER',
'BODY_SIZE_LIMIT',
'SHUTDOWN_TIMEOUT',
'IDLE_TIMEOUT'
]);

Why would this be useful?

Consider the ORIGIN environment variable, which is the source of truth for the base of the request URL. There are many cases when this ORIGIN would be useful to embed into the page.1.

Sadly, that can't be done out of the box because ORIGIN is a private environment variable, which requires being executed in a server context. Importing ORIGIN from a component results in a bundle error about leaking private variables to client-side code.2

The correct way to expose this is to use PUBLIC_ORIGIN instead. But again, that doesn't work because adapter-node only checks for ORIGIN.

Describe the proposed solution

The env.js logic in adapter-node should be updated to also consider PUBLIC_*-prefixed environment variables in addition to the envPrefix.

Perhaps an open question would be: how should envPrefix interact with the PUBLIC_* prefix?

I say that the intuitive behavior is to check for both PUBLIC_{envPrefix}_* and {envPrefix}_* variables, but there is an argument to be made for {envPrefix}_PUBLIC_* instead. Personally though, I much prefer the former as it is more consistent with SvelteKit's existing rules on environment variables.

Alternatives considered

I've tried three workarounds for now and only one of them works closest to what I want.

  1. Setting envPrefix to PUBLIC. This works, but it exposes all of the adapter-node environment variables. If only PUBLIC_ORIGIN is needed, this is quite overkill.
  2. Proxying via the load function in +page.server.js files. This also works, but it falls short when pre-rendering is enabled because it emits a data.json endpoint in the build output. It would certainly be unused as the page is pre-rendered, but I'd rather have it not emit anything at all.
  3. Using page.url.origin in client-side code. This has been the best option so far. It still isn't perfect, though, because it now requires JavaScript execution just to obtain the origin at runtime. The pre-rendered output results in http://sveltekit-prerender being the substitute value.3 Ideally, this should be the PUBLIC_ORIGIN itself.

Importance

nice to have

Additional Information

I'd be willing to submit a PR for this if the work is approved by the team. 🚀

Footnotes

  1. The data-login_uri for a "sign in with Google" button is my motivating example at work. You can also think about OpenGraph use cases with the <meta> tag.

  2. This is great, by the way! 🎉

  3. For OpenGraph use cases in <meta> tags, the origin being pre-rendered as http://sveltekit-prerender is a pre-render-exclusive SEO footgun because some web crawlers can't execute JavaScript.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions