Webpack compiler placeholders
This week I learned how to inject environment variables into a web app using Webpack.
Story
Let’s say you have built a Single Page Application (SPA) app using react-boilerplate
development tool and are ready to deploy it on an SPA enabled server.
NOTE that this app uses connected-react-router
for client routing.
- During build process,
react-boilerplate
serves your app onhttp://localhost:3000
- However, the SPA enabled server, will serve your app on
https://<host>/web-app
Inject node environmental variables into our source code.
// internals/webpack/webpack.base.babel.js// ...output: Object.assign(
{
path: path.resolve(process.cwd(), 'build'),
publicPath: process.env.PUBLIC_PATH || '/',
},
options.output,
),// ...plugins: options.plugins.concat([// ...
new webpack.EnvironmentPlugin({
NODE_ENV: 'development',
PUBLIC_PATH: '/',
}),
// ...]),
PUBLIC_PATH
tells Webpack how to create asset urls.
Make use of injected variables
// app/utils/history.jsimport createHistory from 'history/createBrowserHistory';const { PUBLIC_PATH: basename }= process.env;const history = createHistory({ basename });export default history;
Many other development tools use this process to turn on/off redux devtools
as show in image below.
Create a production build
npx cross-env NODE_ENV=production PUBLIC_PATH='/web-app/' webpack --config internals/webpack/webpack.prod.babel.js
Now whenever users visit https://<host>/web-app
, the routing library will recognize /web-app/
as the root path.
Why compile placeholders?
These environment variables are considered “compile placeholders” due to how Webpack treats them.
During compilation process, Webpack DOES NOT assign basename to the value help by
PUBLIC_PATH
but instead replaces the wholeprocess.env.PUBLIC_PATH
word with the string version of the value held byPUBLIC_PATH
Check this Webpack page for more information.
Usage:
- Deploying a single page app on Github pages