server-side-rendering

安装量: 118
排名: #7284

安装

npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill server-side-rendering

Server-Side Rendering Overview

Build server-side rendered applications using modern template engines, view layers, and data-driven HTML generation with caching, streaming, and performance optimization across Python, Node.js, and Ruby frameworks.

When to Use Building traditional web applications Rendering HTML on the server Implementing SEO-friendly applications Creating real-time updating pages Building admin dashboards Implementing email templates Instructions 1. Flask with Jinja2 Templates

app.py

from flask import Flask, render_template, request, jsonify from datetime import datetime

app = Flask(name)

Custom Jinja2 filters

@app.template_filter('currency') def format_currency(value): return f"${value:.2f}"

@app.template_filter('date_format') def format_date(date_obj): return date_obj.strftime('%Y-%m-%d %H:%M:%S')

@app.context_processor def inject_globals(): """Inject global variables into templates""" return { 'app_name': 'My App', 'current_year': datetime.now().year, 'support_email': 'support@example.com' }

routes.py

@app.route('/') def index(): """Home page""" featured_posts = Post.query.filter_by(featured=True).limit(5).all() return render_template('index.html', featured_posts=featured_posts)

@app.route('/dashboard') @login_required def dashboard(): """User dashboard""" user_stats = { 'total_posts': current_user.posts.count(), 'total_views': sum(p.view_count for p in current_user.posts), 'total_followers': current_user.followers.count() }

recent_activity = current_user.get_activity(limit=10)

return render_template(
    'dashboard.html',
    stats=user_stats,
    activity=recent_activity
)

@app.route('/posts/') def view_post(slug): """View single post""" post = Post.query.filter_by(slug=slug).first_or_404()

# Increment view count
post.view_count += 1
db.session.commit()

# Get related posts
related = Post.query.filter(
    Post.category_id == post.category_id,
    Post.id != post.id
).limit(5).all()

return render_template(
    'post.html',
    post=post,
    related_posts=related,
    comments=post.comments.order_by(Comment.created_at.desc()).all()
)

@app.route('/search') def search(): """Search posts""" query = request.args.get('q', '') page = request.args.get('page', 1, type=int)

if not query:
    return render_template('search.html', posts=[], query='')

posts = Post.query.filter(
    Post.title.ilike(f'%{query}%') |
    Post.content.ilike(f'%{query}%')
).paginate(page=page, per_page=20)

return render_template(
    'search.html',
    posts=posts.items,
    total=posts.total,
    query=query,
    page=page
)

@app.route('/admin/posts/create', methods=['GET', 'POST']) @login_required @admin_required def create_post(): """Create new post""" if request.method == 'POST': title = request.form['title'] content = request.form['content'] category_id = request.form['category_id']

    post = Post(
        title=title,
        slug=generate_slug(title),
        content=content,
        category_id=category_id,
        author_id=current_user.id
    )
    db.session.add(post)
    db.session.commit()

    return redirect(url_for('view_post', slug=post.slug))

categories = Category.query.all()
return render_template('admin/create_post.html', categories=categories)
  1. Jinja2 Template Examples
{% block title %}{{ app_name }}{% endblock %} {% block extra_head %}{% endblock %}
{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %}
{{ message }}
{% endfor %} {% endif %} {% endwith %} {% block content %}{% endblock %}

© {{ current_year }} {{ app_name }}. All rights reserved.

{% block extra_scripts %}{% endblock %}

{% extends "base.html" %}

{% block title %}Dashboard - {{ app_name }}{% endblock %}

{% block content %}

Welcome, {{ current_user.first_name }}!

Total Posts

{{ stats.total_posts }}

Total Views

{{ stats.total_views | default(0) }}

Followers

{{ stats.total_followers }}

Recent Activity

{% if activity %}
    {% for item in activity %}
  • {{ item.created_at | date_format }} {{ item.description }}
  • {% endfor %}
{% else %}

No recent activity.

{% endif %}

{% endblock %}

{% extends "base.html" %}

{% block title %}{{ post.title }} - {{ app_name }}{% endblock %}

{% block content %}

{{ post.title }}

{{ post.content | safe }}
{% if related_posts %} {% endif %}

Comments ({{ comments | length }})

{% if comments %}
    {% for comment in comments %}
  • {{ comment.author.full_name }}

    {{ comment.content }}

  • {% endfor %}
{% else %}

No comments yet.

{% endif %} {% if current_user.is_authenticated %}
{% endif %}

{% endblock %}

  1. Node.js/Express with EJS Templates // app.js const express = require('express'); const path = require('path');

const app = express();

// Set template engine app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views'));

// Middleware app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(express.static(path.join(__dirname, 'public')));

