Skip to content

Environment variables in Svelte templates don't work with npm run build #720

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

Closed
timdeschryver opened this issue Mar 27, 2021 · 21 comments · Fixed by sveltejs/svelte#6835 or #2626
Closed
Labels
bug Something isn't working vite
Milestone

Comments

@timdeschryver
Copy link

timdeschryver commented Mar 27, 2021

First of all, thank you for the great work on SvelteKit.
I migrated my blog today without too many problems, the docs, the migration guide and examples were a great help.
I just stumbled upon this problem.

Describe the bug

It seems like we can't use environment variables (e.g. import.meta.env.MODE) in a (production) build while there are also styles defined in the same route/component.

It does however work when I start the server and open the app with npm run dev

I also tried to follow the vite docs, but sadly with the same outcome.
Logs

$ svelte-kit build
vite v2.1.3 building for production...
✓ 15 modules transformed.
.svelte/output/client/_app/manifest.json                            0.67kb
.svelte/output/client/_app/assets/start-a8cd1609.css                0.16kb / brotli: 0.10kb
.svelte/output/client/_app/pages\index.svelte-91d77487.js           0.56kb / brotli: 0.33kb
.svelte/output/client/_app/assets/pages\index.svelte-c8d90d46.css   0.03kb / brotli: 0.03kb
.svelte/output/client/_app/chunks/index-5061b396.js                 4.60kb / brotli: 1.83kb
.svelte/output/client/_app/start-c78a3e4f.js                        15.25kb / brotli: 5.31kb
vite v2.1.3 building SSR bundle for production...
✓ 8 modules transformed.
file: C:/Users/tdeschryver/dev/poc/sk-environment-variables/src/routes/index.svelte:6:131
> Unexpected token (6:131)
    at Object.pp$4.raise (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:15614:13)
    at Object.pp.unexpected (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:13306:8)
    at Object.pp.expect (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:13300:26)
    at Object.pp$3.parseObj (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:15250:12)
    at Object.pp$3.parseExprAtom (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:14989:17)
    at Object.pp$3.parseExprSubscripts (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:14816:19)
    at Object.pp$3.parseMaybeUnary (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:14793:17)
    at Object.parseMaybeUnary (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:19538:29)
    at Object.pp$3.parseExprOps (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:14728:19)
    at Object.pp$3.parseMaybeConditional (C:\Users\tdeschryver\dev\poc\sk-environment-variables\node_modules\rollup\dist\shared\rollup.js:14711:19)
error Command failed with exit code 1.

To Reproduce

A reproduction can be found at: https://github.com/timdeschryver/sk-environment-variables/blob/main/src/routes/index.svelte

Steps to reproduce:

git clone https://github.com/timdeschryver/sk-environment-variables.git
cd sk-environment-variables
cd ./sk-environment-variables
npm install
npm run build

The code:

<script>
	let variable = import.meta.env.MODE
</script>

<main>
	<h1>Variable: {variable}</h1>
</main>

<!-- comment or remove styles and it works -->
<style>
	h1 {
		color:red
	}
</style>

Expected behavior

I expect the environment variable to be replaced.

Information about your SvelteKit Installation:

  • The output of npx envinfo --system --npmPackages svelte,@sveltejs/kit --binaries --browsers
  System:
    OS: Windows 10 10.0.19042
    CPU: (8) x64 Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
    Memory: 4.24 GB / 15.85 GB
  Binaries:
    Node: 14.16.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.5 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 6.14.11 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 89.0.4389.90
    Edge: Spartan (44.19041.423.0), Chromium (89.0.774.63)
    Internet Explorer: 11.0.19041.1
  npmPackages:
    @sveltejs/kit: next => 1.0.0-next.61
    svelte: ^3.29.0 => 3.35.0
  • Your adapter (e.g. Node, static, Vercel, Begin, etc...)

I get the error with all adapters, node, static, and vercel.

Severity

I have a workaround (I added the variables to a GET request), but I still wanted to log this issue because it might help others.

Additional context

/

@machycek

This comment has been minimized.

@benmccann

This comment has been minimized.

@timdeschryver

This comment has been minimized.

@benmccann benmccann added the bug Something isn't working label Mar 29, 2021
@Lukem121

This comment has been minimized.

@MirrorBytes
Copy link

MirrorBytes commented Apr 1, 2021

Avoiding dot notation with environment variables fixed the issue for me.

@Rich-Harris
Copy link
Member

This is a tricky issue and I'm not immediately sure what the best fix is, but a workaround in the meantime would be to put the env var references in a module (rather than a component) and import them into your components:

export const API_URL = import.meta.env.VITE_API_URL;

@timdeschryver

This comment has been minimized.

@joe-azps

This comment has been minimized.

@benmccann benmccann changed the title Environment variables in build Environment variables in Svelte templates don't work with npm run build May 19, 2021
@disbelief
Copy link

