Uncle Sam's Blog Restructuring Journey: A Full-Stack Upgrade from Django to Gin + Vue.ts
Introduction: The Metamorphosis from Python to Go
After months of refactoring and optimizing, my blog has finally completed a gorgeous turnaround from Django to the Go tech stack!
I remember that in early 2024, I was still maintaining a Django-based blogging system - originally an open-source project called "Maple Knows", and the second version was developed on DRF+Vue.js after understanding the first version. However, the architecture of dynamically typed languages is used in both the front and backend, which makes subsequent maintenance gradually difficult and function iterations become more and more slow.
coincided with a full shift to Golang in the company's technology stack, and I decided to take this opportunity to completely refactor the project in Go.
Today, the newly upgraded Uncle Sam blog system has been officially launched. This is a modern front-end and back-end separation architecture based on Gin + Vue.ts + MySQL + Redis + ES + COS, which not only achieves a leapfrog improvement in performance, but also qualitatively improves scalability and maintainability.
New Architecture Technology Stack
Backend Engine: Gin High Performance Framework
go
Gin route definition and middleware usage example
func main() {
r := gin. Default()
Integrated Redis caching middleware (reduces database access pressure)
r.Use(redisMiddleware())
Article Routing Group (API Versioning Management)
articleGroup := r.Group("/api/v1/articles")
{
articleGroup.GET("", articleHandler.List) // Public Access: List of articles
articleGroup.POST("", authMiddleware(), articleHandler.Create) // Authentication required: Create an article
articleGroup.GET("/:id", articleHandler.Get) // Public access: Individual article details
}
Start the service (listen on port 8080)
if err := r.Run(":8080"); err != nil {
log. Fatalf("Service Start Failed: %v", err)
}
}
Core Reasons for Choosing Gin:
- Performance crushing: 5-10 times faster request processing power than Django, especially in high-concurrency scenarios
- Extremely lightweight: The core framework is less than 5MB, and the deployment package is smaller and starts faster
- Middleware Ecosystem: Out-of-the-box authentication, current limiting, caching, and other modules for easy functional expansion
Data storage layer: Multi-engine collaboration
- MySQL: Responsible for persistent storage of structured data, such as article content, user information, comment data, and other core business data
- Redis:
- Hot article caching (reduces database access pressure)
- User session state management (replaces Django's session mechanism)
- Interface frequency limit counter (to prevent malicious requests)
- Elasticsearch:
- Full-text search engine (supports complex search requirements)
- Intelligent recommendations for related articles (based on content similarity)
- Efficient content filtering (filtering by tags, categories, time, etc.)
Front-end architecture: Vue3 + TypeScript
vue
<template>
<div class="article-detail">
<h1>{{ article.title }}</h1>
<div class="content"></div>
<div class="comments">
</div>
</div>
</template>
Front-end Technology Highlights:
- 'md-editor-v3' is used for efficient rendering and previewing of Markdown content
- TypeScript strong type constraints, reducing runtime errors by more than 70%
- Responsive layout design that performs well on mobile, tablet, and PC
Cloud Service Integration: Tencent Cloud COS
go
Image upload to COS core logic
func UploadToCOS(file *multipart. FileHeader) (string, error) {
Initialize the COS client
client := cos. NewClient(bucketURL, &cos. BaseURL{BucketURL: bucketDomain})
Open the upload file
f, err := file. Open()
if err != nil {
return "", fmt. Errorf("File opened failed: %v", err)
}
defer f.Close()
Generate unique file names (to avoid conflicts)
key := fmt. Sprintf("images/%d-%s", time. Now(). UnixMicro(), file. Filename)
Upload files to COS
_, err = client. Object.Put(context. Background(), key, f, nil)
if err != nil {
return "", fmt. Errorf("COS upload failed: %v", err)
}
Returns the CDN acceleration address
return fmt. Sprintf("%s/%s", cdnDomain, key), nil
}
Cloud Storage Advantages:
- Separation of static resources from application services (reducing server storage pressure)
- Global CDN node acceleration (3-5x faster image loading)
- Automatic media processing (supports image compression, format conversion, watermark addition)
Core function upgrades
1. Fast full-text search
Search systems built on Elasticsearch are a qualitative leap forward:
- Response speed down from seconds to milliseconds (results returned in an average of 150ms)
- Support mixed Chinese and English word segmentation (accurately identify multilingual content)
- Keyword highlighting (quickly target matching content)
- Search suggestions (auto-complete possible keywords as you type)
2. Smart caching policies
Multi-level caching mechanism design:
- Hot articles (top 20% of visits) cached for 15 minutes (dynamically adjusted)
- Daily Top Leaderboard cache for 1 hour (updated regularly)
- Permanent caching of categories/tags list (actively invalidated on update)
- Local caching of home content (independent control of head banner and bottom recommendation)
3. Third-party login integrations
go
GitHub OAuth2 login callback handling
func GitHubLoginCallback(c *gin. Context) {
// 1. Redeem the authorization code for an access token
code := c.Query("code")
token, err := githubOAuth.Exchange(context. Background(), code)
if err != nil {
c.JSON(http. StatusBadRequest, gin. H{"error": "authorization failed"})
return
}
// 2. Get user information
userInfo, err := githubOAuth.GetUserInfo(token. AccessToken)
if err != nil {
c.JSON(http. StatusInternalServerError, gin. H{"error": "Failed to obtain user information"})
return
}
// 3. Create or update local users
user := models. FindOrCreateUser(userInfo)
// 4. Generate JWT token (valid for 7 days)
jwtToken, err := generateJWT(user.ID, 7*24*time. Hour)
if err != nil {
c.JSON(http. StatusInternalServerError, gin. H{"error": "Token generation failed"})
return
}
// 5. Skip to home page (carry token)
c.Redirect(http. StatusFound, fmt. Sprintf("/?token=%s", jwtToken))
}
Supported and planned login methods:
- Online: GitHub login (seamless integration into the open source ecosystem)
- Live: Microsoft Sign-In (Windows Full Series Productivity)
- Under development: WeChat login (covering a wider user group) // Depending on the situation, it needs to be recorded, which is too troublesome
4. Large model integration
javascript
AI writing assistant interaction logic
const askAI = async (question: string) => {
Displays loading status
isLoading.value = true
aiResponse.value = ''
try {
Initiate a streaming request
const res = await fetch('/api/ai/ask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ question, context: currentDraft.value })
})
Handle streaming responses
const reader = res.body?. getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader.read()
if (done) break
Stitch together AI-replied content in real-time
aiResponse.value += decoder.decode(value, { stream: true })
}
} catch (err) {
aiResponse.value = 'AI service is temporarily unavailable, please try again later'
} finally {
isLoading.value = false
}
}
AI Features in Action:
- Intelligent summaries of article content (automatically generate introductions within 200 words)
- Automatic review of comment content (identification of spam comments and sensitive words)
- Writing assistant real-time suggestions (wording optimization, paragraph restructuring suggestions available)
Performance optimization results
| Indicators | Legacy (Django) | New edition (Gin) | Increase |
|---|---|---|---|
| HomeAverage load time | 850ms | 220ms | 74% |
| Search response time | 1200ms | 150ms | 87% |
| Concurrent processing capacity | 150 req/s | 3200 req/s | 20x |
| Server memory usage | 420MB | 55MB | 87% |
| Single article render time | 350ms | 60ms | 83% |
Development Challenges and Solutions
Cross-domain problem handling
Cross-domain solution under the front-end and back-end separation architecture:
go
Refined CORS middleware implementation
func CORSMiddleware() gin. HandlerFunc {
return func(c *gin. Context) {
Allow domain names (production environment restriction source)
origin := c.Request.Header.Get("Origin")
if allowOrigin(origin) {
c.Writer.Header(). Set("Access-Control-Allow-Origin", origin)
}
Allowed request methods
c.Writer.Header(). Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
Allowed request headers
c.Writer.Header(). Set("Access-Control-Allow-Headers", "Origin, Content-Type, Authorization")
Allow credentials (e.g. cookies)
c.Writer.Header(). Set("Access-Control-Allow-Credentials", "true")
Preflight request cache time
c.Writer.Header(). Set("Access-Control-Max-Age", "86400")
Process preflight requests
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(http. StatusNoContent)
return
}
c.Next()
}
}
Large file upload optimization
Experience optimization for image/attachment uploads:
- Front-end shard upload (splitting large files into small 5MB chunks for parallel transfer)
- Backend parallel write to COS (utilizing Go's goroutine concurrency processing)
- Breakpoint resumption support (records can be restored after network interruption if the uploaded fragment is uploaded)
- Real-time display of upload progress (push progress information via WebSocket)
High concurrency scenario response
Traffic Peak Handling Strategy:
- Redis Bloom Filter (prevents cache penetration)
- Gin server connection pool tuning (increase the concurrency processing limit)
- CDN acceleration for static resources (reduces the pressure on the origin server)
- Dynamic scaling configuration (auto-scaling based on CPU/memory usage)
Future Planning
Technology Evolution Route
Short-term plan (within 3 months):
- Multilingual support (automatic switching between Chinese and English)
- Improve content statistics (visits, sources, user behavior)
Medium-term target (within 6 months):
- Deep AI integration (intelligent recommendation engine, automatic image matching)
- PWA support (offline access to core features)
Long-term planning (within 1 year):
- WeChat ecological integration (scan code login, official account synchronization, mini program version)
- Community interaction features (like, favorite, follow author)
Conclusion: A new starting point, a new journey
This refactoring is not only a replacement of the technology stack, but also a complete optimization of the blog system architecture. The transition from dynamic to static types significantly improves code quality and maintainability. The evolution from monolithic frames to front-end separation makes the system more flexible and scalable.
At present, the new blog system is running stably in production, welcome to visit the experience:
- Blog address: Uncle Sam's Tech Blog
- GitHub repository: sam-uncle/blog
The pace of technology upgrades doesn't stop, and I'll focus on improving AI capabilities and multilingual support. If you have any suggestions or find problems, please leave a message in the comment area - the progress of technology always comes from continuous practice and feedback!