Bundlers
Webpack Plugin
Using Clientshell with Webpack.
Installation
pnpm add -D @clientshell/webpack @clientshell/cliThe Webpack Flow
Because Webpack config (webpack.config.cjs) usually runs in pure Node.js (CommonJS), we shouldn't attempt to require the TypeScript (.ts) schema file directly inside the Webpack config.
Instead, we use the clientshell CLI to compile the schema into a JSON manifest first, before Webpack runs.
1. Update Scripts
Update your package.json to generate the JSON file using the CLI (--import tsx ensures Node.js can interpret .ts correctly).
{
"scripts": {
"manifest": "node --import tsx ./node_modules/@clientshell/cli/bin/clientshell.js manifest --schema src/env.schema.ts --output clientshell.manifest.json",
"build": "pnpm manifest && webpack --config webpack.config.cjs",
"dev": "pnpm manifest && webpack serve --config webpack.config.cjs"
}
}2. Setup Webpack
Point the Webpack plugin directly to your pre-generated manifest JSON file!
// webpack.config.cjs
const { ClientshellWebpackPlugin } = require("@clientshell/webpack");
module.exports = {
// ... other config ...
plugins: [
new ClientshellWebpackPlugin({
manifestPath: "./clientshell.manifest.json",
// Values to return in Development stubs
devValues: {
API_URL: "http://localhost:3000",
},
}),
],
};What it does
- Build (
mode: "production"): Copiesclientshell.manifest.jsoninto your Webpack output directory (e.g.,dist/). - Dev (
mode: "development"): Writes a stubenv-config.jsto the output directory using the defaults in your manifest, overlaid with your provideddevValues.
Docker Deployment
When deploying a Webpack app, ensure your Dockerfile runs the manifest step before or as part of the build.
# 1. Build Layer
FROM node:20-alpine AS builder
WORKDIR /app
COPY . .
# Ensure pnpm is installed and run pnpm build
# (which should be "pnpm manifest && webpack")
RUN npm install -g pnpm && pnpm install && pnpm build
# 2. Production Layer
FROM clientshell
COPY --from=builder /app/dist /app/distThe Go injector will look for /app/dist/clientshell.manifest.json inside the container at startup.
