Skip to content

Commit d06bcc9

Browse files
committed
feat: ✨ add script solution
1 parent 844865d commit d06bcc9

Some content is hidden

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

70 files changed

+4513
-648
lines changed

README.md

+39-111
Original file line numberDiff line numberDiff line change
@@ -1,158 +1,86 @@
11
![GitHub branch checks state][build-url] [![codecov][cov-img]][cov-url] [![Known Vulnerabilities][snyk-img]][snyk-url]
22

3-
# Next.js Runtime Environment Configuration
3+
# 🌐 Next.js Runtime Environment Configuration
44

5-
Populate your environment at **runtime** rather than **build time**.
5+
**Effortlessly populate your environment at runtime, not just at build time, with `next-runtime-env`.**
66

7-
- Isomorphic - Server and browser compatible (and even in middleware.)
8-
- Next.js 13 App Router compatible.
9-
- `.env` support during development, just like [Next.js][nextjs-env-vars-order].
7+
🌟 **Highlights:**
8+
- **Isomorphic Design:** Works seamlessly on both server and browser, and even in middleware.
9+
- **Next.js 13 & 14 Ready:** Fully compatible with the latest Next.js features.
10+
- **`.env` Friendly:** Use `.env` files during development, just like standard Next.js.
1011

11-
### Why we created this package 🤔
12+
### 🤔 Why `next-runtime-env`?
1213

13-
[Build once, deploy many][build-once-deploy-many-link] is an essential principle
14-
of software development. The main idea is to use the same bundle for all
15-
environments, from testing to production. This approach enables easy deployment
16-
and testability and is considered a
17-
[fundamental principle of continuous delivery][fundamental-principle-link]. It
18-
is also part of the [twelve-factor methodology][twelve-factor-link]. As crucial
19-
as it is, it has yet to receive significant support in the world of front-end
20-
development, and Next.js is no exception.
14+
In the modern software development landscape, the "[Build once, deploy many][build-once-deploy-many-link]" philosophy is key. This principle, essential for easy deployment and testability, is a [cornerstone of continuous delivery][fundamental-principle-link] and is embraced by the [twelve-factor methodology][twelve-factor-link]. However, front-end development, particularly with Next.js, often lacks support for this - requiring separate builds for different environments. `next-runtime-env` is our solution to bridge this gap in Next.js.
2115

22-
Next.js does support [environment variables][nextjs-env-vars], but only at
23-
build time. This means you must rebuild your app for each target environment,
24-
which violates the principle. But what if you want, or need, to follow the build
25-
once, deploy many principle?
16+
### 📦 Introducing `next-runtime-env`
2617

27-
### This package 📦
18+
`next-runtime-env` dynamically injects environment variables into your Next.js application at runtime. This approach adheres to the "build once, deploy many" principle, allowing the same build to be used across various environments without rebuilds.
2819

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.
20+
### 🤝 Compatibility Notes
3121

32-
### Compatibility 🤝
22+
- **Next.js 14:** Use `next-runtime-env@3.x` for optimal caching support.
23+
- **Next.js 13:** Opt for [`next-runtime-env@2.x`][app-router-branch-link], tailored for the App Router.
24+
- **Next.js 12/13 Page Router:** Stick with [`next-runtime-env@1.x`][pages-router-branch-link].
3325

34-
Because `next-runtime-env` uses Next.js 14 caching, it is only compatible with Next.js 14 and up.
26+
### 🔖 Version Guide
3527

36-
To use with Next.js 13 use [version 2.x][app-router-branch-link]. Version 2.x is build on top of server components it is only compatible with Next.js 13 App Router.
28+
- **1.x:** Next.js 12/13 Page Router
29+
- **2.x:** Next.js 13 App Router
30+
- **3.x:** Next.js 14 with advanced caching
3731

38-
Use [version 1.x][pages-router-branch-link] for Next.js 12/13 Page Router support.
32+
### 🚀 Getting Started
3933

40-
### Versions 🔖
41-
42-
- `next-runtime-env@1.x` - Next.js 12/13 Page Router support.
43-
- `next-runtime-env@2.x` - Next.js 13 App Router support.
44-
- `next-runtime-env@3.x` - Next.js 14 caching support.
45-
46-
### Getting started 🚀
47-
48-
Add the following lines to your `app/layout.tsx`:
34+
In your `app/layout.tsx`, add:
4935