Small but interesting data point: npm run build only fails if the component referencing import.meta.env contains a <style> tag.

I ran into this issue when adding a <style> tag to a component that was working fine before. Took me a couple hours to figure out the root cause was this bug.

@mmarchois

This comment has been minimized.

@timdeschryver
Copy link
Author

AFAIK nothing new, but the suggested workaround works like a charm.

@disbelief
Copy link

and to be honest I actually prefer the workaround because it lets you sanitize/transform/fallback the environment variables values that import.meta.env provides, which are always strings.

Eg. I have some env vars that behave like flags (VITE_SOME_FLAG=true) so in variables I convert those to actual booleans and export the result.

@bluwy
Copy link
Member

bluwy commented Sep 18, 2021

Investigated this today, #1396 (comment) was right. IMO there are some ways we can fix this (easy to hard):

  1. remove css map in svelte's ssr compilation, since it's not used
  2. vite run define plugin first, then compile svelte, so css map generates properly
    • problem: define plugin runs between normal and post plugins, compiling svelte in post phase could not work.
    • solution: run a vite:define svelte preprocessor to replace the svelte code before compiling (handled by vite-plugin-svelte but it would be brittle)
  3. vite set import.meta.env in runtime for ssr
    • problem: many tooling expects this to be statically replaced, it would be a breaking change

I'll probably try no2 first, before no1

@bluwy
Copy link
Member

bluwy commented Sep 19, 2021

I've sent a PR in Svelte implementing solution no1: sveltejs/svelte#6744

@bluwy
Copy link
Member

bluwy commented Sep 26, 2021

From sveltejs/svelte#6744, it was closed in favour of a new options.sourcemap option of type boolean | { js: boolean; css: boolean }. If css is false, we remove the css map. For vite-plugin-svelte, we can force css to false. This is to prevent a potential breaking change.

@benmccann
Copy link
Member

vite set import.meta.env in runtime for ssr
problem: many tooling expects this to be statically replaced, it would be a breaking change

This sounds like the best solution to me. Any idea what tooling would expect it to be statically replaced?

@benmccann
Copy link
Member

benmccann commented Oct 11, 2021

Actually, answering my own question I think that would kill Rollup / Vite's ability to do dead code elimination on things like client-side vs browser-side code, so probably we would not want to do it that way on the client. But it still seems okay on the server. Perhaps we don't want client and server acting differently though

@arxpoetica
Copy link
Member

Created my own repro:

arxpoetica/sveltekit-6qwj7g
stackblitz.com/edit/sveltekit-6qwj7g?file=src%2Froutes%2Findex.svelte

git clone https://github.com/arxpoetica/sveltekit-6qwj7g.git
cd sveltekit-6qwj7g
npm install
npm run dev

Originally was here #2583, but @benmccann appropriately closed the duplicate.

@benmccann
Copy link
Member

For reference, here's the code that's being generated in @arxpoetica's example

/* src/routes/index.svelte generated by Svelte v3.43.1 */
import { create_ssr_component, escape } from "svelte/internal";

const css = {
	code: "div.s-Uap-jPRb-uiE{color:red}.s-Uap-jPRb-uiE{}",
	map: "{\"version\":3,\"file\":\"index.svelte\",\"sources\":[\"index.svelte\"],\"sourcesContent\":[\"<div>{console.log("testing")}</div>\\n<div>{"testing"}</div>\\n\\n<style>\\n\\tdiv {\\n\\t\\tcolor: red;\\n\\t}\\n *{}</style>\\n\"],\"names\":[],\"mappings\":\"AAIC,GAAG,eAAC,CAAC,AACJ,KAAK,CAAE,GAAG,AACX,CAAC,AACD,eAAC,EAAE\"}"
};

const Routes = create_ssr_component(($$result, $$props, $$bindings, slots) => {
	$$result.css.add(css);

	return `<div class="${"s-Uap-jPRb-uiE"}">${escape(console.log("testing"))}</div>
<div class="${"s-Uap-jPRb-uiE"}">${escape("testing")}</div>`;
});

export default Routes;
import "/src/routes/index.svelte?svelte&type=style&lang.css";

It's the css.map that's causing trouble, and I thought it'd be useful to see an example of it in this issue

@benmccann
Copy link
Member

Leaving this open for now. It's only partially solved. We will need to update vite-plugin-svelte as well

@smartello
Copy link

Actually, answering my own question I think that would kill Rollup / Vite's ability to do dead code elimination on things like client-side vs browser-side code, so probably we would not want to do it that way on the client. But it still seems okay on the server. Perhaps we don't want client and server acting differently though

From my perspective, it's not okay on the server because there're a lot of examples where environment gets changed for server-code and it should reflect the change. E.g. if I use a hundred different APIs, I don't want to rebuild the app every time my credentials are changed. One size does not fit all and it makes a lot of sense to have different behaviour for a client and a server codelines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working vite
Projects
None yet