Skip to content

Commit 3a8481d

Browse files
authored
Merge pull request #83 from expatfile/development
🔖 Release stable version
2 parents db46ef1 + b76bc4b commit 3a8481d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2773
-1625
lines changed

.eslintrc.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ module.exports = {
2828
},
2929
overrides: [
3030
{
31-
files: ['src/__mocks__/.*', '**/*.spec.ts'],
31+
files: ['src/__mocks__/.*', '**/*.spec.ts', '**/*.spec.tsx'],
3232
rules: {
3333
'import/no-extraneous-dependencies': [
3434
'error',
@@ -42,7 +42,7 @@ module.exports = {
4242
settings: {
4343
'import/resolver': {
4444
node: {
45-
extensions: ['.js', '.ts'],
45+
extensions: ['.js', '.ts', '.jsx', '.tsx'],
4646
},
4747
},
4848
},

.github/workflows/release.yml

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ name: Release
33
on:
44
push:
55
branches:
6-
- 1.x
76
- main
87
- development
98

README.md

+49-115
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Populate your environment at **runtime** rather than **build time**.
66

77
- Isomorphic - Server and browser compatible (and even in middleware.)
8-
- Static site generation support.
8+
- Next.js 13 App Router compatible.
99
- `.env` support during development, just like [Next.js][nextjs-env-vars-order].
1010

1111
### Why we created this package 🤔
@@ -26,151 +26,88 @@ once, deploy many principle?
2626

2727
### This package 📦
2828

29-
`next-runtime-env` solves this problem by generating a JavaScript file that
30-
contains the environment variables at runtime, so you no longer have to declare
31-
your environment variables at build time. This file is loaded in the client,
32-
safely exposing those variables to the browser. This allows you to follow the
33-
build once, deploy many principle by providing differed runtime variables to the
34-
same build.
29+
`next-runtime-env` solves this problem by creating a context that exposes your environment variables at runtime, so you no longer have to declare
30+
your environment variables at build time. The context provider safely exposes all environment variables prefixed with `NEXT_PUBLIC_` to the browser. This allows you to follow the build once, deploy many principle by providing differed runtime variables to the same build.
3531

3632
### Compatibility 🤝
3733

38-
Our approach is compatible with
39-
[static site generation][static-generation-link] and supports middleware.
40-
41-
For Next.js 13 App Router support, user `[email protected]` or higher.
34+
Because `next-runtime-env` is build on top of server components it is only compatible with Next.js 13 App Router. Use [version 1.x][pages-router-branch-link] for Next.js 13 Page Router support.
4235

4336
### Getting started 🚀
4437

45-
1. Add the following lines to your `next.config.js`:
38+
Add the following lines to your `app/layout.tsx`:
4639

4740
```js
48-
const { configureRuntimeEnv } = require('next-runtime-env/build/configure');
49-
50-
configureRuntimeEnv();
51-
```
52-
53-
When the server starts, this generates an `__ENV.js` file in the `public` folder
54-
containing allow-listed environment variables with a `NEXT_PUBLIC_` prefix.
55-
56-
2. Add the following to the head section of your `pages/_document.js`:
41+
// app/layout.tsx
42+
import { PublicEnvProvider } from 'next-runtime-env';
43+
44+
export default function RootLayout({
45+
children,
46+
}: {
47+
children: React.ReactNode;
48+
}) {
49+
return (
50+
<html lang="en">
51+
<body>
52+
<PublicEnvProvider>{children}</PublicEnvProvider>
53+
</body>
54+
</html>
55+
);
56+
}
5757

58-
```tsx
59-
// pages/_document.tsx
60-
<script src="/__ENV.js" />
58+
// By default server components are statically generated at build-time. To make
59+
// sure the env vars are actually loaded use, add the following line to server
60+
// components that use [env]. 👇
61+
export const dynamic = 'force-dynamic';
6162
```
6263

63-
This will load the generated file in the browser.
64+
The `PublicEnvProvider` will automatically expose all environment variables prefixed with `NEXT_PUBLIC_` to the context. If you want more control over which variables are exposed to the context, you can use the `EnvProvider` and define the exposed variables manually.
6465

6566
### Usage 🧑‍💻
6667

67-
In the browser, your variables will now be available at
68-
`window.__ENV.NEXT_PUBLIC_FOO` and on the server at
69-
`process.env.NEXT_PUBLIC_FOO`. For example:
68+
In the browser your environment variables are now accessible using the `useEnvContext` hook. On the server you can use `process.env` because the layout is forced to be dynamic. For example:
7069

7170
```bash
7271
# .env
7372
NEXT_PUBLIC_FOO="foo"
7473
BAR="bar"
75-
NEXT_PUBLIC_BAZ="baz"
76-
```
77-
78-
```tsx
79-
// pages/some-page.tsx
80-
type Props = {
81-
bar: string;
82-
};
83-
84-
export default function SomePage({ bar }: Props) {
85-
return (
86-
<div>
87-
{window.__ENV.NEXT_PUBLIC_FOO} {bar}
88-
</div>
89-
);
90-
}
91-
92-
export const getStaticProps: GetStaticProps = async (context) => {
93-
return {
94-
props: {
95-
bar: process.env.BAR,
96-
},
97-
};
98-
};
9974
```
10075

101-
### Utilities 🛠
102-
103-
We have included some utility function to make it even easier to work with
104-
environment variables.
105-
106-
#### `env(key: string): string | undefined`
107-
108-
Returns the value of the environment variable with the given key. If the
109-
environment variable is not found, it returns undefined.
110-
111-
##### Example
76+
> A `.env` file is not required, you can also declare your environment variables in whatever way you want.
11277
11378
```tsx
114-
// pages/some-page.tsx
115-
import { env } from 'next-runtime-env';
79+
// app/client-page.tsx
80+
'use client';
11681

117-
type Props = {
118-
bar: string;
119-
};
82+
import { useEnvContext } from 'next-runtime-env';
83+
84+
export default function SomePage() {
85+
const { NEXT_PUBLIC_FOO } = useEnvContext();
12086

121-
export default function SomePage({ bar }: Props) {
12287
return (
123-
<div>
124-
{env('NEXT_PUBLIC_FOO')} {bar}
125-
</div>
88+
<main >
89+
NEXT_PUBLIC_FOO: {NEXT_PUBLIC_FOO}
90+
</main>
12691
);
12792
}
128-
129-
export const getStaticProps: GetStaticProps = async (context) => {
130-
return {
131-
props: {
132-
bar: env('BAR'),
133-
},
134-
};
135-
};
13693
```
13794

138-
#### `allEnv(): ProcessEnv`
139-
140-
Returns all environment variables as a `ProcessEnv` object regardless of
141-
the platform. This is useful if you want to destructure multiple env vars at
142-
once.
143-
144-
##### Example
145-
14695
```tsx
147-
// pages/some-page.tsx
148-
import { allEnv } from 'next-runtime-env';
149-
150-
type Props = {
151-
bar: string;
152-
};
153-
154-
export default function SomePage({ bar }: Props) {
155-
const { NEXT_PUBLIC_FOO, NEXT_PUBLIC_BAZ } = allEnv();
96+
// app/server-page.tsx
15697

98+
export default function SomePage() {
15799
return (
158-
<div>
159-
{NEXT_PUBLIC_FOO} {NEXT_PUBLIC_BAZ} {bar}
160-
</div>
100+
<main >
101+
BAR: {process.env.BAR}
102+
</main>
161103
);
162104
}
105+
```
163106

164-
export const getStaticProps: GetStaticProps = async (context) => {
165-
const { BAR } = allEnv();
107+
### Utilities 🛠
166108

167-
return {
168-
props: {
169-
bar: BAR,
170-
},
171-
};
172-
};
173-
```
109+
We have included some utility function to make it even easier to work with
110+
environment variables.
174111

175112
#### `makeEnvPublic(key: string | string[]): void`
176113

@@ -185,18 +122,14 @@ array of keys.
185122

186123
```js
187124
// next.config.js
188-
const { configureRuntimeEnv } = require('next-runtime-env/build/configure');
189-
const { makeEnvPublic } = require('next-runtime-env/build/make-env-public');
125+
const { makeEnvPublic } = require('next-runtime-env');
190126

191127
// Given that `FOO` is declared as a regular env var, not a public one. This
192128
// will make it public and available as `NEXT_PUBLIC_FOO`.
193129
makeEnvPublic('FOO');
194130

195131
// Or you can make multiple env vars public at once.
196132
makeEnvPublic(['BAR', 'BAZ']);
197-
198-
// This will generate the `__ENV.js` file and include `NEXT_PUBLIC_FOO`.
199-
configureRuntimeEnv();
200133
```
201134

202135
### Maintenance 👷
@@ -207,6 +140,7 @@ The #1 US expat tax e-filing software. 🇺🇸
207140
### Other work 📚
208141

209142
Big thanks to the [react-env][react-env-repo] project, which inspired us. 🙏
143+
Also, a big shout out to @andonirdgz for the idea to use a context provider. 💪
210144

211145
[build-url]: https://img.shields.io/github/checks-status/expatfile/next-runtime-env/main
212146
[cov-img]: https://codecov.io/gh/expatfile/next-runtime-env/branch/main/graph/badge.svg?token=mbGgsweFuP
@@ -217,7 +151,7 @@ Big thanks to the [react-env][react-env-repo] project, which inspired us. 🙏
217151
[build-once-deploy-many-link]: https://www.mikemcgarr.com/blog/build-once-deploy-many.html
218152
[fundamental-principle-link]: https://cloud.redhat.com/blog/build-once-deploy-anywhere
219153
[twelve-factor-link]: https://12factor.net
220-
[static-generation-link]: https://nextjs.org/docs/basic-features/pages#static-generation
154+
[pages-router-branch-link]: https://github.com/expatfile/next-runtime-env/tree/1.x
221155
[nextjs-env-vars]: https://nextjs.org/docs/basic-features/environment-variables
222156
[react-env-repo]: https://github.com/andrewmclagan/react-env
223157
[expatfile-site]: https://expatfile.tax

docs/EXPOSING_CUSTOM_ENV.md

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Exposing custom environment variables 🛠
2+
3+
You might not only want to expose environment variables that are prefixed with `NEXT_PUBLIC_`. In this case you can use the `EnvProvider` to expose custom environment variables to the context.
4+
5+
## Example
6+
7+
```tsx
8+
// app/layout.tsx
9+
10+
import { EnvProvider } from 'next-runtime-env';
11+
12+
export default function RootLayout({
13+
children,
14+
}: {
15+
children: React.ReactNode;
16+
}) {
17+
return (
18+
<html lang="en">
19+
<body>
20+
<EnvProvider
21+
env={{
22+
NEXT_PUBLIC_: process.env.NEXT_PUBLIC_FOO,
23+
BAR: process.env.BAR,
24+
BAZ: process.env.BAZ,
25+
notAnEnvVar: 'not-an-env-var',
26+
}}
27+
>
28+
{children}
29+
</EnvProvider>
30+
</body>
31+
</html>
32+
);
33+
}
34+
35+
// By default server components are statically generated at build-time. To make
36+
// sure the env vars are actually loaded use, add the following line to server
37+
// components that use [env]. 👇
38+
export const dynamic = 'force-dynamic';
39+
```

docs/GETTING_STARTED.md

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Getting started 🚀
2+
3+
1. First, install the package into your project:
4+
5+
```bash
6+
npm install next-runtime-env
7+
# or
8+
yarn add next-runtime-env
9+
# or
10+
pnpm install next-runtime-env
11+
```
12+
13+
2. Then wrap your component with RuntimeEnvProvider, for example in the root layout:
14+
15+
```tsx
16+
// src/app/layout.tsx
17+
import { PublicEnvProvider } from 'next-runtime-env';
18+
19+
export default function RootLayout({
20+
children,
21+
}: {
22+
children: React.ReactNode;
23+
}) {
24+
return (
25+
<html lang="en">
26+
<body>
27+
<PublicEnvProvider>{children}</PublicEnvProvider>
28+
</body>
29+
</html>
30+
);
31+
}
32+
```
33+
34+
> Keep in mind that the RuntimeEnvProvider must be added in a Server Component.
35+
36+
3. Next force dynamic generation for the Server Component by adding the following line:
37+
38+
```tsx
39+
// src/app/layout.tsx
40+
41+
// ...
42+
43+
export const dynamic = 'force-dynamic';
44+
```
45+
46+
> By default server components are statically generated at build-time. To make sure the env vars are actually loaded during runtime, you need to force dynamic generation.
47+
48+
4. Finally, use `useEnvContext` hook to access the runtime environment variables in your components:
49+
50+
```tsx
51+
import { useEnvContext } from 'next-runtime-env';
52+
53+
export function MyComponent() {
54+
const { NEXT_PUBLIC_FOO, NEXT_PUBLIC_BAZ } = useEnvContext();
55+
56+
useEffect(() => {
57+
// some api call using NEXT_PUBLIC_BAZ
58+
}, [NEXT_PUBLIC_BAZ]);
59+
60+
return <div>{NEXT_PUBLIC_FOO}</div>;
61+
}
62+
```
63+
64+
That's it! You can now use the next-runtime-env package to access runtime environment variables in your Next.js app.

docs/MAKING_ENV_PUBLIC.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Making env public 🛠
2+
3+
In some cases you might have control over the naming of the environment variables. (Or you simply don't want to prefix them with `NEXT_PUBLIC_`.) In this case you can use the `makeEnvPublic` utility function to make them public.
4+
5+
## Example
6+
7+
```ts
8+
// next.config.js
9+
10+
const { makeEnvPublic } = require('next-runtime-env');
11+
12+
// Given that `FOO` is declared as a regular env var, not a public one. This
13+
// will make it public and available as `NEXT_PUBLIC_FOO`.
14+
makeEnvPublic('FOO');
15+
16+
// Or you can make multiple env vars public at once.
17+
makeEnvPublic(['BAR', 'BAZ']);
18+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

0 commit comments

Comments
 (0)