Preview Channels
Test and share your changes before going live. Preview channels create temporary, shareable URLs perfect for stakeholder reviews, QA testing, and feature validation.
What Are Preview Channels?β
Preview channels are temporary hosting environments that:
- Create unique URLs for testing
- Run alongside your production site
- Expire automatically (configurable)
- Perfect for pull request previews
- Support all Hosting features
Example URL: your-project--channel-name-randomhash.web.app
Creating Preview Channelsβ
Basic Usageβ
# Deploy to a preview channel
firebase hosting:channel:deploy preview
# Output:
# β Hosting URL: https://myapp--preview-x8yn3k.web.app
# β Channel URL (expires 2024-12-15): https://myapp--preview-x8yn3k.web.app
Named Channelsβ
Use descriptive names for better organization:
# Feature-specific channel
firebase hosting:channel:deploy new-checkout-flow
# Version-specific channel
firebase hosting:channel:deploy v2-0-0-beta
# PR-specific channel
firebase hosting:channel:deploy pr-123
Setting Expirationβ
# Expires in 7 days (default)
firebase hosting:channel:deploy preview
# Expires in 30 days
firebase hosting:channel:deploy preview --expires 30d
# Expires in 12 hours
firebase hosting:channel:deploy preview --expires 12h
# Expires on specific date
firebase hosting:channel:deploy preview --expires 2024-12-31
Managing Preview Channelsβ
List Active Channelsβ
firebase hosting:channel:list
# Output:
# βββββββββββββββ¬βββββββββββββββββββββββββββββββββ¬ββββββββββββββββββ
# β Channel ID β URL β Expiration β
# βββββββββββββββΌβββββββββββββββββββββββββββββββββΌββββββββββββββββββ€
# β preview β myapp--preview-x8yn3k.web.app β Dec 15, 2024 β
# β feature-authβ myapp--feature-auth-a3b4c5.web.app β Dec 20, 2024 β
# β pr-456 β myapp--pr-456-d6e7f8.web.app β Dec 18, 2024 β
# βββββββββββββββ΄βββββββββββββββββββββββββββββββββ΄ββββββββββββββββββ
Open Channel in Browserβ
# Open specific channel
firebase hosting:channel:open preview
# Opens default browser to channel URL
Delete Channelsβ
# Delete specific channel
firebase hosting:channel:delete preview
# Delete with confirmation skip
firebase hosting:channel:delete preview --force
CI/CD Integrationβ
GitHub Actionsβ
name: Preview Channel on PR
on:
pull_request:
types: [opened, synchronize]
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install and Build
run: |
npm ci
npm run build
- name: Deploy Preview
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT }}'
channelId: pr-${{ github.event.number }}
expires: 7d
- name: Comment PR
uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'π Preview deployed to: ${{ steps.deploy.outputs.url }}'
})
GitLab CIβ
preview:
stage: deploy
script:
- npm ci
- npm run build
- firebase hosting:channel:deploy merge-request-$CI_MERGE_REQUEST_IID --expires 7d
environment:
name: preview/$CI_MERGE_REQUEST_IID
url: https://your-project--merge-request-$CI_MERGE_REQUEST_IID-*.web.app
only:
- merge_requests
Bitbucket Pipelinesβ
pipelines:
pull-requests:
'**':
- step:
name: Deploy Preview
script:
- npm ci
- npm run build
- firebase hosting:channel:deploy pr-$BITBUCKET_PR_ID --expires 7d --token $FIREBASE_TOKEN
- echo "Preview URL available in Firebase Console"
Advanced Usageβ
Multi-Site Preview Channelsβ
# Deploy specific site to preview
firebase hosting:channel:deploy preview --only hosting:app
firebase hosting:channel:deploy preview --only hosting:blog
# Deploy multiple sites
firebase hosting:channel:deploy preview --only hosting:app,hosting:blog
Channel Cloningβ
# Clone preview to another channel
firebase hosting:clone SOURCE:preview TARGET:qa-review
# Promote preview to production
firebase hosting:clone SOURCE:preview TARGET:live
Environment-Specific Buildsβ
// package.json
{
"scripts": {
"build:preview": "REACT_APP_ENV=preview npm run build",
"build:production": "REACT_APP_ENV=production npm run build",
"deploy:preview": "npm run build:preview && firebase hosting:channel:deploy preview",
"deploy:production": "npm run build:production && firebase deploy --only hosting"
}
}
// In your app
const API_URL = process.env.REACT_APP_ENV === 'preview'
? 'https://api-staging.example.com'
: 'https://api.example.com';
Testing Strategiesβ
QA Testing Workflowβ
-
Deploy to preview channel
firebase hosting:channel:deploy qa-sprint-15 --expires 14d
-
Share with QA team
- Send preview URL
- Include test credentials
- Note expiration date
-
Iterate on feedback
# Redeploy same channel with fixes
firebase hosting:channel:deploy qa-sprint-15 -
Promote when approved
firebase hosting:clone myapp:qa-sprint-15 myapp:live
A/B Testingβ
// Simple client-side A/B test using preview channels
const isTestGroup = Math.random() < 0.5;
const baseUrl = isTestGroup
? 'https://myapp--new-design-x8yn3k.web.app'
: 'https://myapp.web.app';
// Track metrics for each version
analytics.track('page_view', {
version: isTestGroup ? 'new-design' : 'current'
});
Feature Flags with Preview Channelsβ
// feature-flags.js
const FEATURES = {
newCheckout: window.location.hostname.includes('--new-checkout-'),
darkMode: window.location.hostname.includes('--dark-mode-'),
betaFeatures: window.location.hostname.includes('--beta-')
};
// Usage
if (FEATURES.newCheckout) {
renderNewCheckout();
} else {
renderLegacyCheckout();
}
Collaboration Featuresβ
Stakeholder Reviewsβ
Create dedicated channels for different stakeholders:
# For design review
firebase hosting:channel:deploy design-review --expires 7d
# For client preview
firebase hosting:channel:deploy client-demo --expires 30d
# For internal testing
firebase hosting:channel:deploy internal-qa --expires 3d
Feedback Collectionβ
Embed feedback tools in preview channels:
<!-- Only show in preview channels -->
<script>
if (window.location.hostname.includes('--')) {
// Load feedback widget
const script = document.createElement('script');
script.src = 'https://feedback-tool.com/widget.js';
document.head.appendChild(script);
}
</script>
Performance Testingβ
Load Testing Preview Channelsβ
# Deploy performance test version
firebase hosting:channel:deploy perf-test --expires 1d
# Run load tests against preview URL
artillery quick --count 100 --num 10 \
https://myapp--perf-test-x8yn3k.web.app/
Lighthouse CIβ
# .github/workflows/lighthouse.yml
- name: Run Lighthouse
uses: treosh/lighthouse-ci-action@v9
with:
urls: |
${{ steps.deploy.outputs.url }}
${{ steps.deploy.outputs.url }}/products
${{ steps.deploy.outputs.url }}/checkout
uploadArtifacts: true
Security Considerationsβ
Access Controlβ
Preview channels are publicly accessible. For sensitive previews:
-
Use obscure channel names
firebase hosting:channel:deploy $(openssl rand -hex 12)
-
Implement client-side auth
// Simple password protection
if (window.location.hostname.includes('--')) {
const password = prompt('Enter preview password:');
if (password !== 'SECRET_PREVIEW_PASS') {
window.location.href = 'https://example.com';
}
} -
Short expiration times
firebase hosting:channel:deploy sensitive-preview --expires 1h
Data Protectionβ
// Use different data in previews
const isPreview = window.location.hostname.includes('--');
const API_ENDPOINT = isPreview
? 'https://api-staging.example.com' // Test data
: 'https://api.example.com'; // Production data
Troubleshootingβ
Common Issuesβ
Issue | Cause | Solution |
---|---|---|
"Channel not found" | Channel expired | Redeploy with new channel |
"Permission denied" | Not authenticated | Run firebase login |
URL not updating | Browser cache | Hard refresh (Ctrl+F5) |
Build differences | Env variables | Check build configuration |
Slow deployments | Large files | Optimize assets |
Debug Commandsβ
# Check channel details
firebase hosting:channel:list
# View deployment logs
firebase hosting:channel:deploy preview --debug
# Compare with production
diff -r ./build ./build-production
Best Practicesβ
1. Naming Conventionsβ
# Good channel names
pr-123 # Pull request number
feature-auth # Feature name
v2-beta # Version
sprint-15 # Sprint number
client-review # Purpose
# Avoid
test # Too generic
preview # Not descriptive
john-test # Personal names
2. Cleanup Strategyβ
# Automated cleanup script
#!/bin/bash
firebase hosting:channel:list --json | \
jq -r '.result[].name' | \
grep -E '^pr-[0-9]+$' | \
xargs -I {} firebase hosting:channel:delete {} --force
3. Documentationβ
Always document preview channels in PRs:
## Preview Channel
π **Preview URL**: https://myapp--pr-123-x8yn3k.web.app
**Expires**: Dec 31, 2024
**What to test**:
- [ ] New checkout flow
- [ ] Mobile responsive design
- [ ] Payment integration
**Known issues**:
- Analytics disabled in preview
- Using staging API endpoints
Cost Optimizationβ
Preview Channel Costsβ
- Storage: Counts toward 10GB limit
- Bandwidth: Standard rates apply
- Channels: No per-channel cost
Cost-Saving Tipsβ
-
Set appropriate expiration
# Short-lived for quick reviews
--expires 1d
# Longer for QA cycles
--expires 7d -
Clean up regularly
# Delete after PR merge
firebase hosting:channel:delete pr-$PR_NUMBER -
Share channels
- Reuse channels for similar features
- Update existing channels vs creating new
Next Stepsβ
- Set up GitHub Integration for automatic previews
- Configure Local Testing environment
- Learn about Hosting Management
- Implement Monitoring for channels
Pro Tip: Make preview channels part of your standard workflow. They're free to create and invaluable for catching issues before production. Every PR should have a preview! π