Skip to content

Commit f218ece

Browse files
committed
Embed env vars in ssr build, improve readme
1 parent ad6619f commit f218ece

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,23 @@ If `src/index.ssr.js` exports a function called `devServerHandler`, it will be i
5050
### Relative Urls, PUBLIC_URL and BASE_HREF
5151
`create-react-app` provides a variable called `PUBLIC_URL`, which is accessible via `process.env.PUBLIC_URL` in JavaScript or by using the placeholder `%PUBLIC_URL%` in HTML to reference assets. This variable is determined at **compile time** and must be specified before compilation, which makes your compiled web app dependant on the specified location.
5252

53-
For projects with server-side rendering however, there is another, possibly better way to deal with this. Instead of hardcoding the public url, HTML assets can be referenced with a relative url and the server-side renderer can read a specified base url at **runtime** and render it into a base tag. `react-scripts-with-ssr` supports using `PUBLIC_URL` but recommends the described approach using the `BASE_HREF` environment variable:
53+
For projects with server-side rendering however, there is another way to deal with this. Instead of hardcoding the public url, HTML assets can be referenced with a relative url and the server-side renderer can read a specified base url at **runtime** and render it into a base tag. `react-scripts-with-ssr` supports using `PUBLIC_URL` but also allows the `BASE_HREF` approach:
5454
* Define a `BASE_HREF` environment variable in your server runtime environment containing your base url (e.g. `https://example.com/folder`).
5555
* Add `<base href="%BASE_HREF%/" />` to your index.html template. Notice the trailing slash.
5656
* Replace `%BASE_HREF%` with the value of `process.env.BASE_HREF` in your server-side request handler.
5757
* Make all asset references in HTML relative. Do not use `%PUBLIC_URL%` in URLs or server-relative URLs (e.g. `/some/url`).
5858
* Make the build scripts emit relative paths by providing `PUBLIC_URL` as environment variable with the value `.` during compile time or setting the `homepage` field in `package.json` to `.`.
5959
* If you need access to BASE_HREF in JavaScript, read it from `document.getElementsByTagName("base")[0].href;`.
6060

61-
### Using runtime environment variables on the client
61+
### Environment variables
6262

63-
`create-react-app` provides `process.env` on the client-side to access environment variables prefixed with REACT_APP and defined at **compile time**.
63+
`create-react-app` embeds environment variables prefixed with REACT_APP in the build during **compile time** and provides them with a simulated `process.env` object using Webpack's DefinePlugin.
6464

65-
However, if you want to make your server's **runtime** environment variables available on the client-side, you can do this with a `clientEnv` variable:
65+
While embedding is necessary on the client-side, the ssr request handler runs in a Node.js context with real environment variables. `react-scripts-with-ssr` allows accessing external environment variables in the ssr request handler during **runtime**. However, all variables contained in the client-side build are also embedded into the ssr request handler as default values if they are not provided by the runtime environment.
66+
67+
If you want to make your server's **runtime** environment variables available on the client-side, you can do this with a `clientEnv` variable:
6668
* Add a variable assignment script `<script>clientEnv=%CLIENT_ENV%</script>` to the head section in `public/index.html`.
67-
* Replace the placeholder in the ssr request handler with `.replace(/%CLIENT_ENV%/g, JSON.stringify({ FOO: 'bar' }))`.
69+
* Replace the placeholder in the ssr request handler with `.replace(/%CLIENT_ENV%/g, JSON.stringify({ FOO: process.env.FOO }))`.
6870
* Access the value on the client-side with `clientEnv.FOO`.
6971
* For TypeScript: Declare the global variable `declare const clientEnv: NodeJS.ProcessEnv;`.
7072

config/webpack.ssr.config.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,23 @@ module.exports = function (webpackEnv) {
4040
[
4141
// do not generate an additional index.html for ssr
4242
HtmlWebpackPlugin,
43-
// avoid shadowing of process.env for ssr handler
43+
// avoid overriding process.env on the server, we will provide a customized DefinePlugin
4444
webpack.DefinePlugin
4545
].every(pluginClass => !(plugin instanceof pluginClass))
46-
),
46+
).concat([
47+
// modified version of the DefinePlugin that does not override but extend process.env
48+
// this will preserve embedded env vars but also allow reading real env vars on the server
49+
new webpack.DefinePlugin(
50+
Object.keys(env.raw).reduce(
51+
(newEnv, key) => ({
52+
...newEnv,
53+
// this will result in s.th. like: process.env.FOO = process.env.FOO || "embedded default value"
54+
['process.env.' + key]: 'process.env.' + key + '||' + JSON.stringify(env.raw[key])
55+
}),
56+
{}
57+
)
58+
)
59+
]),
4760
externals: [nodeExternals()]
4861
},
4962
// client compiler config

0 commit comments

Comments
 (0)