// Local variables middleware app.use((req, res, next) => { res.locals.currentUser = req.user || null; res.locals.appName = 'My App'; res.locals.currentYear = new Date().getFullYear(); next(); });

// Routes app.get('/', (req, res) => { const posts = [ { id: 1, title: 'Post 1', excerpt: 'First post', slug: 'post-1' }, { id: 2, title: 'Post 2', excerpt: 'Second post', slug: 'post-2' } ];

res.render('index', { posts });

});

app.get('/posts/:slug', async (req, res) => { const { slug } = req.params; const post = await Post.findOne({ where: { slug } });

if (!post) {
    return res.status(404).render('404');
}

const comments = await post.getComments();
const relatedPosts = await Post.findAll({
    where: { categoryId: post.categoryId },
    limit: 5
});

res.render('post', {
    post,
    comments,
    relatedPosts
});

});

app.get('/dashboard', requireAuth, (req, res) => { const stats = { totalPosts: req.user.posts.length, totalViews: req.user.posts.reduce((sum, p) => sum + p.views, 0) };

res.render('dashboard', { stats });

});

app.listen(3000);

  1. EJS Template Examples
<%= typeof title != 'undefined' ? title + ' - ' : '' %><%= appName %> <%- include('partials/navbar') %>
<%- body %>
<%- include('partials/footer') %>

<%= post.title %>

<%- post.content %>
<% if (relatedPosts && relatedPosts.length > 0) { %> <% } %>

Comments (<%= comments.length %>)

<% comments.forEach(comment => { %>
<%= comment.author.name %>

<%= comment.content %>

<% }); %> <% if (currentUser) { %>
<% } %>
  1. Caching and Performance

Flask caching

from flask_caching import Cache

cache = Cache(app, config={'CACHE_TYPE': 'redis'})

@app.route('/posts/') @cache.cached(timeout=3600) # Cache for 1 hour def view_post(slug): """Cached post view""" post = Post.query.filter_by(slug=slug).first_or_404() comments = post.comments.all() return render_template('post.html', post=post, comments=comments)

@app.route('/api/posts') @cache.cached(timeout=300) # Cache for 5 minutes def get_posts(): """Cached API endpoint""" posts = Post.query.filter_by(published=True).all() return jsonify([p.to_dict() for p in posts])

Invalidate cache

@app.route('/admin/posts//edit', methods=['POST']) @admin_required def edit_post(id): post = Post.query.get(id) # Update post db.session.commit()

# Clear cache
cache.delete_memoized(view_post, post.slug)
cache.delete_memoized(get_posts)

return redirect(url_for('view_post', slug=post.slug))
  1. Django Template Examples

views.py

from django.shortcuts import render from django.views.generic import DetailView, ListView from django.db.models import Q from .models import Post, Comment

class PostListView(ListView): model = Post template_name = 'blog/post_list.html' context_object_name = 'posts' paginate_by = 10

def get_queryset(self):
    return Post.objects.filter(published=True).order_by('-created_at')

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['featured_posts'] = Post.objects.filter(featured=True)[:5]
    return context

class PostDetailView(DetailView): model = Post template_name = 'blog/post_detail.html' context_object_name = 'post' slug_field = 'slug'

def get_queryset(self):
    return Post.objects.filter(published=True)

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['comments'] = self.object.comments.all()
    context['related_posts'] = Post.objects.filter(
        category=self.object.category
    ).exclude(id=self.object.id)[:5]
    return context
  1. Django Templates

{% extends "base.html" %}

{% block title %}Blog - {{ app_name }}{% endblock %}

{% block content %}

Blog Posts

{% if featured_posts %} {% endif %}

All Posts

{% for post in posts %}

{{ post.title }}

By {{ post.author.get_full_name }} {{ post.created_at|date:"M d, Y" }}

{{ post.content|truncatewords:50 }}

{% empty %}

No posts yet.

{% endfor %}
{% if is_paginated %} {% endif %}

{% endblock %}

Best Practices ✅ DO Use template inheritance for DRY code Implement caching for frequently rendered pages Use template filters for formatting Separate concerns between views and templates Validate and sanitize all user input Use context processors for global variables Implement proper pagination Use conditional rendering appropriately Cache expensive queries Optimize template rendering ❌ DON'T Put business logic in templates Use unbounded loops in templates Execute database queries in templates Trust user input without sanitization Over-nest template inheritance Use very long template files Render sensitive data in templates Ignore template caching opportunities Use global variables excessively Mix multiple concerns in one template Complete Example @app.route('/hello/') def hello(name): return render_template('hello.html', name=name)

hello.html

Hello, {{ name | capitalize }}!

返回排行榜