kit
kit copied to clipboard
After upgrading to Vite 3 and with latest SvelteKit `process.env.NODE_ENV` is not replaced anymore
Describe the bug
I was using "@sveltejs/kit": "1.0.0-next.370" and "vite": "2.9.14".
After the upgrade to "@sveltejs/kit": "1.0.0-next.391" and "vite": "3.0.2" I'm having issue with service-worker.ts which has this code in it:
/// <reference lib="webworker" />
import {
precacheAndRoute,
createHandlerBoundToURL,
cleanupOutdatedCaches,
} from "workbox-precaching";
import { NavigationRoute, registerRoute } from "workbox-routing";
import { build, files, version } from "$service-worker";
const worker = self as unknown as ServiceWorkerGlobalScope;
cleanupOutdatedCaches();
precacheAndRoute([
...build.map((f) => ({ url: f, revision: null })),
/// more code
]);
// other workbox code
What is happening is that after npm run build (vite build) the service-worker.js in build directory contains code like:
....M="production"===process.env.NODE_ENV?K:A;class l extends Error{constructor(e,t).....
As you can see process.env.NODE_ENV is not replaced.
Reading on vitejs config I saw the define property which should do replacement like this:
define: {
"process.env.NODE_ENV": '"production"',
//"process.env.NODE_ENV": import.meta.env.MODE, // this doesn't work
},
I think this is not correct usage in SvelteKit.
I think SvelteKit should replace automagically that env because it's so common in the world.
System Info
System:
OS: Windows 10 10.0.19044
Binaries:
Node: 16.16.0 - C:\Program Files\nodejs\node.EXE
npm: 8.15.0 - C:\Program Files\nodejs\npm.CMD
npmPackages:
@sveltejs/adapter-static: 1.0.0-next.38 => 1.0.0-next.38
@sveltejs/kit: 1.0.0-next.391 => 1.0.0-next.391
svelte: 3.49.0 => 3.49.0
vite: 3.0.2 => 3.0.2
Severity
blocking an upgrade
I'm using this code right now:
import { sveltekit } from "@sveltejs/kit/vite";
import { defineConfig } from "vite";
export default defineConfig(({ mode }) => {
return {
plugins: [sveltekit()],
define: {
"process.env.NODE_ENV":
mode === "production" ? '"production"' : '"development"',
},
//other configs...
};
});
Wat do you think?
SvelteKit was never handling process.env.NODE_ENV so I assume this is a change in Vite. I'd prefer that Vite be responsible for this sort of thing, but we need to figure out what changed between 2 and 3.
Rich, what an honor your direct answer. You are a human example for me to follow.
I read that Vite doesn't want to replace these envs so I guess the only way is to do it by hand with the code I posted, if you think (rightly) it's not SvelteKit's job.
If you change process.env.NODE_ENV to process.env['NODE_ENV'] does Vite's behavior change? I remember that in Vite v2 there was code that did an actual text search for process.env. (note trailing dot) followed by identifier characters, and replaced those with property accesses off of an object that contained only env vars with the "allowable" prefix (VITE_ by default), but that could be worked around by using process.env['NODE_ENV'] which would not match Vite's text search regex. I haven't had time to investigate whether this workaround still works in Vite v3, but it's probably worth a try.
This is not possible to try for me because I'm importing workbox in service-worker.ts. And it uses a lot of process.env.*.
I ran into this issue as well, just upgraded to the latest SvelteKit. I have code like this in my svelte.config.js to change the base path depending on if it's development or not. You might wonder why I need that though? It's because all my API calls are proxied via an /routes/api/[...rest]/+server.js catch all, which needs to live, relative to the routes, where it will in production (and my whole SvelteKit app is under a subfolder of the legacy app in production, using adapter-static).
const config = {
kit: {
paths: {
base: process.env.NODE_ENV === 'development' ? undefined : '/v2'
...
A simple workaround is to just set it in my package.json scripts like this. I think I'll look for and/or file a bug Vite as well.
"scripts": {
"dev": "NODE_ENV=development vite dev"
}
I have the same problem. When I use workbox, many process.env.NODE_ENV are seen in the service-worker.js in build directory.
It seems that vite.config.js configuration is not used to build service-worker. I used define and @rollup/plugin-replace but it didn't work.
vite.config.ts is indeed ignored while building the service worker (see: build_service_worker.js)
As far as I'm aware process.env replacing in vite only worked through the define plugin. Which is used by everyone with large enough dependency graph, since too much of the ecosystem uses process.env.NODE_ENV checks.
Now, the behaviour was probably changed by this PR: https://github.com/sveltejs/kit/pull/5839/files#diff-435b0550c8431b095f93ce127dfa5bef62671c54f320f0aaaa44d3dfd7b332b1L67-R66
After this, sw build uses it's own config and no longer merges the default config, effectively making it impossible to use the define plugin (and any other plugins or configuration options, to be precise).
While I'm not sure we actually need to merge the default config (there might be some incompatible plugins and options), there should be a way to tweak the sw build configuration. We can probably add vite.service-worker.config.ts or provide configuration through kit.serviceWorker option in svelte.config.js
If I'm reading correctly this issue should be resolved with #6329, which will allow the use of define again for the service worker. In the meantime, my workaround is basically a post-build sed script, heh...
Yep, this should work now — we can probably close this issue. Any objections?
Yep, this should work now — we can probably close this issue. Any objections?
No, it still doesn't work, so I implemented the Option 1 you proposed in #6329
This one is tricky as Vite doesn't have a concept of a 'service worker build', just SSR or not-SSR. Options:
- pass through certain properties from the main config (e.g.
define)- add an option to the plugin like
sveltekit({ serviceWorkerConfig: vite.UserConfig })Option 1 would be a breaking change. Option 2 is probably the better choice, and could be done in a non-breaking way, but I'm going to mark this as 'breaking' in case we decide the other way
Confirmed that #7140 (which went live in @sveltejs/[email protected]) makes it possible to create a functional Workbox service worker.
If you are using Workbox to build your service worker, you will need to add the following configuration to your vite.config file. Note that this requires exporting a defineConfig function instead of a simple config object.
export default defineConfig(({ mode }) => {
// ...the rest of your Vite configuration...
define: {
'process.env.NODE_ENV': mode === 'production' ? '"production"' : '"development"'
},
}
I think this can be closed, but I wonder if a note about this should be included in 10_service_workers? Anyone who uses Workbox (or perhaps any other service worker library, I haven't tried) will have a failing service worker until they implement this configuration, and the console errors for that sort of thing are not very helpful.
This may be implemented in Vite 4.2: https://github.com/vitejs/vite/blob/v4.2.0-beta.0/packages/vite/CHANGELOG.md#420-beta0-2023-02-27
Is this still an issue with Vite 4? If not, closing.
I think this is working right now. I'll re-open if not. Thank you all.