【发布时间】:2021-08-13 13:50:20
【问题描述】:
我创建了一个 SPA - 使用 Angular 11 的单页应用程序,我将其托管在共享托管服务器上。
我遇到的问题是我无法在社交媒体(Facebook 和 Twitter)上分享我拥有的任何页面(除了第一条路线 - /),因为元标记没有更新(我有一个服务正在根据请求的页面处理每个页面的元标记)(我知道这是因为 Facebook 和 Twitter 没有抓取 JavaScript)。
为了解决这个问题,我尝试了 Angular Universal(SSR - 服务器端渲染)和 Scully(创建静态页面)。两者(Angular Universal 和 Scully)都在解决我的问题,但我更喜欢使用默认的 Angular SPA 构建。
我正在采取的方法:
- 文件结构(共享主机服务器/public_html/):
- crawlers/
- crawlers.php
- share/
- 404.json
- about.json
- work.json
- .htaccess
- index.html
- crawlers.php 包含以下内容:
<?php
$page = filter_input(INPUT_GET, 'page');
if (file_exists('./share/'.$page.'.json')) {
$file = file_get_contents('./share/'.$page.'.json');
} else {
$file = file_get_contents('./share/404.json');
}
$data = json_decode($file);
return makePage($data);
function makePage($data) {
$html = '<!doctype html>'.PHP_EOL;
$html .= '<html>'.PHP_EOL;
$html .= '<head>'.PHP_EOL;
$html .= '<meta property="og:type" content="website" />'.PHP_EOL;
$html .= '<meta property="og:site_name" content="My Website" />'.PHP_EOL;
$html .= '<meta property="og:title" content="'.$data->title.'" />'.PHP_EOL;
$html .= '<meta property="og:description" content="'.$data->description.'" />'.PHP_EOL;
$html .= '<meta property="og:image" content="'.$data->image.'" />'.PHP_EOL;
$html .= '<meta name="twitter:card" content="summary_large_image"/>'.PHP_EOL;
$html .= '<meta name="twitter:title" content="'.$data->title.'" />'.PHP_EOL;
$html .= '<meta name="twitter:description" content="'.$data->description.'" />'.PHP_EOL;
$html .= '<meta name="twitter:image" content="'.$data->image.'" />'.PHP_EOL;
$html .= '<meta http-equiv="refresh" content="0;url='.$data->url.'">'.PHP_EOL;
$html .= '</head>'.PHP_EOL;
$html .= '<body></body>'.PHP_EOL;
$html .= '</html>';
echo $html;
}
?>
og:url 未指定,因为我认为如果不指定它,Facebook 将不知道实际的内容 URL,并将其卡片链接到静态文件。这应该不是问题,因为我使用了http-equiv="refresh",它将普通用户重定向到正确的 URL。
- 例如,404.json 包含以下内容:
{
"title": "404: Not Found | My Website",
"description": "My awesome description.",
"image": "https://www.mywebsite.com/assets/images/share/404.jpg",
"url": "https://www.mywebsite.com",
}
- .htaccess 包含以下内容:
RewriteEngine On
RewriteBase /
# Allow robots.txt to pass through
RewriteRule ^robots.txt - [L]
# Allow social media crawlers to work
RewriteCond %{HTTP_USER_AGENT} (facebookexternalhit/[0-9]|Twitterbot)
RewriteRule ^(.+)$ /crawlers/crawlers.php?page=$1 [NC,L]
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist use index.html
RewriteRule ^ /index.html
当我测试 crawlers/crawlers.php?page=test-page 时,它运行良好(在访问 https://www.mywebsite.com/crawlers/crawlers.php?page=test-page 之后),我认为问题出在 # Allow social media crawlers to work 下面的 .htaccess 条件中的原因。在 Facebook 上分享仍然显示第一个路由 (/) 的元标记,这意味着重定向到 crawlers/crawlers.php 不起作用。
另外,https://developers.facebook.com/tools/debug/sharing/ 上的 URL https://www.mywebsite.com/about 不会重定向到 https://www.mywebsite.com/crawelers/crawlers.php?page=about。
我想将重定向到 crawlers/crawlers.php 的社交媒体爬虫仅用于以下页面:https://www.mywebsite.com/about、https://www.mywebsite.com/work 等,但不适用于https://www.mywebsite.com(第一条路线 - /)。
非常感谢任何帮助。谢谢!
【问题讨论】:
-
你为什么首先尝试通过 external 重定向来处理这个问题?
-
@CBroe 如果不使用 Angular Universal(或 Scully、Prerender.io 等),我不知道有任何其他方法可以处理此问题。
-
但这与外部重定向与内部重定向有什么关系?您的
crawlers.php脚本“存在”在 Web 服务器上的同一域设置中,不是吗?外部重定向会产生问题,因为 Facebook 会认为这意味着 this 是您实际想要分享的 URL。如果您将原始 URL 设置为og:url值,那么 Facebook 将再次请求 那个,因此您最终将进入重定向循环。 -
@CBroe 我不明白您建议进行哪些更改。我将
.htaccessRewriteRule ^/(.*)$ https://www.mywebsite.com/crawlers/crawlers.php?page=$1 [R=301,L]更改为RewriteRule ^/(.*)$ /crawlers/crawlers.php?page=$1 [NC,L]。另外,我从crawlers.php中删除了og:url和canonical。我认为这样做 Facebook 将不知道实际的内容 URL,并将其卡片链接到静态文件。这应该不是问题,因为我使用了http-equiv="refresh",它将普通用户重定向到正确的 URL。但是,它不起作用... -
我猜重写本身一开始就不起作用?当您在 .htaccess 中配置重写时,与 never 匹配的路径 RewriteRule 以一个前导斜杠开头,此时该斜杠已被剥离。
标签: angular facebook .htaccess mod-rewrite meta-tags