5036
```js
5137
// app/layout.tsx
52-
import { PublicEnvProvider } from 'next-runtime-env';
38+
import { PublicEnvScript } from 'next-runtime-env';
5339

54-
export default function RootLayout({
55-
children,
56-
}: {
57-
children: React.ReactNode;
58-
}) {
40+
export default function RootLayout({ children }) {
5941
return (
6042
<html lang="en">
43+
<head>
44+
<PublicEnvScript />
45+
</head>
6146
<body>
62-
<PublicEnvProvider>{children}</PublicEnvProvider>
47+
{children}
6348
</body>
6449
</html>
6550
);
6651
}
6752
```
6853

69-
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.
54+
The `PublicEnvScript` component automatically exposes all environment variables prefixed with `NEXT_PUBLIC_` to the browser. For custom variable exposure, refer to [EXPOSING_CUSTOM_ENV.md](docs/EXPOSING_CUSTOM_ENV.md).
7055

71-
### Usage 🧑‍💻
56+
### 🧑‍💻 Usage
7257

73-
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:
74-
75-
```bash
76-
# .env
77-
NEXT_PUBLIC_FOO="foo"
78-
BAR="bar"
79-
```
80-
81-
> A `.env` file is not required, you can also declare your environment variables in whatever way you want.
58+
Access your environment variables easily:
8259

8360
```tsx
8461
// app/client-page.tsx
8562
'use client';
86-
87-
import { useEnvContext } from 'next-runtime-env';
88-
89-
export default function SomePage() {
90-
const { NEXT_PUBLIC_FOO } = useEnvContext();
91-
92-
return (
93-
<main >
94-
NEXT_PUBLIC_FOO: {NEXT_PUBLIC_FOO}
95-
</main>
96-
);
97-
}
98-
```
99-
100-
```tsx
101-
// app/server-page.tsx
102-
// This is as of Next.js 14, but you could also use other dynamic functions
103-
import { unstable_noStore as noStore } from 'next/cache';
63+
import { env } from 'next-runtime-env';
10464

10565
export default function SomePage() {
106-
noStore(); // Opt into dynamic rendering
107-
108-
// This value will be evaluated at runtime
109-
return (
110-
<main >
111-
BAR: {process.env.BAR}
112-
</main>
113-
);
66+
const NEXT_PUBLIC_FOO = env('NEXT_PUBLIC_FOO');
67+
return <main>NEXT_PUBLIC_FOO: {NEXT_PUBLIC_FOO}</main>;
11468
}
11569
```
11670

117-
### Utilities 🛠
118-
119-
We have included some utility function to make it even easier to work with
120-
environment variables.
121-
122-
#### `makeEnvPublic(key: string | string[]): void`
71+
### 🛠 Utilities
12372

124-
Makes an environment variable with a given key public. This is useful if you
125-
want to use an environment variable in the browser, but it was was not declared
126-
with a `NEXT_PUBLIC_` prefix.
127-
128-
For ease of use you can also make multiple env vars public at once by passing an
129-
array of keys.
130-
131-
##### Example
132-
133-
```js
134-
// next.config.js
135-
const { makeEnvPublic } = require('next-runtime-env');
136-
137-
// Given that `FOO` is declared as a regular env var, not a public one. This
138-
// will make it public and available as `NEXT_PUBLIC_FOO`.
139-
makeEnvPublic('FOO');
140-
141-
// Or you can make multiple env vars public at once.
142-
makeEnvPublic(['BAR', 'BAZ']);
143-
```
73+
Need to expose non-prefixed environment variables to the browser? Check out [MAKING_ENV_PUBLIC.md](docs/MAKING_ENV_PUBLIC.md).
14474

145-
> You can also use the experimental instrumentation hook introduced in Next.js 13. See the `with-app-router` example for more details.
75+
### 👷 Maintenance
14676

147-
### Maintenance 👷
77+
`next-runtime-env` is proudly maintained by [Expatfile.tax](expatfile-site), the leading US expat tax e-filing software.
14878

149-
This package is maintained and actively used by [Expatfile.tax][expatfile-site].
150-
The #1 US expat tax e-filing software. 🇺🇸
79+
### 📚 Acknowledgments
15180

152-
### Other work 📚
81+
Kudos to the [react-env](react-env-repo) project for the inspiration, and a shoutout to @andonirdgz for the innovative context provider idea!
15382

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

15785
[build-url]: https://img.shields.io/github/checks-status/expatfile/next-runtime-env/main
15886
[cov-img]: https://codecov.io/gh/expatfile/next-runtime-env/branch/main/graph/badge.svg?token=mbGgsweFuP

docs/EXPOSING_CUSTOM_ENV.md

