Skip to content

Commit

Permalink
feat: support server render html (AppFlowy-IO#5471)
Browse files Browse the repository at this point in the history
* feat: node server

* fix: replace node to bun
  • Loading branch information
qinluhe authored Jun 5, 2024
1 parent f6e33a5 commit 52e7fb4
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy_test_web.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
with:
SSH_PRIVATE_KEY: ${{ env.SSH_PRIVATE_KEY }}
ARGS: "-rlgoDzvc -i"
SOURCE: "frontend/appflowy_web_app/dist frontend/appflowy_web_app/Dockerfile frontend/appflowy_web_app/nginx.conf frontend/appflowy_web_app/.env nginx-signed.crt nginx-signed.key"
SOURCE: "frontend/appflowy_web_app/dist frontend/appflowy_web_app/server.cjs frontend/appflowy_web_app/start.sh frontend/appflowy_web_app/Dockerfile frontend/appflowy_web_app/nginx.conf frontend/appflowy_web_app/.env nginx-signed.crt nginx-signed.key"
REMOTE_HOST: ${{ env.REMOTE_HOST }}
REMOTE_USER: ${{ env.REMOTE_USER }}
EXCLUDE: "frontend/appflowy_web_app/dist/, frontend/appflowy_web_app/node_modules/"
Expand Down
15 changes: 13 additions & 2 deletions frontend/appflowy_web_app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
FROM node:latest
FROM oven/bun:latest

WORKDIR /app

RUN apt-get update && \
apt-get install -y nginx

RUN bun install cheerio pino axios pino-pretty

COPY . .

RUN addgroup --system nginx && \
adduser --system --no-create-home --disabled-login --ingroup nginx nginx

Expand All @@ -18,6 +24,11 @@ COPY nginx-signed.key /etc/ssl/private/nginx-signed.key

RUN chown -R nginx:nginx /etc/ssl/certs/nginx-signed.crt /etc/ssl/private/nginx-signed.key

COPY start.sh /app/start.sh

RUN chmod +x /app/start.sh


EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]
CMD ["/app/start.sh"]
22 changes: 21 additions & 1 deletion frontend/appflowy_web_app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,28 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/appflowy.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>AppFlowy</title>
<meta name="description"
content="AppFlowy is an AI collaborative workspace where you achieve more without losing control of your data"
/>
<meta property="og:title" content="AppFlowy" />
<meta property="og:description"
content="AppFlowy is an AI collaborative workspace where you achieve more without losing control of your data"
/>
<meta property="og:image"
content="https://d3uafhn8yrvdfn.cloudfront.net/website/production/_next/static/media/og-image.e347bfb5.png"
/>
<meta property="og:url" content="https://appflowy.com" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="AppFlowy" />
<meta name="twitter:description"
content="AppFlowy is an AI collaborative workspace where you achieve more without losing control of your data"
/>
<meta name="twitter:image"
content="https://d3uafhn8yrvdfn.cloudfront.net/website/production/_next/static/media/og-image.e347bfb5.png"
/>
<meta name="twitter:site" content="@appflowy" />
<meta name="twitter:creator" content="@appflowy" />
</head>
<body id="body">
<div id="root"></div>
Expand Down
17 changes: 14 additions & 3 deletions frontend/appflowy_web_app/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ http {

gzip_http_version 1.0;

gzip_comp_level 5;

gzip_vary on;

gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/wasm;

# Existing server block for HTTP
Expand Down Expand Up @@ -61,15 +65,22 @@ http {
ssl_prefer_server_ciphers on;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}

location /static/ {
root /usr/share/nginx/html;
expires 30d;
access_log off;
location ~* \.wasm$ {
types { application/wasm wasm; }
default_type application/wasm;
}
}

location /appflowy.svg {
Expand Down
6 changes: 5 additions & 1 deletion frontend/appflowy_web_app/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

114 changes: 114 additions & 0 deletions frontend/appflowy_web_app/server.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
const path = require('path');
const fs = require('fs');
const pino = require('pino');
const cheerio = require('cheerio');
const axios = require('axios');

const distDir = path.join(__dirname, 'dist');
const indexPath = path.join(distDir, 'index.html');

const setOrUpdateMetaTag = ($, selector, attribute, content) => {
if ($(selector).length === 0) {
$('head').append(`<meta ${attribute}="${selector.match(/\[(.*?)\]/)[1]}" content="${content}">`);
} else {
$(selector).attr('content', content);
}
};
// Create a new logger instance
const logger = pino({
transport: {
target: 'pino-pretty',
level: 'info',
options: {
colorize: true,
translateTime: 'SYS:standard',
destination: `${__dirname}/pino-logger.log`,
},
},
});

const logRequestTimer = (req) => {
const start = Date.now();
const pathname = new URL(req.url).pathname;
logger.info(`Incoming request: ${pathname}`);
return () => {
const duration = Date.now() - start;
logger.info(`Request for ${pathname} took ${duration}ms`);
};
};

const fetchMetaData = async (url) => {
try {
const response = await axios.get(url);
return response.data;
} catch (error) {
logger.error('Error fetching meta data', error);
return null;
}
};

const createServer = async (req) => {
const timer = logRequestTimer(req);

if (req.method === 'GET') {
const pageId = req.url.split('/').pop();
let htmlData = fs.readFileSync(indexPath, 'utf8');
const $ = cheerio.load(htmlData);
if (!pageId) {
timer();
return new Response($.html(), {
headers: { 'Content-Type': 'text/html' },
});
}

const description = 'Write, share, comment, react, and publish docs quickly and securely on AppFlowy.';
let title = 'AppFlowy';
const url = 'https://appflowy.com';
let image = 'https://d3uafhn8yrvdfn.cloudfront.net/website/production/_next/static/media/og-image.e347bfb5.png';
// Inject meta data into the HTML to support SEO and social sharing
// if (metaData) {
// title = metaData.title;
// image = metaData.image;
// }

$('title').text(title);
setOrUpdateMetaTag($, 'meta[name="description"]', 'name', description);
setOrUpdateMetaTag($, 'meta[property="og:title"]', 'property', title);
setOrUpdateMetaTag($, 'meta[property="og:description"]', 'property', description);
setOrUpdateMetaTag($, 'meta[property="og:image"]', 'property', image);
setOrUpdateMetaTag($, 'meta[property="og:url"]', 'property', url);
setOrUpdateMetaTag($, 'meta[property="og:type"]', 'property', 'article');
setOrUpdateMetaTag($, 'meta[name="twitter:card"]', 'name', 'summary_large_image');
setOrUpdateMetaTag($, 'meta[name="twitter:title"]', 'name', title);
setOrUpdateMetaTag($, 'meta[name="twitter:description"]', 'name', description);
setOrUpdateMetaTag($, 'meta[name="twitter:image"]', 'name', image);

timer();
return new Response($.html(), {
headers: { 'Content-Type': 'text/html' },
});
} else {
timer();
logger.error({ message: 'Method not allowed', method: req.method });
return new Response('Method not allowed', { status: 405 });
}
};

const start = () => {
try {
Bun.serve({
port: 3000,
fetch: createServer,
error: (err) => {
logger.error(`Internal Server Error: ${err}`);
return new Response('Internal Server Error', { status: 500 });
},
});
logger.info(`Server is running on port 3000`);
} catch (err) {
logger.error(err);
process.exit(1);
}
};

start();
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ function CollaborativeEditor({ doc }: { doc: Y.Doc }) {

useEffect(() => {
if (!editor) return;

editor.connect();
setIsConnected(true);

Expand Down
10 changes: 10 additions & 0 deletions frontend/appflowy_web_app/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

# Start the frontend server
bun run server.cjs &

# Start the nginx server
service nginx start

tail -f /dev/null

0 comments on commit 52e7fb4

Please sign in to comment.