Skip to content

搞英语 → 看世界

翻译英文优质信息和名人推特

Menu
  • 首页
  • 作者列表
  • 独立博客
  • 专业媒体
  • 名人推特
  • 邮件列表
  • 关于本站
Menu

静态 HTML 注释

Posted on 2022-10-09

如果你有一个静态 HTML 网站,但你想包含评论,这里有一个有趣的方法来使用 PostgreSQL 的 NOTIFY 和 LISTEN。

最大的想法是将评论写为静态 HTML,仅当评论发生变化时,而不是每次都进行数据库查询来显示它们。如果您遇到流量激增,这可以防止“死亡拥抱”。

我已经这样做了六年多了,效果很好。这是使用 Ruby 作为粘合剂的秘诀,尽管您可以使用任何脚本语言。

  1. 用于注释的 PostgreSQL 数据库表
  2. Ruby 接收表单帖子,插入数据库
  3. 当评论改变时,PostgreSQL 触发器发送 NOTIFY
  4. Ruby 运行 PostgreSQL LISTEN,将更新的评论导出到 HTML
  5. 静态页面上的 JavaScript 包括 HTML

用于注释的 PostgreSQL 数据库表

create table comments ( id integer primary key generated by default as identity, uri text, created_at date default current_date, name text, email text, comment text ); create index on comments(uri);

下载代码

Ruby 接收表单帖子,插入数据库

将其放在您想要评论的任何 HTML 页面上:

 <section id="comments"></section> <script src="/comments.js"></script>

下载代码

