Skip to content

Commit

Permalink
feat: env vars
Browse files Browse the repository at this point in the history
- add env vars setup
- add debug helper
- update readme
  • Loading branch information
denchiklut committed Mar 5, 2023
1 parent e18ee7f commit 8d89680
Show file tree
Hide file tree
Showing 14 changed files with 93 additions and 10 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DEBUG=APP:*
EXAMPLE_HOST=https://jsonplaceholder.typicode.com
18 changes: 18 additions & 0 deletions @types/env/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,21 @@ declare const IS_DEV: boolean
declare const IS_PROD: boolean
declare const IS_SERVER: boolean
declare const IS_SPA: boolean


type ENV_KEYS =
| 'DEBUG'
| 'NODE_ENV'
| 'EXAMPLE_HOST'

type ENV_VARS = Partial<Collection<ENV_KEYS, string>>

namespace NodeJS {
interface Process {
env: ENV_VARS
}
}

interface Window {
env_vars: ENV_VARS
}
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ You can use this project as a boilerplate for your SSR applications. Feel free t
- [x] `SPA` mode
- [x] `Webpack 5`
- [x] `React 18`
- [x] `Polyfills`

## Startup project

Expand All @@ -23,7 +24,29 @@ Before starting work with the project, run the command:
yarn install
```

### Step 2. Starting the project
### Step 2. Environment variables

Add `.env` file based on `.env.example`

#### Adding new `env` variable

1. Add it to `.env` file
2. Add it\`s name to `@types/env/index.d.ts` (for TS)
3. If this variable needs to be accessible from both `client` & `server` add it\`s name to
`setEnvVars` function in `common/env/env.util`
4. You can access this variable via `getEnvVars` function.
This function will return a proper value based on environment & log a message if variable is not defined.

#### Global variables

Note that additionally there will be few useful `global variables` available for you.

- IS_DEV
- IS_PROD
- IS_SERVER
- IS_SPA

### Step 3. Starting the project

To start the project in **SSR** mode, run the command

Expand Down
1 change: 1 addition & 0 deletions config/spec/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ import '@testing-library/jest-dom'

window.IS_SERVER = false
window.IS_DEV = false
window.IS_SPA = true
1 change: 1 addition & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default {
'^src/(.*)$': '<rootDir>/src/$1',
'^client/(.*)$': '<rootDir>/src/client/$1',
'^server/(.*)$': '<rootDir>/src/server/$1',
'^common/(.*)$': '<rootDir>/src/common/$1',
'^components/(.*)': '<rootDir>/src/client/components/$1',
'^@shared/(.*)': '<rootDir>/src/client/components/@shared/$1',
'^pages/(.*)$': '<rootDir>/src/client/pages/$1',
Expand Down
4 changes: 4 additions & 0 deletions src/client/components/home/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { useState } from 'react'
import { getDebugger, getEnvVars } from 'src/common'
import css from './styles.scss'

const debug = getDebugger('component: Home')
export const Home = () => {
const [count, setCount] = useState(0)
const exampleHost = getEnvVars('EXAMPLE_HOST')
debug('example host %s', exampleHost)

return (
<div className={css.wrapper}>
Expand Down
8 changes: 8 additions & 0 deletions src/common/debugger/debugger.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import debugLib from 'debug'

const debug = process.env.DEBUG

if (debug) debugLib.enable(debug)
else debugLib.disable()

export const getDebugger = (debugLabel: string) => debugLib(`APP:${debugLabel}`)
1 change: 1 addition & 0 deletions src/common/debugger/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './debugger.util'
22 changes: 22 additions & 0 deletions src/common/env/env.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { getDebugger } from 'common/debugger'

export const setEnvVars = (nonce?: string) => {
const envVars: ENV_VARS = {
DEBUG: process.env.DEBUG,
NODE_ENV: process.env.NODE_ENV,
EXAMPLE_HOST: process.env.EXAMPLE_HOST
}

return `<script nonce='${nonce}'>window.env_vars = ${JSON.stringify(envVars)}</script>`
}

export const getEnvVars = (variable: ENV_KEYS, initial = '') => {
const debug = getDebugger('common:env.util')
const source = IS_SERVER || IS_SPA ? process.env : window.env_vars

if (!(variable in source)) {
debug('%s is not defined', variable)
}

return source[variable] ?? initial
}
1 change: 1 addition & 0 deletions src/common/env/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './env.util'
2 changes: 2 additions & 0 deletions src/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './debugger'
export * from './env'
6 changes: 4 additions & 2 deletions src/server/middleware/render/render.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { RouteObject } from 'react-router-dom'
import type { ServerResponse } from 'webpack-dev-middleware'
import type { ChunkExtractor, ChunkExtractorOptions } from '@loadable/server'
import requireFromString from 'require-from-string'
import { setEnvVars } from 'common/env'

export const getHtml = (reactHtml: string, chunkExtractor: ChunkExtractor) => {
const scriptTags = chunkExtractor.getScriptTags()
Expand All @@ -16,10 +17,11 @@ export const getHtml = (reactHtml: string, chunkExtractor: ChunkExtractor) => {
<head>
<meta charset='UTF-8'>
<title>SSR app</title>
<link rel='icon' href='/favicon.ico' />
<meta content='width=device-width, initial-scale=1' name='viewport' />
<link rel='icon' href='/favicon.ico' />
<meta content='width=device-width, initial-scale=1' name='viewport' />
${linkTags}
${styleTags}
${setEnvVars()}
</head>
<body>
<div id='root'>${reactHtml}</div>
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"src/*": ["src/*"],
"server/*": ["src/server/*"],
"client/*": ["src/client/*"],
"errors/*": ["src/client/errors/*"],
"common/*": ["src/common/*"],
"components/*": ["src/client/components/*"],
"@shared/*": ["src/client/components/@shared/*"],
"pages/*": ["src/client/pages/*"],
Expand Down
10 changes: 4 additions & 6 deletions webpack/plugins/define.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ interface Props {
}

dotenv.config()
const config = (isServer: boolean, spa: boolean) => ({
IS_SERVER: isServer,
const config = (IS_SERVER: boolean, IS_SPA: boolean) => ({
IS_SERVER,
IS_DEV,
IS_PROD,
IS_SPA: spa,
'process.env': {
DEBUG: JSON.stringify(process.env.DEBUG)
}
IS_SPA,
'process.env': JSON.stringify(process.env)
})

export const definePlugin = ({ server = false, spa = false }: Props = {}) =>
Expand Down

0 comments on commit 8d89680

Please sign in to comment.