Pug编译HTML前跨模板执行函数 实现索引页展示项目阅读时长
问题解答
完全不需要把项目改造成Express项目,你现在用的Gulp+Pug静态构建栈本身就能实现这个需求。你之前的方案走不通的根本原因是:阅读时长的计算逻辑写在前端JS里,只有用户打开对应详情页的时候,才会去查DOM、算时长,数据存在当前页面的内存里,索引页加载的时候既碰不到详情页的DOM,也拿不到别的页面算出来的结果,自然没法展示。
实现步骤
把计算逻辑从浏览器端挪到Gulp编译阶段,所有Pug渲染前就把所有项目的阅读时长算完存好,再把数据传给所有模板用就行:
- 先改计算函数,去掉浏览器DOM依赖
你原来的函数靠document.getElementsByClassName拿内容,Node环境里没有document,改成直接接收纯文本返回结果的纯函数就可以在构建时用:// 直接写在gulpfile.js里,构建的时候直接调用 const calculateReadTime = (plainTextContent) => { const wordCount = plainTextContent.replace(/[^\w ]/g, "").split(/\s+/).length; const readingTimeInMinutes = Math.floor(wordCount / 228) + 1; return `${readingTimeInMinutes} minute read`; } - 编译前批量算完所有项目的时长
在跑Pug编译任务之前,先遍历所有项目的内容:- 要是你已经把项目标题、正文、slug这些信息抽成单独的JSON/JS数据文件存着,就直接读每个项目的正文内容,丢进上面的函数算时长,结果存在一个普通对象里就行,key用项目唯一标识(比如你之前用的
project-one类名、项目路径slug都可以),value就是算出来的时长字符串。 - 要是你现在的项目内容都是直接写在Pug模板里没抽出来,就先在构建时用cheerio这类Node端的DOM解析库,读一下每个详情页渲染后的HTML,提取对应项目容器的文本算时长,再存到结果对象里就行。
- 要是你已经把项目标题、正文、slug这些信息抽成单独的JSON/JS数据文件存着,就直接读每个项目的正文内容,丢进上面的函数算时长,结果存在一个普通对象里就行,key用项目唯一标识(比如你之前用的
- 把算好的时长数据传给所有Pug模板
配置gulp-pug的编译参数,把存了全量项目时长的对象作为全局变量传给所有模板,渲染的时候直接取值就行:- 索引页循环渲染每个项目条目的时候,直接按项目id拿对应的时长插进去,访客一进索引页就能看到每个项目要读多久
- 详情页也不用再留前端查DOM算时长的逻辑了,直接拿当前项目的时长渲染到对应位置就行,还能省点前端JS的运行开销。
别想着用localStorage存前端算出来的时长凑合用,那玩意儿得用户把每个详情页都点开过才能攒全数据,新用户第一次开索引页啥都看不到,体验非常差。
内容的提问来源于stack exchange,提问作者user2588166
相关产品推荐
相关产品推荐

