方法1(修改核心代码)
我发现可以使用其他帮助者扩展Ghost的源代码。我通过在Current/Core/core/Frontend/Apps中添加一个新目录来实现这一目标。我使用了一个名为AMP的现有“应用程序”的示例,该示例非常简单,以开始创建主题中可用的新帮手。在这些现有的应用程序中,该结构很简单,因为助手在LIB/助手中注册。在过程结束时,您需要将应用程序中的目录名称添加到apps.internal json部分中的当前/core/core/core/shardy/config/overrides.json。
在我们应用中的index.js文件的示例内容是:接下来,在此应用程序的LIB目录中,我们创建了一个名为helpers的文件夹。在内部,我们创建了一个新文件,这将是在车把模板中被调用的助手的名称。例如,让我们命名为uppercase.js。
下面是这样的助手代码的一个示例,它只需将助手参数中给定文本的字母转换为大写:
const path = require('path'); module.exports = { activate: function activate(ghost) { ghost.helperService.registerDir(path.resolve(__dirname, './lib/helpers')); } };
不要忘记将应用程序目录的名称添加到当前/core/core/shardy/config/overrides.json。重新启动幽灵后,一切都应该准备就绪。
方法2(不修改核心代码)
我最近开发了这种方法,您不仅可以将其应用于自主幽灵,还可以应用于托管提供商提供的幽灵实例。在后一种情况下,它需要适当的体系结构计划,并购买一台小型服务器,该服务器将充当您的最终幽灵实例的代理。
const {SafeString, escapeExpression} = require('../../../../services/handlebars'); module.exports = function uppercase(text) { return `${text.toUpperCase()}`; };
用户的浏览器将请求发送到包含中间件上游的NGINX服务器。所有请求,无论位置如何,都将被代理到中间件。
我们的USERRESDECORATOR将是异步的,以免阻止主线程。在创建帮助者时,我们将返回异步处理的主题。目前,您需要知道,并非所有用户的浏览器请求都需要装饰的所有内容。因此,第一步是检查Ghost响应的内容类型标头。您可以按以下方式执行此操作,然后比较它是否是文本/HTML,仅装饰html文档返回给用户:// where'proxyres'是您内部的代理响应'userresDecorator' const contentType = proxyres.headers ['content-type'] || ''; 如果(!contentType.includes('text/html')){ //返回原始内容,如果响应不是'text/html' 返回proxyresdata; } 令htmlcontent = proxyresdata.tostring('utf8'); //用“ htmlcontent”做某事并返回 返回htmlcontent;
在此条件语句中,我们可以开始修改HTMLCONTENT,但是为什么我们需要它呢?让我们从幽灵主题中为我们的自定义助手建立基础!
在本文中,我将在我主题的index.hbs文件(主页)中创建一个自定义助手。在车把模板中的可见位置中,我添加了一个示例自定义助手,将其命名{{hello_world}}。
刷新后,由于{{hello_world}} Ghost的默认帮助者中不存在助手,因此我从Ghost收到了错误消息。为了使我们的逻辑工作,我们必须逃脱这个助手,以免被Ghost的内置车把将其视为助手。
正确的方法是将此助手写为\ {{hello_world}}。这样,幽灵将其视为纯文本。刷新幽灵主页后,您应该看到纯文本{{hello_world}}。如果发生这种情况,您就在正确的轨道上。现在,让我们返回中间软件服务器文件,我们将在其中使用响应装饰器。⚠️记住要在主题中逃脱自定义帮助者!不要忘记添加\字符。
// Where 'proxyRes' is your proxy response inside 'userResDecorator' const contentType = proxyRes.headers['content-type'] || ''; if (!contentType.includes('text/html')) { // Return original content if response is not 'text/html' return proxyResData; } let htmlContent = proxyResData.toString('utf8'); // Do something with 'htmlContent' and return return htmlContent;在此变量中,我们将Ghost实例的响应作为页面的完整HTML。想象一下,此响应是您幽灵实例的主页。 HTML内容还将包括我们的纯文本{{hello_world}},该{{hello_world}}显示为纯文本。如果我们的自定义助手处于此形式,我们可以在中间件中使用Handlebars.js(https://handlebarsjs.com/)对其进行编译。切记首先通过软件包管理器安装库,例如NPM:NPM安装式车把并将其添加到您的代码中:const hannebars = require(“ handlebars”);。
//用把手编译响应html,然后返回渲染模板 令htmlcontent = proxyresdata.tostring('utf8'); const模板= handlebars.compile(htmlcontent); htmlContent = template({});
哇!现在,我们已经使用handlebars.js编译并渲染了HTML,但我们还没有完成。我们仍然需要注册我们的自定义助手{{hello_world}}。添加以下代码,最好是在初始化handlebars.js之后:
{{!After refreshing, I get an error message from Ghost because the {{hello_world}} helper doesn’t exist in Ghost's default helpers. For our logic to work, we must escape this helper so that it’s not treated as a helper by Ghost’s built-in Handlebars.
The correct way is to write this helper as \{{hello_world}}. This way, Ghost treats it as plain text. After refreshing the Ghost homepage, you should see the plain text {{hello_world}}. If this happens, you are on the right track. Let’s now return to the middleware server file, where we will use the response decorator.
⚠️ Remember to escape custom helpers in your theme! Don’t forget to add the \ character.
let htmlContent = proxyResData.toString('utf8');//仅在
内渲染车把>>>
在此代码中,我们的自定义帮助者和车把仅在容器中呈现>> 异步处理const path = require('path'); module.exports = { activate: function activate(ghost) { ghost.helperService.registerDir(path.resolve(__dirname, './lib/helpers')); } };如果您打算创建返回更多复杂数据的动态助手,则可能需要随着时间的推移在车把中实现异步助手。这在以下情况下很有用:从数据库中获取值(例如,幽灵数据库)
// Returns 'Hello from middleware!' with the current timestamp handlebars.registerHelper('hello_world', function (options) { return `Hello from middleware! ${new Date().toISOString()}`; });发送API请求并处理其响应
//用车把注册ASYNC帮助者 const hb =异步(车把); HB.RegisterHelper('Hello_world',async函数(options){ //您可以在这里使用等待! // ... });
记住在脚本开始时添加库初始化:const asynchelpers = require('handlebars-asasync-helpers');。如果您遇到由于车把-Async-Helpers和Handerbars之间的版本冲突而遇到的问题,只需将车把降低到 ^4.7.6即可。不幸的是,异步辅助库已经有一段时间没有维护,但它仍然在实践中起作用。
数据库通信和对象
如果要在Ghost中进行数据库查询以获取,例如当前帖子,这是可能的,而不是困难的。您可以使用knex(https://knexjs.org/)之类的库,这是一个清晰而快速的SQL查询构建器。请记住,为此,您将需要车把 - 迅速携带者。正确配置KNEX以连接到Ghost的数据库。初始化knex为db变量,然后尝试以下代码:
//从数据库返回当前帖子标题 HB.RegisterHelper('post_title',async函数(options){ const uuid = options.hash.uuid; 尝试 { const {title} =等待db(“帖子”) 。选择(“标题”) 。 限制(1) 。第一的(); 返回标题; } catch(error){返回`错误:$ {error.message}`; } });
然后,在Ghost主题的post.hbs模板中,添加以下助手:\ {{post_title uuid =“ {{uuid}}}}}。在此示例中,{{uuid}}将被检索并作为幽灵中可用的助手,填充我们的助手的UUID字段,并导致自定义助手显示。
您还可以使用AXIOS向Ghost Content API提出HTTP请求,但这比直接数据库通信要慢得多。
实施体系结构- 表现
- 我知道,基于中间件的解决方案在速度方面可能不是最好的,但是我个人使用了此解决方案,并且没有注意到页面加载时间的大幅下降。单个请求的平均响应时间不到100ms(根据Express-STATUS-MONITOR),我使用一个自定义助手,该助手从每个页面上的数据库中检索一些值。
当然,您可以添加缓存机制来改善中间件性能或使用替代解决方案而不是Express-HTTP-Proxy。
使用Docker或其他容器化机制。我已经在项目中使用了它,而且效果很好。为Ghost,nginx和node.js图像添加幽灵和数据库图像。将它们连接到共享网络(驱动程序:桥),配置nginx和node.js Server - 非常简单!
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3