将下一个代码放入您的 Nginx 配置中,以将 /comments 发送到 localhost。

 location = /comments { proxy_pass http://127.0.0.1:4567; }

下载代码

Ruby Sinatra 接收表单帖子。

 require 'pg' require 'sinatra' DB = PG::Connection.new(dbname: 'test', user: 'tester') post '/comments' do DB.exec_params("insert into comments (uri, name, email, comment) values ($1, $2, $3, $4)", [params[:uri], params[:name], params[:email], params[:comment]]) redirect to(request.env['HTTP_REFERER']) end

下载代码

在服务器上的终端中运行它,它应该默认侦听端口 4567。

当评论改变时,PostgreSQL 触发器发送 NOTIFY

 create function comments_changed() returns trigger as $$ begin perform pg_notify('comments_changed', new.uri); return new; end; $$ language plpgsql; create trigger comments_changed after insert or update on comments for each row execute procedure comments_changed();

下载代码

将该函数加载到具有您的评论表的 PostgreSQL 数据库中。

它向侦听器(如下)发送此 URI的注释已更改的通知。然后侦听器将重新输出仅针对此 URI 的注释,而不是全部。

Ruby 运行 PostgreSQL LISTEN,将更新的评论导出到 HTML

在您的 Web 根目录中创建一个名为 /commentcache/ 的目录,以保存静态评论。

然后让这个 Ruby 脚本在终端中运行以监听数据库更改,并将更新后的注释以 HTML 格式写入磁盘。

 require 'pg' DB = PG::Connection.new(dbname: 'test', user: 'tester') BASEDIR = '/var/www/htdocs/commentcache/' # directory in your web root # a single comment list entry, used in ol map, below def li(row) '<li><cite>%s (%s)</cite><p>%s</p></li>' % [row['name'], row['created_at'], row['comment']] end # top-level map of database rows into HTML list def ol(rows) rows.inject('') {|html, row| html += li(row) ; html} end # write comments to disk for this URI def save_comments(uri) rows = DB.exec_params("select name, created_at, comment from comments where uri = $1 order by id", [uri]).to_a File.open(BASEDIR + uri, 'w') do |f| f.puts ol(rows) end end # first write them all DB.exec("select distinct(uri) from comments").each do |r| save_comments(r['uri']) end # listen for changes. re-write when changed DB.exec('listen comments_changed') while true do DB.wait_for_notify do |event, pid, uri| save_comments(uri) end end

下载代码

静态页面上的 JavaScript 在查看时包含当前 HTML

使用 JavaScript 显示表单以发表评论,并从 /commentcache/ 路径加载评论列表。

 function showForm(uri) { document.getElementById('comments').innerHTML = ` <header><h1>Comments:</h1></header> <form method="post" action="/comments"> <input type="hidden" name="uri" value="${uri}"> <label for="name">Your Name</label> <input type="text" name="name" id="name" required> <label for="email">Your Email</label> <input type="email" name="email" id="email" required> <label for="comment">Comment</label> <textarea name="comment" id="comment" cols="80" rows="10" required></textarea> <input type="submit" value="post comment"> </form> <ol id="commentlist"></ol>`; } function getComments(uri) { try { const xhr = new XMLHttpRequest(); xhr.open('get', '/commentcache/' + uri); xhr.send(null); xhr.onload = function() { if (xhr.status === 200) { document.getElementById('commentlist').innerHTML = xhr.responseText; } }; } catch(e) { } } // /blog/topic/page.html uri = 'blog_topic_page.html' for filesystem const uri = location.pathname.substring(1).replace(/\//g, '_'); showForm(uri); getComments(uri);

下载代码

就这样。我已经从我的实际使用中稍微简化了它,我有一些约束和检查会分散本示例的核心点。

还有其他方法可以做到这一点。 NOTIFY 和 LISTEN 不是必需的。接收发布评论的 Ruby Sinatra 路由可以立即将 HTML 写入磁盘。但我还有其他删除和更新评论的脚本,我喜欢NOTIFY 触发器和 LISTEN 脚本的组合如何始终让它们在磁盘上保持更新。

另一种有趣的方法是将注释直接写入每个 HTML 文件,而不是单独的文件,因此您根本不需要 JavaScript。

可选升级:删除时通知

我为示例简化了 PostgreSQL 触发器,但是通过多几行代码,您也可以使用相同的触发器来通知已删除的评论。删除行的值在“旧”中,而插入和更新的值在“新”中,因此我们必须创建一个 uri 变量和一个 if/then/else 来知道使用哪个。

 create or replace function comments_changed() returns trigger as $$ declare uri text; begin if tg_op = 'DELETE' then uri = old.uri; else uri = new.uri; end if; perform pg_notify('comments_changed', uri); return old; end; $$ language plpgsql; create trigger comments_changed after insert or update or delete on comments for each row execute procedure comments_changed();

下载代码

你可以在我博客中的任何页面看到这段代码,除了这个,因为我怀疑这会充满烦人的测试评论,我删除了。如果您确实在其中一个页面上发表评论,请保持友善,不要让我后悔花了四个小时写这篇文章。

原文: https://sive.rs/shc

本站文章系自动翻译,站长会周期检查,如果有不当内容,请点此留言,非常感谢。
  • Abhinav
  • Abigail Pain
  • Adam Fortuna
  • Alberto Gallego
  • Alex Wlchan
  • Answer.AI
  • Arne Bahlo
  • Ben Carlson
  • Ben Kuhn
  • Bert Hubert
  • Bits about Money
  • Brian Krebs
  • ByteByteGo
  • Chip Huyen
  • Chips and Cheese
  • Christopher Butler
  • Colin Percival
  • Cool Infographics
  • Dan Sinker
  • David Walsh
  • Dmitry Dolzhenko
  • Dustin Curtis
  • Elad Gil
  • Ellie Huxtable
  • Ethan Marcotte
  • Exponential View
  • FAIL Blog
  • Founder Weekly
  • Geoffrey Huntley
  • Geoffrey Litt
  • Greg Mankiw
  • Henrique Dias
  • Hypercritical
  • IEEE Spectrum
  • Investment Talk
  • Jaz
  • Jeff Geerling
  • Jonas Hietala
  • Josh Comeau
  • Lenny Rachitsky
  • Liz Danzico
  • Lou Plummer
  • Luke Wroblewski
  • Matt Baer
  • Matt Stoller
  • Matthias Endler
  • Mert Bulan
  • Mostly metrics
  • News Letter
  • NextDraft
  • Non_Interactive
  • Not Boring
  • One Useful Thing
  • Phil Eaton
  • Product Market Fit
  • Readwise
  • ReedyBear
  • Robert Heaton
  • Ruben Schade
  • Sage Economics
  • Sam Altman
  • Sam Rose
  • selfh.st
  • Shtetl-Optimized
  • Simon schreibt
  • Slashdot
  • Small Good Things
  • Taylor Troesh
  • Telegram Blog
  • The Macro Compass
  • The Pomp Letter
  • thesephist
  • Thinking Deep & Wide
  • Tim Kellogg
  • Understanding AI
  • 英文媒体
  • 英文推特
  • 英文独立博客
©2025 搞英语 → 看世界 | Design: Newspaperly WordPress Theme