I would like to use dotenv to configure the port number the app listens on via a .env file.
I minimal implementation of that approach follows these steps:
npx degit "sveltejs/sapper-template#rollup" sapper-dotenv-port.npm install dotenv..env file with content PORT=5000.src/server.js as follows:--- a/src/server.js
+++ b/src/server.js
@@ -6,6 +6,9 @@ import * as sapper from '@sapper/server';
const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';
+const result = require('dotenv').config({ debug: true });
+console.log('dotenv result:', result);
+
polka() // You can also use Express
.use(
compression({ threshold: 0 }),
I would expect that the Sapper app listens on port 5000. However, it listens on default port 3000 instead. The console output shows the reason:
❯ npm run dev
> [email protected] dev /[...]/sapper-dotenv-port
> sapper dev
✔ server (952ms)
✔ client (959ms)
> Listening on http://localhost:3000
[dotenv][DEBUG] did not match key and value when parsing line 2:
[dotenv][DEBUG] "PORT" is already defined in `process.env` and will not be overwritten
dotenv result: { parsed: { PORT: '5000' } }
✔ service worker (28ms)
As far as I understand the cause of process.env.PORT being already defined, this is due to the following two lines in the Sapper code base:
PORT: this.port at src/api/dev.ts#L287this.proc = child_process.fork(`${dest}/server/server.js`, [], {
cwd: process.cwd(),
env: Object.assign({
PORT: this.port
}, process.env),
stdio: ['ipc'],
execArgv
});
process.env.PORT = process.env.PORT || ${opts.port || 3000}; at src/cli.ts#L179fs.writeFileSync(launcher, `
// generated by sapper build at ${new Date().toISOString()}
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
process.env.PORT = process.env.PORT || ${opts.port || 3000};
console.log('Starting server on port ' + process.env.PORT);
require('./server/server.js');
`.replace(/^\t+/gm, '').trim());
Thus, the definition of process.env.PORT is hard coded. That way, it is not possible to redefine its value using dotenv.
It would be great if I could define that port number in my .env file.
I don't know if it's useful to you, but I simply add PORT=1234 to my dev task in package.json.
I don't know if it's useful to you, but I simply add
PORT=1234to mydevtask inpackage.json.
True, one can add PORT=1234 to package.json -- or alternatively to the script that calls npm start to run the application.
In my case, I use systemd and I have added line
Environment=PORT=1234
to the unit configuration that launches my Sapper app.
However, I would prefer a unified way to configure my various Node.js apps. Usually, I configure those apps via dotenv. That way, I know directly where I find the respective configuration.
@martinburger you should put require('dotenv').config({ debug: true }); above const { PORT, NODE_ENV } = process.env;. I haven't checked, but that's how I usually do it and it works afaik.
Edit: Looks like you need require('dotenv').config({ override: true }) which is suboptimal.
I think the trick is to use Node.js' --require(-r) command line option to preload dotenv in the production environment:
diff --git a/package.json b/package.json
index 55e44ad..caf661f 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
"dev": "sapper dev",
"build": "sapper build --legacy",
"export": "sapper export --legacy",
- "start": "node __sapper__/build",
+ "start": "node -r dotenv/config __sapper__/build",
"cy:run": "cypress run",
"cy:open": "cypress open",
"test": "run-p --race dev cy:run"
That way, Sapper takes the PORT number specified in the .env file into account.
diff --git a/src/server.js b/src/server.js
index c77f593..d558ead 100644
--- a/src/server.js
+++ b/src/server.js
@@ -3,6 +3,14 @@ import polka from 'polka';
import compression from 'compression';
import * as sapper from '@sapper/server';
+const dotenvResult = require('dotenv').config();
+if (!dotenvResult.error) {
+ console.log(`PORT from .env file: ${dotenvResult.parsed.PORT}`);
+} else {
+ console.log('No .env file.');
+}
+console.log(`PORT from process.env: ${process.env.PORT}`);
+
const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';
After building Sapper with npm run build I get the following results.
No .env file:
$ npm start
[...]
Starting server on port 3000
No .env file.
PORT from process.env: 3000
No PORT set in existing .env file:
$ npm start
[...]
Starting server on port 3000
PORT from .env file: undefined
PORT from process.env: 3000
PORT set to 5000 in .env file:
$ npm start
[...]
Starting server on port 5000
PORT from .env file: 5000
PORT from process.env: 5000
Override PORT to 6000 via command line:
$ PORT=6000 npm start
[...]
Starting server on port 6000
PORT from .env file: 5000
PORT from process.env: 6000
If you use dotenv in that way, you might want to issue a warning like the following one to avoid some confusion caused by inconsistent port numbers:
diff --git a/src/server.js b/src/server.js
index c77f593..1c9de3f 100644
--- a/src/server.js
+++ b/src/server.js
@@ -3,9 +3,18 @@ import polka from 'polka';
import compression from 'compression';
import * as sapper from '@sapper/server';
+const dotenvResult = require('dotenv').config();
+
const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';
+if (dev && !dotenvResult.error && dotenvResult.parsed.PORT && dotenvResult.parsed.PORT !== process.env.PORT) {
+ console.warn(`PORT = ${dotenvResult.parsed.PORT} is specified in .env file and Sapper runs in development mode.`);
+ console.warn(`The there specified port number differs from process.env.PORT: ${process.env.PORT}`);
+ console.warn(`You might want to run Sapper via '$ PORT=${dotenvResult.parsed.PORT} npm run dev' to use the same PORT as in .env file.`);
+ console.warn('Hint: You can set PORT via .env file in production mode if you start Sapper via "node -r dotenv/config __sapper__/build" (see package.json).');
+}
+
polka() // You can also use Express
.use(
compression({ threshold: 0 }),
This will warn you if you run Sapper in development mode and the .env file specifies PORT number:
$ npm run dev
[...]
✔ server (948ms)
PORT = 5000 is specified in .env file and Sapper runs in development mode.
The there specified port number differs from process.env.PORT: 3000
You might want to run Sapper via '$ PORT=5000 npm run dev' to use the same PORT as in .env file.
Hint: You can set PORT via .env file in production mode if you start Sapper via "node -r dotenv/config __sapper__/build" (see package.json).
> Listening on http://localhost:3000
[...]
The way to cause sapper to consider dotenv's configuration runs is as follows:
npm i -g dotenv-cli
Then edit your package json:
"scripts": {
"dev": "dotenv sapper dev",
}
That way, the contents of your .env file will be considered at application launch time.
Most helpful comment
The way to cause sapper to consider dotenv's configuration runs is as follows:
Then edit your package json:
That way, the contents of your
.envfile will be considered at application launch time.