'How to use dotenv in SvelteKit project?

I'm trying to use dotenv.config() in a SvelteKit project.

I can run npm run build successfully. But when I try to start the server (using node build), it throws Error: Dynamic require of "fs" is not supported.

I tried to comment out the dotenv part in src/routes/test.js and build again, and this time the server started without any errors. (I created the project with npm init svelte@next without typescript, and except for the codes here, nothing else is changed)

How should I use dotenv here to load environment variables at runtime?

svelte.config.js

import node from '@sveltejs/adapter-node';

const config = {
    kit: {
        adapter: node(),
        target: '#svelte'
    }
};

export default config;

/src/routes/test.js

import dotenv from 'dotenv';

dotenv.config();

export function get() {
    return {
        body: {
            test: process.env.TEST
        }
    }
}

.env

TEST=123


Solution 1:[1]

No need to explicitly load dotenv. Vite uses dotenv https://vitejs.dev/guide/env-and-mode.html#env-files

You can access your variable via import.meta.env.VITE_MY_VAR

Important is that your env variables must be prefixed with VITE_ in order to get them exposed. And if you are already running npm run dev, quit it and start again.

That worked for me.

Solution 2:[2]

I solved the problem with env-cmd (https://www.npmjs.com/package/env-cmd) by adding env-cmd to the beginning of svelte-kit dev, svelte-kit preview and node build.

Also, use process.env['TEST'] instead of process.env.TEST since process.env.TEST is replaced with ({}) by vite. (https://github.com/vitejs/vite/issues/3176)

Solution 3:[3]

This is what I did:

vite has a special config option for server port.

// import adapter from '@sveltejs/adapter-static';
import adapter from '@sveltejs/adapter-node';
import preprocess from 'svelte-preprocess';
import path from 'path';
import dotenv from 'dotenv-flow';

dotenv.config();

/** @type {import('@sveltejs/kit').Config} */
const config = {
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: preprocess(),

    kit: {
        // hydrate the <div id="svelte"> element in src/app.html
        // target: '#svelte',
        /*
        adapter: adapter({
            // default options are shown
            pages: 'build',
            assets: 'build',
            fallback: 'index.html'
        }),
        */

        adapter: adapter({
            out: './build',
            precompress: true
        }),
        vite: {
            resolve: {
                alias: {
                    $components: path.resolve('./src/components'),
                    $stores: path.resolve('./src/stores'),
                    $api: path.resolve('./src/api')
                }
            },
            build: {
                minify: true
            },
            server: {
                port: process.env.PORT || 3000
            }
        }
    }
};

export default config;

I have .env for defaults (dev etc) and .env.local that is ignored in .gitignore for production (keys, etc).

When .env.local is present it uses that port.

edit: this does not work with node-adapter in production. I think we need to declare PORT some other way. it only works with npm run dev

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Christian Pfisterer
Solution 2
Solution 3 chovy