Lesson 44-WinterJS Advanced Application Development

Server-Side Rendering (SSR)

Basic SSR Implementation

Integration with winter.serve and Template Engine

// src/entry-server.js
import { createSSRApp } from 'vue'; // Example framework-agnostic
import App from './App.vue';
import { renderToString } from 'winter-ssr'; // Assumed SSR renderer
import templateEngine from './template-engine';

export async function render(url) {
  const app = createSSRApp(App, { url });
  const html = await renderToString(app);

  // Inject dynamic content using template engine
  return templateEngine.render('layout', {
    body: html,
    title: 'WinterJS SSR Demo'
  });
}

// src/template-engine.js
export default {
  render(templateName, data) {
    const templates = {
      layout: (data) => `
        <!DOCTYPE html>
        <html>
          <head>
            <title>${data.title}</title>
          </head>
          <body>
            ${data.body}
          </body>
        </html>
      `
    };
    return templates[templateName](data);
  }
};

Server-Side Route Handling

// server.js
import http from 'http';
import { parse } from 'url';
import { render } from './src/entry-server';

const server = http.createServer(async (req, res) => {
  const { pathname } = parse(req.url);

  try {
    const html = await render(pathname);
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end(html);
  } catch (err) {
    res.writeHead(500);
    res.end('Server Error');
    console.error(err);
  }
});

server.listen(3000, () => {
  console.log('SSR Server running on http://localhost:3000');
});

Data Prefetching and State Synchronization

Server-Side Data Prefetching

// src/entry-server.js
export async function render(url) {
  const app = createSSRApp(App, { url });

  // Execute route-level data prefetching
  const matchedComponents = getMatchedComponents(url);
  await Promise.all(
    matchedComponents.map(Component => {
      if (Component.asyncData) {
        return Component.asyncData({ store, route: url });
      }
    })
  );

  // Get prefetched state
  const initialState = store.getState();

  // Render application
  const html = await renderToString(app);

  return {
    html,
    initialState // Inject into client
  };
}

Client-Side State Synchronization

// src/entry-client.js
import { createApp } from 'vue';
import App from './App.vue';
import { hydrate } from 'winter-ssr';
import { createStore } from './store';

const store = createStore();
const app = createApp(App);

// Initialize client store with server-injected state
if (window.__INITIAL_STATE__) {
  store.replaceState(window.__INITIAL_STATE__);
}

hydrate(app, document.getElementById('app'), () => {
  // Client activation complete
  app.mount('#app');
});

SSR Performance Optimization

Component-Level Caching Strategy

// src/cache-strategy.js
export const componentCache = new Map();

export function getCacheKey(component, props) {
  return `${component.name}-${JSON.stringify(props)}`;
}

export async function renderWithCache(component, props) {
  const key = getCacheKey(component, props);

  if (componentCache.has(key)) {
    return componentCache.get(key);
  }

  const html = await renderComponent(component, props);
  componentCache.set(key, html);

  // Set cache expiration
  if (componentCache.size > 1000) {
    componentCache.delete(componentCache.keys().next().value);
  }

  return html;
}

Streaming SSR Implementation

// src/stream-renderer.js
export async function streamRender(app) {
  const stream = new ReadableStream({
    start(controller) {
      const context = { write: controller.enqueue.bind(controller) };

      // Chunked rendering
      renderApp(app, context, (chunk) => {
        controller.enqueue(new TextEncoder().encode(chunk));
      }).then(() => {
        controller.close();
      }).catch(err => {
        controller.error(err);
      });
    }
  });

  return stream;
}

SSR Security and Error Handling

Security Measures

// src/security-middleware.js
export function sanitizeInput(input) {
  return input.replace(/[<>]/g, '');
}

export function helmetMiddleware(req, res, next) {
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader('Content-Security-Policy', "default-src 'self'");
  next();
}

// Use in rendering flow
export async function safeRender(url) {
  try {
    const sanitizedUrl = sanitizeInput(url);
    return await render(sanitizedUrl);
  } catch (err) {
    console.error('SSR Error:', err);
    return {
      html: '<h1>500 Internal Server Error</h1>',
      statusCode: 500
    };
  }
}

SSR Use Cases

SEO Optimization Implementation

// src/seo-meta.js
export function generateMetaTags(page) {
  const meta = {
    title: page.title,
    description: page.description,
    keywords: page.keywords,
    og: {
      title: page.ogTitle || page.title,
      description: page.ogDescription || page.description,
      image: page.ogImage || '/default-og.png'
    }
  };

  return `
    <title>${meta.title}</title>
    <meta name="description" content="${meta.description}">
    <meta name="keywords" content="${meta.keywords}">
    <meta property="og:title" content="${meta.og.title}">
    <meta property="og:description" content="${meta.og.description}">
    <meta property="og:image" content="${meta.og.image}">
  `;
}

Static Site Generation (SSG)

Basic SSG Implementation

winter.build Configuration

// winter.config.js
export default {
  ssg: {
    entry: 'src/entry-static.js',
    output: {
      path: 'dist',
      clean: true
    },
    routes: async () => {
      const { getStaticPaths } = await import('./src/routes');
      return getStaticPaths();
    }
  }
};

// src/entry-static.js
import { createStaticApp } from 'winter-static'; // Assumed static site generator
import App from './App.vue';

export async function generateStaticSite() {
  const app = createStaticApp(App);
  const paths = await getStaticPaths();

  for (const path of paths) {
    const html = await app.render(path);
    writeFileSync(`dist${path}.html`, html);
  }
}

Content Management and Dynamic Routing

Dynamic Route Generation