+49-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,56 @@
11
# Exposing custom environment variables 🛠
22

3+
- [Exposing custom environment variables 🛠](#exposing-custom-environment-variables-)
4+
- [Using the script approach (recommend)](#using-the-script-approach-recommend)
5+
- [Example](#example)
6+
- [Using the context approach](#using-the-context-approach)
7+
- [Example](#example-1)
8+
9+
## Using the script approach (recommend)
10+
11+
You might not only want to expose environment variables that are prefixed with `NEXT_PUBLIC_`. In this case you can use the `EnvScript` to expose custom environment variables to the browser.
12+
13+
### Example
14+
15+
```tsx
16+
// app/layout.tsx
17+
// This is as of Next.js 14, but you could also use other dynamic functions
18+
import { unstable_noStore as noStore } from 'next/cache';
19+
import { EnvScript } from 'next-runtime-env';
20+
21+
export default function RootLayout({
22+
children,
23+
}: {
24+
children: React.ReactNode;
25+
}) {
26+
noStore(); // Opt into dynamic rendering
27+
28+
// This value will be evaluated at runtime
29+
return (
30+
<html lang="en">
31+
<head>
32+
<EnvScript
33+
env={{
34+
NEXT_PUBLIC_: process.env.NEXT_PUBLIC_FOO,
35+
BAR: process.env.BAR,
36+
BAZ: process.env.BAZ,
37+
notAnEnvVar: 'not-an-env-var',
38+
}}
39+
/>
40+
</head>
41+
<body>
42+
{children}
43+
</body>
44+
</html>
45+
);
46+
}
47+
```
48+
49+
## Using the context approach
50+
351
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.
452

5-
## Example
53+
### Example
654

755
```tsx
856
// app/layout.tsx

docs/GETTING_STARTED.md

+63
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,68 @@
11
# Getting started 🚀
22

3+
- [Getting started 🚀](#getting-started-)
4+
- [Using the script approach (recommend)](#using-the-script-approach-recommend)
5+
- [Using the context approach](#using-the-context-approach)
6+
7+
We recommend using the script approach, because you can use the environment variables outside the React context. If you intend to stay withing the react context you can use the context approach.
8+
9+
## Using the script approach (recommend)
10+
11+
1. First, install the package into your project:
12+
13+
```bash
14+
npm install next-runtime-env
15+
# or
16+
yarn add next-runtime-env
17+
# or
18+
pnpm install next-runtime-env
19+
```
20+
21+
1. Then add the script to your head in the root layout:
22+
23+
```tsx
24+
// src/app/layout.tsx
25+
import { PublicEnvScript } from 'next-runtime-env';
26+
27+
export default function RootLayout({
28+
children,
29+
}: {
30+
children: React.ReactNode;
31+
}) {
32+
return (
33+
<html lang="en">
34+
<head>
35+
<PublicEnvScript />
36+
</head>
37+
<body>
38+
{children}
39+
</body>
40+
</html>
41+
);
42+
}
43+
```
44+
45+
1. Finally, use `env` utility to access the runtime environment variables any where in your app:
46+
47+
```tsx
48+
import { env } from 'next-runtime-env';
49+
50+
export function MyComponent() {
51+
const NEXT_PUBLIC_FOO = env('NEXT_PUBLIC_FOO');
52+
const NEXT_PUBLIC_BAZ = env('NEXT_PUBLIC_BAZ');
53+
54+
useEffect(() => {
55+
// some api call using NEXT_PUBLIC_BAZ
56+
}, [NEXT_PUBLIC_BAZ]);
57+
58+
return <div>{NEXT_PUBLIC_FOO}</div>;
59+
}
60+
```
61+
62+
That's it! You can now use the next-runtime-env package to access runtime environment variables in your Next.js app.
63+
64+
## Using the context approach
65+
366
1. First, install the package into your project:
467

568
```bash
File renamed without changes.

examples/with-app-router/package.json examples/with-app-router-context/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12-
"@types/node": "20.9.0",
12+
"@types/node": "20.9.2",
1313
"@types/react": "18.2.37",
1414
"@types/react-dom": "18.2.15",
15-
"eslint": "8.53.0",
16-
"eslint-config-next": "14.0.1",
17-
"next": "14.0.1",
15+
"eslint": "8.54.0",
16+
"eslint-config-next": "14.0.3",
17+
"next": "14.0.3",
1818
"next-runtime-env": "link:../..",
1919
"react": "18.2.0",
2020
"react-dom": "18.2.0",

0 commit comments

Comments
 (0)