Facebook Like Button 在 Angular App 中的宽度为 0

Facebook Like Button has width 0 in Angular App

TL;DR

我插入了 Meta Developers Page for a Facebook Like Button generated into this CodePen 但 Button 不显示的确切代码(宽度和高度均为 0px)

目标

在我们的 Angular 12 应用程序中,我们希望在视频下包含三个内容:

我为它们中的每一个都创建了组件,它们会触发将脚本标记写入 DOM 以获取 JS 库(我们使用 NGXS 进行异步操作)。

facebook-分享-button.component.ts

const SCRIPT_ID = 'facebook-share-button';

@Component(...)
export class FacebookShareButtonComponent implements AfterViewInit, OnDestroy {
  @Select((state) => state.router.state.fullUrl) fullUrl$: Observable<string>;

  constructor(private store: Store) {}

  ngAfterViewInit() {
    this.store.dispatch(
      new CoreActions.LoadScript(
        SCRIPT_ID,
        'https://connect.facebook.net/de_DE/sdk.js#xfbml=1&version=v12.0',
        { async: true }
      )
    );
  }

  ngOnDestroy() {
    this.store.dispatch(new CoreActions.RemoveScript(SCRIPT_ID));
  }
}

facebook-分享-button.component.html

<div class="facebook-share-button">
  <div id="fb-root"></div>
  <div
    class="fb-share-button"
    [attr.data-href]="fullUrl$ | async"
    data-layout="button"
    data-size="large"
  ></div>
</div>

问题

Facebook 分享按钮和 Pinterest Pin 按钮工作正常,只有 Facebook 点赞按钮不显示。它的宽度和高度为 0px

完整代码

类似facebook-button.component.ts

import { AfterViewInit, Component, OnDestroy } from '@angular/core';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { CoreActions } from 'src/app/core/core.actions';

const SCRIPT_ID = 'facebook-like-button';

@Component({
  selector: 'app-facebook-like-button',
  templateUrl: './facebook-like-button.component.html',
  styleUrls: ['./facebook-like-button.component.styl'],
})
export class FacebookLikeButtonComponent implements AfterViewInit, OnDestroy {
  @Select((state) => state.router.state.fullUrl) fullUrl$: Observable<string>;

  constructor(private store: Store) {}

  ngAfterViewInit() {
    this.store.dispatch(
      new CoreActions.LoadScript(
        SCRIPT_ID,
        'https://connect.facebook.net/de_DE/sdk.js#xfbml=1&version=v12.0',
        { anonymous: true, nonce: '4j5id3DJ' }
      )
    );
  }

  ngOnDestroy() {
    this.store.dispatch(new CoreActions.RemoveScript(SCRIPT_ID));
  }
}

类似facebook-button.component.html

<div class="facebook-like-button">
  <div id="fb-root"></div>
  <div
    class="fb-like"
    [attr.data-href]="fullUrl$ | async"
    data-width="77"
    data-layout="standard"
    data-action="like"
    data-size="large"
    data-share="false"
  ></div>
</div>

我尝试过的东西

  1. 删除 facebook-share-button 组件(可能是两个脚本相互干扰)
  2. 将代码放在 ngOnInit() 中(而不是 ngAfterViewInit()
  3. 设置静态 data-href 属性(即删除异步管道)
  4. 删除 facebook-share-button.component.htmlfacebook-like-button.component.html 或两者中的 <div id="fb-root"></div>
  5. <div id="fb-root"></div> 移动到 app.component.html
  6. 尝试 .fb-like 的选项并一一删除它们
  7. 在脚本标签中将 asyncdefercrossorigin 设置为不同的值
  8. 其他浏览器和停用 AdBlockers
  9. 手动包含脚本标签
  10. 在 Whosebug 上搜索有类似问题的人
  11. 以上所有的组合

但没有任何效果。

最后,我将 developers.facebook.net 提供的确切代码包含到 app.component.html 中,但仍然无法正常工作。我尝试在 Codepen 中输入它(见上文),但仍然没有按钮!

我觉得有点傻。我在这里做一些根本性的错误......? 你能帮忙吗?

你分享的 Codepen 在 Google Chrome 但只在 Chrome.

在 Safari 和 Firefox 上,我遇到 内容安全策略 问题。

内容安全策略

问题是由于 Content Security Policy (a.k.a CSP):

Instead of blindly trusting everything that a server delivers, CSP defines the Content-Security-Policy HTTP header, which allows you to create an allowlist of sources of trusted content, and instructs the browser to only execute or render resources from those sources. Even if an attacker can find a hole through which to inject script, the script won't match the allowlist, and therefore won't be executed.

因此您需要在您的网站上允许 facebook 路径(用于提供脚本)。

Facebook 要求的列表很长,而且随着时间的推移不断增加,从 this page 开始,您应该添加如下内容:

script-src
  https://connect.facebook.net
  https://graph.facebook.com
  https://js.facebook.com;
style-src
  'unsafe-inline';
frame-src
  *.facebook.com
  connect.facebook.net;
child-src
  *.facebook.com
  connect.facebook.net;
img-src
  data:
  *.facebook.com
  *.facebook.net
  *.fbcdn.net;
font-src
  data:;
connect-src
  *.facebook.com
  connect.facebook.net;
form-action
  *.facebook.com
  connect.facebook.net;

需要将以上这些值添加到您的站点默认值中,它应该如下所示:

Content-Security-Policy: default-src 'self'; img-src *; child-src: *

More documentation on the CSP from Mozilla Docs.

有用的链接:

通过 HTML 标签设置 CSP <meta>

您可以通过HTML <meta>设置CSP,例如:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

请注意,如果您在网站中设置多个 <meta http-equiv=... <head>,则只会使用最后一个,其他的将被忽略。

广告拦截器,另一个潜在问题

如果您有像 EFF Privacy BadgeruBlock(uBlock Origin)这样的广告拦截器,您将需要禁用这些扩展程序或取消阻止站点,然后重新加载代码笔。

使用广告拦截器的用户将看不到您的按钮,因为他们进行的 JS 调用将被阻止,在 Google Chrome 您将看到 net::ERR_BLOCKED_BY_CLIENT.