Some checks failed
Build and Push to Harbor / build-and-push (push) Has been cancelled
- Created detailed best practices guide for Godot HTML5/Web exports - Removed empty stub files (they mask problems rather than solving them) - Kept favicon.ico as it's a legitimate browser requirement - Guide covers export config, optimization, deployment, and troubleshooting
448 lines
11 KiB
Markdown
448 lines
11 KiB
Markdown
# Godot HTML5 Export Best Practices Guide
|
|
|
|
A comprehensive guide for exporting Godot games to HTML5/Web and deploying them properly.
|
|
|
|
## Table of Contents
|
|
- [Pre-Export Checklist](#pre-export-checklist)
|
|
- [Export Configuration](#export-configuration)
|
|
- [Post-Export Optimization](#post-export-optimization)
|
|
- [Deployment Best Practices](#deployment-best-practices)
|
|
- [Common Issues & Solutions](#common-issues--solutions)
|
|
- [Security Considerations](#security-considerations)
|
|
|
|
---
|
|
|
|
## Pre-Export Checklist
|
|
|
|
### 1. Set Project Icon
|
|
**Location:** `Project → Project Settings → Application → Config → Icon`
|
|
|
|
```
|
|
✅ Use a square PNG image (ideally 512x512 or 1024x1024)
|
|
✅ Godot will auto-generate smaller sizes (16x16, 32x32, etc.)
|
|
✅ This icon becomes your favicon and app icons
|
|
```
|
|
|
|
**Why:** Prevents 404 errors for `/favicon.ico` and provides proper branding.
|
|
|
|
### 2. Configure Export Presets
|
|
**Location:** `Project → Export → Add → HTML5`
|
|
|
|
#### Essential Settings:
|
|
```
|
|
Export Type: Regular (or Threads if you need SharedArrayBuffer)
|
|
Export With Debug: OFF for production
|
|
Texture Format: Compress for Smaller Downloads
|
|
```
|
|
|
|
#### Head Include (Optional):
|
|
Only add custom meta tags if needed:
|
|
```html
|
|
<meta name="description" content="Your game description">
|
|
<meta name="keywords" content="game, webgl, godot">
|
|
<meta name="author" content="Your Name">
|
|
```
|
|
|
|
### 3. Audio Configuration
|
|
**Location:** `Project → Project Settings → Audio`
|
|
|
|
```
|
|
✅ Mix Rate: 44100 Hz (standard web audio)
|
|
✅ Output Latency: 15ms (balance between quality and performance)
|
|
✅ Enable Audio Input: Only if needed (requires user permissions)
|
|
```
|
|
|
|
### 4. Display Settings
|
|
**Location:** `Project → Project Settings → Display → Window`
|
|
|
|
```
|
|
✅ Size: Set your target resolution (e.g., 1920x1080)
|
|
✅ Resizable: Enable if you want responsive sizing
|
|
✅ Stretch Mode: "2d" or "viewport" for web games
|
|
✅ Stretch Aspect: "expand" or "keep" based on your needs
|
|
```
|
|
|
|
---
|
|
|
|
## Export Configuration
|
|
|
|
### Recommended HTML5 Export Settings
|
|
|
|
#### 1. **Vram Texture Compression**
|
|
Enable both formats for maximum compatibility:
|
|
```
|
|
✅ For Desktop: s3tc (DXT1/DXT5)
|
|
✅ For Mobile: etc2 (or astc if targeting newer devices)
|
|
```
|
|
|
|
#### 2. **Custom HTML Shell**
|
|
Leave default unless you need:
|
|
- Custom loading screens
|
|
- Analytics integration
|
|
- Special PWA features
|
|
|
|
#### 3. **Export Mode**
|
|
- **Release:** Production builds (optimized, no debug symbols)
|
|
- **Debug:** Development builds (larger, has debug info)
|
|
|
|
### 4. **Progressive Web App (PWA)**
|
|
Enable if you want installable web apps:
|
|
```
|
|
Export → HTML5 → Progressive Web App: ON
|
|
Offline Page: Enable for offline support
|
|
Icon Sizes: Godot auto-generates these
|
|
```
|
|
|
|
---
|
|
|
|
## Post-Export Optimization
|
|
|
|
### 1. File Size Optimization
|
|
|
|
#### Compress WASM Files
|
|
The `.wasm` file is usually the largest. Use Brotli or Gzip:
|
|
|
|
```bash
|
|
# Using Brotli (best compression)
|
|
brotli -9 YourGame.wasm
|
|
|
|
# Using Gzip (better compatibility)
|
|
gzip -9 YourGame.wasm
|
|
```
|
|
|
|
#### Nginx Configuration:
|
|
```nginx
|
|
# Enable compression for Godot files
|
|
gzip on;
|
|
gzip_types application/wasm application/javascript text/html;
|
|
gzip_min_length 1000;
|
|
|
|
# Better: Use Brotli
|
|
brotli on;
|
|
brotli_types application/wasm application/javascript text/html;
|
|
```
|
|
|
|
### 2. Caching Strategy
|
|
|
|
```nginx
|
|
# Cache static assets aggressively
|
|
location ~* \.(wasm|js|pck)$ {
|
|
expires 1y;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
|
|
# Cache images
|
|
location ~* \.(png|jpg|jpeg|gif|ico)$ {
|
|
expires 1y;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
|
|
# Don't cache the HTML file
|
|
location ~* \.html$ {
|
|
expires -1;
|
|
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
|
}
|
|
```
|
|
|
|
### 3. Required HTTP Headers
|
|
|
|
For SharedArrayBuffer/Threads support:
|
|
```nginx
|
|
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
|
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
|
```
|
|
|
|
**Note:** These are already in your nginx.conf - good job!
|
|
|
|
---
|
|
|
|
## Deployment Best Practices
|
|
|
|
### 1. Directory Structure
|
|
|
|
```
|
|
your-game/
|
|
├── index.html # Main entry (or YourGame.html)
|
|
├── YourGame.js # Godot engine
|
|
├── YourGame.wasm # Compiled game
|
|
├── YourGame.pck # Game assets
|
|
├── YourGame.worker.js # Service worker
|
|
├── YourGame.icon.png # Favicon/Icon
|
|
├── favicon.ico # Browser favicon (convert from icon)
|
|
├── manifest.json # PWA manifest
|
|
└── assets/ # Optional: separate assets folder
|
|
```
|
|
|
|
### 2. Serving Files
|
|
|
|
#### Option A: Simple HTTP Server (Development)
|
|
```bash
|
|
# Python 3
|
|
python3 -m http.server 8000
|
|
|
|
# Python 2
|
|
python -m SimpleHTTPServer 8000
|
|
|
|
# Node.js (http-server)
|
|
npx http-server -p 8000
|
|
```
|
|
|
|
#### Option B: Production (Nginx/Caddy)
|
|
Use your current Kubernetes deployment approach.
|
|
|
|
### 3. HTTPS Requirement
|
|
|
|
Modern browsers require HTTPS for:
|
|
- SharedArrayBuffer (threads)
|
|
- Service Workers (offline)
|
|
- WebGL 2.0 features
|
|
- Clipboard API
|
|
- Gamepad API
|
|
|
|
**Your setup already has this via cert-manager + Let's Encrypt ✅**
|
|
|
|
---
|
|
|
|
## Common Issues & Solutions
|
|
|
|
### Issue 1: "SharedArrayBuffer is not defined"
|
|
|
|
**Cause:** Missing CORS headers or HTTP (not HTTPS)
|
|
|
|
**Solution:**
|
|
```nginx
|
|
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
|
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
|
```
|
|
|
|
### Issue 2: Blank Screen or "Failed to load"
|
|
|
|
**Debug Steps:**
|
|
1. Open browser DevTools (F12)
|
|
2. Check Console for errors
|
|
3. Check Network tab for failed requests
|
|
|
|
**Common Causes:**
|
|
- Missing files (check all exports completed)
|
|
- Wrong MIME types
|
|
- File path mismatches (case-sensitive on Linux)
|
|
|
|
**Solution:** Verify nginx MIME types:
|
|
```nginx
|
|
types {
|
|
application/wasm wasm;
|
|
application/javascript js;
|
|
text/html html;
|
|
}
|
|
```
|
|
|
|
### Issue 3: Audio Not Playing
|
|
|
|
**Cause:** Browsers require user interaction before playing audio
|
|
|
|
**Solution:** In Godot, show a "Click to Start" screen:
|
|
```gdscript
|
|
func _ready():
|
|
# Don't autoplay audio
|
|
# Wait for user input first
|
|
pass
|
|
|
|
func _on_start_button_pressed():
|
|
$AudioStreamPlayer.play()
|
|
```
|
|
|
|
### Issue 4: Poor Performance
|
|
|
|
**Optimization Tips:**
|
|
1. **Reduce Draw Calls:** Batch sprites, use TileMaps
|
|
2. **Optimize Shaders:** Simple shaders = better performance
|
|
3. **Texture Compression:** Use compressed textures
|
|
4. **Object Pooling:** Reuse nodes instead of creating/destroying
|
|
5. **Profile:** Use Godot's built-in profiler
|
|
|
|
### Issue 5: Large File Sizes
|
|
|
|
**Solutions:**
|
|
1. **Enable Compression:** Gzip/Brotli on server
|
|
2. **Optimize Assets:**
|
|
- Convert PNGs to WebP
|
|
- Compress audio (OGG Vorbis instead of WAV)
|
|
- Use texture compression
|
|
3. **Lazy Loading:** Load assets on-demand, not all at startup
|
|
4. **Asset Streaming:** Use Godot's asset streaming features
|
|
|
|
---
|
|
|
|
## Security Considerations
|
|
|
|
### 1. Content Security Policy (CSP)
|
|
|
|
If you need CSP headers:
|
|
```nginx
|
|
# Relaxed CSP for Godot games
|
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'unsafe-inline'; worker-src 'self' blob:; connect-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';" always;
|
|
```
|
|
|
|
### 2. X-Frame-Options
|
|
|
|
Prevent clickjacking:
|
|
```nginx
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
```
|
|
|
|
**Your nginx.conf already has this ✅**
|
|
|
|
### 3. Input Validation
|
|
|
|
If your game has:
|
|
- User-generated content
|
|
- Multiplayer features
|
|
- External data loading
|
|
|
|
**Always validate and sanitize inputs!**
|
|
|
|
---
|
|
|
|
## Testing Checklist
|
|
|
|
Before deploying to production:
|
|
|
|
### Browser Compatibility
|
|
- [ ] Chrome/Chromium (Latest)
|
|
- [ ] Firefox (Latest)
|
|
- [ ] Safari (Latest)
|
|
- [ ] Edge (Latest)
|
|
- [ ] Mobile browsers (iOS Safari, Chrome Mobile)
|
|
|
|
### Performance Testing
|
|
- [ ] Load time < 10 seconds on 3G
|
|
- [ ] 60 FPS on target hardware
|
|
- [ ] Memory usage stable over time
|
|
- [ ] No memory leaks after extended play
|
|
|
|
### Functionality Testing
|
|
- [ ] Audio works (after user interaction)
|
|
- [ ] Input (keyboard, mouse, touch, gamepad)
|
|
- [ ] Fullscreen mode works
|
|
- [ ] Save/Load functionality
|
|
- [ ] All game mechanics work as expected
|
|
|
|
### Accessibility
|
|
- [ ] Works without sound (visual feedback)
|
|
- [ ] Keyboard-only controls (if applicable)
|
|
- [ ] Colorblind-friendly (if applicable)
|
|
|
|
---
|
|
|
|
## Advanced: Custom Docker Build
|
|
|
|
For building in CI/CD (like your Kaniko setup):
|
|
|
|
### Dockerfile Example:
|
|
```dockerfile
|
|
FROM nginx:alpine
|
|
|
|
# Copy game files
|
|
COPY htlm/ /usr/share/nginx/html/
|
|
|
|
# Copy custom nginx config
|
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
|
|
# Set proper permissions
|
|
RUN chown -R nginx:nginx /usr/share/nginx/html
|
|
|
|
# Expose port
|
|
EXPOSE 8080
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=3s \
|
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1
|
|
```
|
|
|
|
### nginx.conf (Your current one is excellent):
|
|
```nginx
|
|
server {
|
|
listen 8080;
|
|
server_name _;
|
|
|
|
root /usr/share/nginx/html;
|
|
index YourGame.html;
|
|
|
|
# Compression
|
|
gzip on;
|
|
gzip_types application/wasm application/javascript text/html;
|
|
|
|
# CORS for SharedArrayBuffer
|
|
add_header Cross-Origin-Embedder-Policy "require-corp" always;
|
|
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
|
|
|
# Security headers
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
|
|
# Caching
|
|
location ~* \.(wasm|js|pck)$ {
|
|
expires 1y;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Resources
|
|
|
|
### Official Documentation
|
|
- [Godot HTML5 Export Docs](https://docs.godotengine.org/en/stable/tutorials/export/exporting_for_web.html)
|
|
- [Godot Web Editor](https://editor.godotengine.org/)
|
|
|
|
### Tools
|
|
- [Godot Web Export Validator](https://pwa-directory.appspot.com/)
|
|
- [WebPageTest](https://www.webpagetest.org/) - Performance testing
|
|
- [Lighthouse](https://developers.google.com/web/tools/lighthouse) - PWA audit
|
|
|
|
### Community
|
|
- [Godot Forums - HTML5 Export](https://godotengine.org/community)
|
|
- [r/godot](https://reddit.com/r/godot)
|
|
|
|
---
|
|
|
|
## Your Current Setup Analysis
|
|
|
|
### What You're Doing Right ✅
|
|
1. **Proper CORS Headers** for SharedArrayBuffer
|
|
2. **Security Headers** (X-Frame-Options, X-Content-Type-Options)
|
|
3. **Compression** enabled (gzip)
|
|
4. **Proper MIME types** for .wasm files
|
|
5. **Cache headers** for static assets
|
|
6. **Service Worker** for offline support
|
|
7. **GitOps deployment** with Flux
|
|
8. **Container orchestration** with Kubernetes
|
|
|
|
### Recommendations
|
|
1. ✅ **Keep the favicon.ico** (converted from your icon)
|
|
2. ❌ **Don't create empty stub files** for scanner requests
|
|
3. ✅ **Monitor logs** but ignore 404s for files your app doesn't use
|
|
4. ✅ **Consider adding** a robots.txt to reduce scanner noise
|
|
5. ✅ **Consider adding** rate limiting to prevent abuse
|
|
|
|
### About Those 404 Errors
|
|
The files being requested (`support_parent.css`, `twint_ch.js`, `lkk_ch.js`) are:
|
|
- **Not part of Godot exports**
|
|
- **Not needed by your game**
|
|
- **Requested by bots/scanners** looking for e-commerce vulnerabilities
|
|
- **Safe to ignore** - they don't affect your game
|
|
|
|
**Best Practice:** Monitor real errors, ignore scanner noise in logs.
|
|
|
|
---
|
|
|
|
## License
|
|
This guide is provided as-is for educational purposes.
|
|
Feel free to adapt for your own projects.
|
|
|
|
---
|
|
|
|
**Last Updated:** November 2025
|
|
**Godot Version:** 4.x (applicable to 3.x with minor changes)
|