我的最终目标是从移动应用程序(在React Native中,它显示WebView组件中的帖子)消费存储在WordPress网站中的帖子,要做到这一点,我需要以某种方式获得帖子的足够成熟的html内容,而不需要WordPress主题相关的东西,如页眉、页脚、侧边栏。
我对成熟的html是什么意思?好吧,让我谈谈我遇到的问题。
我尝试简单地使用get_post($postID)->post_content
检索post html(之后我还尝试直接调用JSON WordPress REST API,但结果相同)。由于缺少一些CSS和JavaScript,React并不总是能很好地呈现这个html,当我使用一些WordPress插件将自定义内容添加到帖子中时,就会发生这种情况。当我使用高级WordPress插件UniteGallery将照片库添加到帖子中时,我意识到了这一点,当React呈现帖子的JSON版本时,它根本不显示照片库,而是显示红色消息(在正常HTML内容中):UniteGallery css & scripts missing, check if your template includes wp_footer().
因此,我在普通浏览器中打开了显示相同帖子的完整网页,并将此HTML与JSON版本1进行了比较
首先我注意到了大小的差异:网页几乎是2MB,JSON版本大约是20KB。出于这个原因,我想避免这样的解决方案,即(React)应用程序应该下载整个网页,并在注入CSS后隐藏网站主题相关的东西,如标题、菜单、侧边栏和页脚
相反,我想准备(服务器端)html(而不是超尺寸),以便应用程序可以按原样使用它。
我发现巨大的HTML可以从逻辑上分为4个块:
- BLOCK1:很多与主题相关的东西:样式定义(超过70%的内容)和不需要的主题标题
- BLOCK2:发布内容(几乎与JSON版本一相同)
- BLOCK3:小部件和页脚的不需要的侧边栏(与主题模板相关的东西)
- BLOCK4:css导入、javascript导入和一些javascript块
遵循"巨大HTML"的摘录:
<!DOCTYPE html>
<html>
<!-- ********* BLOCK1 STARTS ********* -->
<head>
<title>Post Title</title>
<!-- several theme-related meta and css link tags -->
<!-- few theme-related javasdcript blocks and imports-->
<!-- REACT-RENDER REQUIREMENT no. 1: 2 jQuery imports -->
<script type='text/javascript' src='https://example.com/wp-includes/js/jquery/jquery.min.js?ver=3.5.1' id='jquery-core-js'></script>
<script type='text/javascript' src='https://example.com/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.3.2' id='jquery-migrate-js'></script>
<style id="fusion-stylesheet-inline-css" type="text/css">
/* = = = = = > HUGE REACT-UNUSED theme-related CSS BLOCK < = = = = = */
</style>
</head>
<body>
<!-- SURELY UNWANTED HEADER related stuff -->
<!-- ********* BLOCK1 ENDS ********* -->
<!-- ********* BLOCK2 STARTS: THE_CONTENT ********* -->
<article id="post-1234" class="post post-1234 type-post status-publish">
<h1 class="entry-title">Post Title</h1>
<div class="video-shortcode">
<iframe title="YouTube video player" src="https://www.youtube.com/embed/Suib_DXOj0E?wmode=transparent&autoplay=0" width="800" height="450" allowfullscreen allow="autoplay; fullscreen"></iframe>
</div>
<div class="fusion-fullwidth" style="padding:0px;margin: 0px;border-width: 0px 0px 0px 0px;border-style:solid;">
<p><strong>Photo Gallery1 Title</strong></p>
<div id='unitegallery_1_1' class='unite-gallery' style='margin:0px auto;'>
<img alt="_FCO0020" src="" data-image="https://example.com/wp-content/uploads/FCO0020.jpg" data-thumb="https://example.com/wp-content/uploads/FCO0020-300x200.jpg" title="" style="display:none">
<img alt="_FCO0022" src="" data-image="https://example.com/wp-content/uploads/FCO0022.jpg" data-thumb="https://example.com/wp-content/uploads/FCO0022-300x200.jpg" title="" style="display:none">
<!-- FOLLOWS A LOT OF PICTURES OF THE PHOTO-GALLERY -->
</div>
<!-- Follows the Javascript block the check the presence of UniteGallery library, and display the red error -->
<script type='text/javascript'>
window.onload = function (e) {
if (typeof ugCheckForErrors == "undefined") {
document.getElementById("unitegallery_1_1").innerHTML =
"<span style='color:red'>Unite Gallery Error - gallery js and css files not included in the footer. Please make sure that wp_footer() function is added to your theme.</span>";
}
else { ugCheckForErrors("unitegallery_1_1", "jquery"); }
};
</script>
</div>
</article>
<!-- *** BLOCK2 ENDS *** -->
<!-- *** BLOCK3 STARTS *** -->
<aside id="sidebar" class="sidebar fusion-blogsidebar" style="float: right;">
<!-- SURELY UNWANTED SIDEBAR related stuff-->
</aside>
<div class="fusion-footer">
<!-- SURELY UNWANTED FOOTER related stuff-->
</div>
<!-- *** BLOCK3 ENDS *** -->
<!-- *** BLOCK4 STARTS *** -->
<div class="avada-footer-scripts">
<!-- some theme-related css link -->
<!-- REACT-RENDER REQUIREMENT no. 2: UniteGallery CSS link -->
<link rel='stylesheet' id='unite-gallery-css-css' href='https://example.com/wp-content/plugins/unitegallery/unitegallery-plugin/css/unite-gallery.css?ver=5.7.2' type='text/css' media='all' />
<!-- many theme-related imports and javascript blocks -->
<!-- REACT-RENDER REQUIREMENT no. 3: UniteGallery JS imports -->
<script type='text/javascript' src='https://example.com/wp-content/plugins/unitegallery/unitegallery-plugin/js/unitegallery.min.js?ver=5.7.2' id='unitegallery_main-js'></script>
<script type='text/javascript' src='https://example.com/wp-content/plugins/unitegallery/unitegallery-plugin/themes/tiles/ug-theme-tiles.js?ver=5.7.2' id='unitegallery_tiles_theme-js'></script>
<!-- REACT-RENDER REQUIREMENT no. 4: UniteGallery gallery unhiding -->
<script type='text/javascript'>
var ugapi1;
jQuery(document).ready(function () {
var objUGParams = {
gallery_theme: "tiles",
gallery_width: "100%",
tiles_type: "nested"
};
if (ugCheckForErrors('#unitegallery_1_1', 'cms'))
ugapi1 = jQuery('#unitegallery_1_1').unitegallery(objUGParams);
});
</script>
</div>
<!-- *** BLOCK4 ENDS *** -->
</body>
</html>
因此,我尝试将上面代码中用注释突出显示的行(CSS&JavaScript)作为REACT-RENDER REQUIREMENT
附加到帖子的JSON版本中(对这些行进行硬编码),然后React正确地渲染帖子中的照片库。照片库已经存在,但被隐藏(样式为display:none
),由CSS&我手动添加的JavaScript内容
注意我添加了以下必需行:
- 2从BLOCK导入jQuery
- UniteGallery从BLOCK 4导入和javascript而BLOCK 4中并不是所有的css和javascript都需要来获得一个有效的UniteGallery照片库:大多数都是与网站主题相关的东西
为了系统地将缺失的插件相关内容添加到HTML中,我尝试了如下操作:
ob_start(); // <- buffer following outputs
wp_head(); // <- output header stuff
$post = new WP_Query('p ='. $postID);
if ($post->have_posts()) $post->the_post(); // <- output post content
wp_footer(); // <- output footer stuff
$full_post_content = ob_get_contents(); // get the output buffer
ob_end_clean(); // <- clear buffer and stop buffering
// -> save $full_post_content to DB table 'app_posts'
通过这种方式,帖子的内容用UniteGallery CSS&JavaScript导入,但仍然缺少jQuery导入(请参见上面的BLOCK1)和UniteGallery JavaScript块,该块取消隐藏照片库(请参见以上BLOCK4的末尾),然后帖子中的照片库仍然不显示。
我在使用UniteGallery时遇到了这个问题,但实际上我认为,如果帖子的内容由JSON-REST-API检索,那么任何将自定义内容添加到帖子中的插件都可能产生React无法正确呈现的帖子内容。
出于这个原因,我正在寻找这样一种方式(例如在我的自定义WordPress插件中)来保存包含的帖子的HTML版本:
- light帖子内容的JSON版本
- CSS&JavaScripts需要在React中正确地呈现这样的帖子,考虑到涉及丰富帖子内容的插件
这就是我在问题开始时的意思,">帖子的HTML内容足够成熟">
显然,我不知道是否有内置的WordPress工具/API可以实现这一点,但我愿意开发这样的自定义插件,以方便用户WordPress内容管理器的工作。
如果我理解正确,你想在react应用程序中显示你在WordPress网站上的现有帖子,那么应该这样做:
一点理论
主题和插件负责在WordPress网站的客户端显示UI(html,css,js)。对于显示帖子,很可能是你的主题负责(如果你不使用构造函数插件或其他插件)主题是一组php文件,其中包括页眉、正文和页脚以及其他区域。每个帖子类型都有自己的模板,(取决于主题)但本质总是一样的,这是显示当前帖子的php代码,其中包括各种脚本和样式,对于插件来说,这是很多脚本、样式和php。。那我为什么要写这个??事实上,从中间拉出一些东西几乎是不可能的!
为什么它很糟糕而且很难做到(在react应用程序中显示带有所有样式和脚本的完成html):
- 你肯定会在脚本中发生冲突
- 你不会有一个你想要的轻量级页面,你肯定需要加载很多不同的脚本,例如jQuery,因为它肯定会在wordpress中使用
- 这是一种困难和错误的方式
现在你能做什么:
解决方案
-
正确的方法:使用REST API Wordpress我建议忘记在你的网站上显示你的帖子,制作你自己的html和css模板,并将其转换为react模板。当加载你的反应页面并呈现你的帖子时,动态地从WordPress api中提取数据。参见REST API wordpress文章
-
第二种方式,它是快速的方式,但不方便用户使用iframe
你可以在iframe中显示你的整个帖子页面,它的重量也会很重,因为整个页面都会被加载,你不能隐藏页脚和页眉,因为脚本通常加载在页脚中,你所能做的就是在你的页面以iframe打开时,借助css将它们隐藏起来,例如:
你可以在你的帖子链接中添加一个get参数,表示链接在iframe中打开:your.site/posts/123?iframe_mode=true
然后打开header.php模板并在其中添加以下代码:
<html <?php language_attributes(); ?> class="no-js no-svg <?php $s=''; if(isset($_GET['iframe_mode'])) {$s="iframe-mode"} print $s; ?>">
现在编写您想从iframe 中隐藏的css规则
.iframe-mode .my-navbar {display: none}
/*... etc*/
您还可以从模板输出中隐藏不需要的部分(而不是页脚!)
<php if(!isset($_GET['iframe_mode'])): ?>
<?php get_template_part( 'template-parts/header/site-header' ); ?>
<?php endif; ?>
结论
总的来说,我建议你第一个选择!Wordpress会像它一样工作,你只需打开帖子的rest api,如果它关闭了,并在你的react应用程序中使用它,提取数据并在react应用中渲染,而不使用Wordpress中的html和其他东西,只有JSON数据!祝你好运