// src/routes.js
export async function getStaticPaths() {
  const posts = await fetch('https://api.winterjs.com/posts')
    .then(res => res.json());

  return {
    paths: posts.map(post => ({
      params: { slug: post.slug }
    })),
    fallback: 'blocking' // 404 handling strategy
  };
}

export async function getStaticProps({ params }) {
  const post = await fetch(`https://api.winterjs.com/posts/${params.slug}`)
    .then(res => res.json());

  return {
    props: { post },
    revalidate: 60 // ISR: Incremental Static Regeneration
  };
}

SSG Performance Optimization

Incremental Static Regeneration (ISR)

// winter.config.js
export default {
  ssg: {
    revalidate: {
      default: 60, // Default 60 seconds revalidation
      paths: {
        '/blog/*': 300, // Blog posts revalidate every 5 minutes
        '/products/*': 3600 // Product pages revalidate every 1 hour
      }
    }
  }
};

Static Asset Optimization

// winter.config.js
export default {
  ssg: {
    assets: {
      compress: {
        js: true,
        css: true,
        images: {
          webp: true,
          avif: true
        }
      },
      preload: ['critical.css', 'main.js']
    }
  }
};

SSG and CMS Integration

Headless CMS Connection

// src/cms-integration.js
export async function fetchCMSContent() {
  const token = process.env.CMS_TOKEN;
  const response = await fetch('https://cms.winterjs.com/api/content', {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });

  if (!response.ok) {
    throw new Error('Failed to fetch CMS content');
  }

  return response.json();
}

// Use in static generation
export async function getStaticProps() {
  const content = await fetchCMSContent();
  return {
    props: { content },
    revalidate: 3600
  };
}

SSG Use Cases

Documentation Site Generation

// src/docs-generator.js
export async function generateDocs() {
  const files = await glob('docs/**/*.md');
  const docsRoutes = files.map(file => ({
    params: {
      slug: file.replace('docs/', '').replace('.md', '')
    }
  }));

  return {
    paths: docsRoutes,
    fallback: false
  };
}

export async function getStaticProps({ params }) {
  const content = await markdownToHtml(`docs/${params.slug}.md`);
  return {
    props: { content }
  };
}

Real-Time Application Development

WebSocket Real-Time Communication

Basic WebSocket Implementation

// server.js
import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 8080 });

const clients = new Set();

wss.on('connection', (ws) => {
  clients.add(ws);

  ws.on('message', (message) => {
    // Broadcast message to all clients
    for (const client of clients) {
      if (client.readyState === WebSocket.OPEN) {
        client.send(message);
      }
    }
  });

  ws.on('close', () => {
    clients.delete(ws);
  });
});

// Client implementation
const ws = new WebSocket('ws://localhost:8080');

ws.onmessage = (event) => {
  console.log('Received:', event.data);
};

function sendMessage(message) {
  ws.send(JSON.stringify(message));
}

GraphQL and WinterJS Integration

Apollo Client Configuration

// src/apollo-client.js
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client/core';

export const apolloClient = new ApolloClient({
  link: new HttpLink({
    uri: 'https://api.winterjs.com/graphql',
    headers: {
      'Authorization': `Bearer ${localStorage.getItem('token')}`
    }
  }),
  cache: new InMemoryCache()
});

// Usage in component
import { useQuery } from '@vue/apollo-composable'; // Example framework-agnostic
import { gql } from '@apollo/client/core';

const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`;

export default {
  setup() {
    const { result, loading, error } = useQuery(GET_USER, {
      id: '123'
    });

    return { user: result, loading, error };
  }
};

Real-Time Collaborative Editing

CRDT Algorithm Implementation

// src/crdt.js
export class CRDTDocument {
  constructor() {
    this.siteId = Math.random().toString(36).substr(2, 9);
    this.clock = 0;
    this.chars = new Map(); // Character position mapping
  }

  insert(position, char) {
    this.clock++;
    const id = { siteId: this.siteId, clock: this.clock };
    this.chars.set(position, { id, char });
    this.sortChars();
  }

  delete(position) {
    this.clock++;
    const id = { siteId: this.siteId, clock: this.clock };
    this.chars.set(position, { id, deleted: true });
    this.sortChars();
  }

  sortChars() {
    this.chars = new Map([...this.chars.entries()].sort((a, b) => a[0] - b[0]));
  }

  getText() {
    return [...this.chars.values()]
      .filter(char => !char.deleted)
      .map(char => char.char)
      .join('');
  }
}

Real-Time Communication Performance Optimization

Message Compression and Batching

// server.js
import zlib from 'zlib';

wss.on('connection', (ws) => {
  let messageBuffer = [];
  let batchTimer;

  ws.on('message', (message) => {
    messageBuffer.push(message);

    // Batch processing timer
    if (!batchTimer) {
      batchTimer = setTimeout(() => {
        const batch = messageBuffer.join('\n');
        zlib.deflate(batch, (err, compressed) => {
          if (!err) {
            ws.send(compressed);
          }
        });
        messageBuffer = [];
        batchTimer = null;
      }, 50); // 50ms batch processing window
    }
  });
});

Real-Time Application Security Controls

Authentication and Authorization

// server.js
import jwt from 'jsonwebtoken';

wss.on('connection', (ws, req) => {
  const token = req.url.split('token=')[1];

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    ws.user = decoded;

    ws.on('message', (message) => {
      if (!hasPermission(ws.user, message)) {
        ws.send(JSON.stringify({ error: 'Unauthorized' }));
        return;
      }
      // Process message...
    });
  } catch (err) {
    ws.close(1008, 'Invalid token');
  }
});

function hasPermission(user, message) {
  // Permission check logic
  return user.roles.includes('admin') || 
         message.type !== 'delete';
}
Share your love