Production Deployment
Deploy your QwickApps React Framework applications to production with confidence using these deployment guides and best practices.
Overview
QwickApps React Framework applications are standard React applications that can be deployed to any hosting platform. This guide covers optimization strategies, environment configuration, and platform-specific deployment instructions.
Pre-Deployment Checklist
✅ Performance Optimization
- Bundle analysis completed (
npm run build -- --analyze) - Tree shaking verified (no unused imports)
- Images optimized (WebP format with fallbacks)
- CSS minified and compressed
- JavaScript chunked appropriately
✅ Security
- API tokens stored in environment variables
- HTTPS enabled on production domain
- CORS configured correctly
- Content Security Policy (CSP) implemented
- Sensitive data sanitized from client bundle
✅ Configuration
- Environment variables configured
- Data providers configured for production
- Cache TTL values optimized for production traffic
- Error tracking and monitoring enabled
- Analytics integration completed
Environment Configuration
Environment Variables
# Production .env file
REACT_APP_API_URL=https://api.yourdomain.com
REACT_APP_CMS_URL=https://cms.yourdomain.com
REACT_APP_VERSION=$npm_package_version
REACT_APP_BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Sensitive tokens (use platform-specific secret management)
REACT_APP_STRAPI_TOKEN=your-production-token
REACT_APP_ANALYTICS_ID=your-analytics-id
Production Configuration
// src/config/production.ts
export const productionConfig = {
api: {
baseUrl: process.env.REACT_APP_API_URL!,
timeout: 10000,
retries: 3
},
cache: {
defaultTTL: 300000, // 5 minutes in production
maxSize: 200,
enableMetrics: false // Disable in production
},
theme: {
enableDevTools: false,
persistUserPreferences: true
}
};
Build Optimization
Production Build Script
{
"scripts": {
"build:prod": "NODE_ENV=production npm run build",
"build:analyze": "npm run build -- --analyze",
"build:stats": "npm run build -- --stats",
"prebuild": "npm run lint && npm run test"
}
}
Webpack Optimization
// webpack.config.js additions for production
const path = require('path');
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
maxSize: 200000
},
qwickapps: {
test: /[\\/]node_modules[\\/]@qwickapps[\\/]/,
name: 'qwickapps',
chunks: 'all',
priority: 20
}
}
}
}
};
Deployment Platforms
Vercel Deployment
- Install Vercel CLI:
npm i -g vercel
- Configure
vercel.json:
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/static-build",
"config": {
"distDir": "build"
}
}
],
"routes": [
{
"src": "/static/(.*)",
"headers": {
"cache-control": "s-maxage=31536000,immutable"
}
},
{
"src": "/(.*)",
"dest": "/index.html"
}
],
"env": {
"REACT_APP_API_URL": "https://api.yourdomain.com"
}
}
- Deploy:
vercel --prod
Netlify Deployment
- Configure
netlify.toml:
[build]
publish = "build"
command = "npm run build"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
[[headers]]
for = "/static/*"
[headers.values]
cache-control = "max-age=31536000,immutable"
[context.production.environment]
REACT_APP_API_URL = "https://api.yourdomain.com"
- Deploy via Git:
git push origin main # Auto-deploys via Git integration
AWS S3 + CloudFront
- Build and Upload:
# Build application
npm run build
# Upload to S3 (using AWS CLI)
aws s3 sync build/ s3://your-bucket-name --delete
aws cloudfront create-invalidation --distribution-id YOUR_DISTRIBUTION_ID --paths "/*"
- CloudFront Configuration:
{
"OriginPath": "",
"DefaultRootObject": "index.html",
"CustomErrorResponses": [
{
"ErrorCode": 404,
"ResponsePagePath": "/index.html",
"ResponseCode": 200
}
]
}
Docker Deployment
- Create
Dockerfile:
# Build stage
FROM node:18-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Production stage
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
- Configure
nginx.conf:
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
# Handle client-side routing
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets
location /static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}
- Build and Deploy:
docker build -t qwickapps-app .
docker run -p 80:80 qwickapps-app
Database and API Considerations
Data Provider Configuration
// Production data provider setup
import { CachedDataProvider, StrapiDataProvider } from '@qwickapps/schema';
const strapiProvider = new StrapiDataProvider(
process.env.REACT_APP_STRAPI_URL!,
process.env.REACT_APP_STRAPI_TOKEN
);
const productionProvider = new CachedDataProvider(strapiProvider, {
maxSize: 500,
defaultTTL: 600000, // 10 minutes for production
customTTL: {
'pages.*': 1800000, // Pages cache longer
'config.*': 3600000, // Config caches longest
'dynamic.*': 60000 // Dynamic content shorter
}
});
API Rate Limiting
// Implement request throttling
class ThrottledDataProvider implements DataProvider {
private requestQueue: Array<() => Promise<any>> = [];
private processing = false;
private readonly maxConcurrent = 5;
private readonly delayBetweenRequests = 100; // ms
async getData(dataSource: string): Promise<any[]> {
return new Promise((resolve, reject) => {
this.requestQueue.push(async () => {
try {
const result = await this.baseProvider.getData(dataSource);
resolve(result);
} catch (error) {
reject(error);
}
});
this.processQueue();
});
}
private async processQueue() {
if (this.processing) return;
this.processing = true;
while (this.requestQueue.length > 0) {
const batch = this.requestQueue.splice(0, this.maxConcurrent);
await Promise.all(batch.map(request => request()));
if (this.requestQueue.length > 0) {
await new Promise(resolve => setTimeout(resolve, this.delayBetweenRequests));
}
}
this.processing = false;
}
}
Monitoring and Analytics
Error Tracking
// src/utils/errorTracking.ts
export function initializeErrorTracking() {
window.addEventListener('error', (event) => {
console.error('Application Error:', event.error);
// Send to error tracking service
if (process.env.NODE_ENV === 'production') {
sendErrorToService({
message: event.error?.message,
stack: event.error?.stack,
timestamp: new Date().toISOString()
});
}
});
}
Performance Monitoring
// Performance tracking for data binding
const performanceMetrics = {
trackDataBinding: (dataSource: string, duration: number) => {
if (process.env.NODE_ENV === 'production') {
// Send to analytics service
analytics.track('data_binding_performance', {
dataSource,
duration,
timestamp: Date.now()
});
}
}
};
Health Checks
// src/utils/healthCheck.ts
export async function performHealthCheck(): Promise<boolean> {
try {
// Check API connectivity
const apiResponse = await fetch(`${process.env.REACT_APP_API_URL}/health`);
// Check data provider
const testData = await dataProvider.getData('health.check');
// Check theme system
const themeLoaded = document.documentElement.getAttribute('data-theme');
return apiResponse.ok && testData.length >= 0 && themeLoaded !== null;
} catch (error) {
console.error('Health check failed:', error);
return false;
}
}
Security Hardening
Content Security Policy
<!-- Add to index.html -->
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self';
connect-src 'self' https://api.yourdomain.com https://cms.yourdomain.com;
">
Environment Variable Security
# Use platform-specific secret management
# Vercel: vercel env add
# Netlify: netlify env:set
# AWS: Parameter Store or Secrets Manager
# Docker: Docker secrets or env files
# Never commit these to version control
echo "REACT_APP_STRAPI_TOKEN=*" >> .gitignore
API Security
// Implement API key rotation
class SecureApiProvider {
private async getApiKey(): Promise<string> {
const stored = localStorage.getItem('api_key_expiry');
const expiry = stored ? parseInt(stored) : 0;
if (Date.now() > expiry) {
return this.refreshApiKey();
}
return process.env.REACT_APP_API_TOKEN!;
}
private async refreshApiKey(): Promise<string> {
// Implement key refresh logic
const response = await fetch('/api/refresh-token', {
method: 'POST',
credentials: 'include'
});
const { token, expiresIn } = await response.json();
localStorage.setItem('api_key_expiry', (Date.now() + expiresIn).toString());
return token;
}
}
Performance Optimization
Lighthouse Optimization
# Install Lighthouse CI
npm install -g @lhci/cli
# Create lighthouse configuration
# .lighthouserc.js
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000'],
startServerCommand: 'npm run serve',
numberOfRuns: 3
},
assert: {
assertions: {
'categories:performance': ['warn', { minScore: 0.9 }],
'categories:accessibility': ['error', { minScore: 0.9 }]
}
}
}
};
# Run performance audit
lhci autorun
Bundle Analysis
# Analyze bundle composition
npm run build -- --analyze
# Check for duplicate dependencies
npx webpack-bundle-analyzer build/static/js/*.js
# Monitor bundle size over time
npx bundlesize
Troubleshooting
Common Deployment Issues
Build Failures:
# Clear node_modules and package-lock.json
rm -rf node_modules package-lock.json
npm install
npm run build
Environment Variable Issues:
// Verify environment variables are loaded
console.log('Environment:', {
NODE_ENV: process.env.NODE_ENV,
API_URL: process.env.REACT_APP_API_URL,
// Don't log sensitive tokens
});
Routing Issues (404 on refresh):
# Ensure your server handles client-side routing
location / {
try_files $uri $uri/ /index.html;
}
CORS Issues:
// Configure your API server
app.use(cors({
origin: process.env.FRONTEND_URL,
credentials: true
}));
Deployment Checklist
Pre-Launch
- Performance audit completed (Lighthouse score > 90)
- Accessibility audit completed (WCAG AA compliance)
- Security audit completed (CSP, HTTPS, secrets)
- Cross-browser testing completed
- Mobile responsiveness verified
- Error tracking configured
- Analytics integration tested
Launch Day
- DNS configuration verified
- SSL certificates installed
- CDN configuration tested
- Monitoring alerts configured
- Backup and rollback procedures tested
- Performance baselines established
Post-Launch
- Monitor error rates and performance metrics
- Set up automated deployments
- Configure staging environment for testing
- Establish maintenance and update procedures
- Monitor cache hit ratios and optimization opportunities
What's Next?
- Performance Guide - Optimize your application performance
- CMS Integration - Connect to production CMS systems
- Data Binding Guide - Optimize data loading patterns
- Component Development - Build production-ready components