简体   繁体   English

MEAN.js社交分享?

[英]MEAN.js Social Sharing?

So I built an app using MEAN.js, and I made some updates to the Articles (blog) section for better SEO, readability, design, etc. One problem I can't seem to figure out, though, is how to share the Articles using Facebook, Google+, Twitter, etc. and have them populate the right data using og meta tags. 所以我使用MEAN.js构建了一个应用程序,我对文章(博客)部分进行了一些更新,以获得更好的搜索引擎优化,可读性,设计等。但是,我似乎无法弄清楚的一个问题是,如何分享使用Facebook,Google +,Twitter等文章,让他们使用og meta标签填充正确的数据。

WHAT I WANT 我想要的是

All I want is to be able to share Articles (blog posts) from my MEAN.js application, and have the article content show up when I post the link in Social sites (eg Facebook). 我想要的是能够从我的MEAN.js应用程序共享文章(博客文章),并在我在社交网站(例如Facebook)中发布链接时显示文章内容。

WHAT I HAVE TRIED 我做了什么

I've tried creating a separate server layout specifically for blog posts, but this breaks so many other things that I realized the amount of work probably wasn't worth it - there has to be a smarter way. 我已经尝试专门为博客文章创建一个单独的服务器布局,但这打破了很多其他的东西,我意识到工作量可能不值得 - 必须有一个更聪明的方法。

I've also tried updating og meta tag data with Angular on the client side, but these values must not get updated before Social sites grab those tags...in other words, it didn't actually do what I wanted it to. 我也尝试在客户端使用Angular更新og元标记数据,但是在社交网站获取这些标记之前,这些值不能更新......换句话说,它实际上并没有按照我的意愿行事。

I've tried grabbing the Angular route URL when the index is rendering so I can update those og meta values before the index is rendered, but I can't find these values anywhere in the req data. 我已经尝试在索引呈现时抓取Angular路由URL,这样我可以在呈现索引之前更新这些og元值,但是我无法在req数据中的任何位置找到这些值。

WHAT I THINK THE PROBLEM IS 我认为问题是什么

Conceptually, this is what I believe is happening: 从概念上讲,这是我认为正在发生的事情:

  1. The request hits my server, but since it's a single page application using Angular's routing, the req.url value is simply the root page ('/'). 请求命中我的服务器,但由于它是使用Angular路由的单页应用程序,因此req.url值只是根页('/')。

  2. The index file gets loaded, which uses the standard server template layout. 加载索引文件,该文件使用标准服务器模板布局。

  3. Angular gets loaded and makes an AJAX call to get the Article data, then binds that data to the variables on the page. Angular被加载并进行AJAX调用以获取Article数据,然后将该数据绑定到页面上的变量。

So basically the layout is getting rendered (with the og meta values) before Angular even figures out what article information to grab. 所以基本上布局是在Angular甚至找出要抓取的文章信息之前渲染(使用og元值)。

WHAT I'M GUESSING THE IDEAL SOLUTION IS 我认为理想的解决方案是什么

In my express.js file, the app's local variables are set as follows: 在我的express.js文件中,应用程序的局部变量设置如下:

// Setting application local variables
app.locals.siteName = config.app.siteName;
app.locals.title = config.app.title;
app.locals.description = config.app.description;
app.locals.keywords = config.app.keywords;
app.locals.imageUrl = config.app.imageUrl;
app.locals.facebookAppId = config.facebook.clientID;
app.locals.jsFiles = config.getJavaScriptAssets();
app.locals.cssFiles = config.getCSSAssets();

These local variables are then rendered by Swig in the layout.server.view.html file as follows: 然后,这些局部变量由layout.server.view.htmllayout.server.view.html文件中呈现,如下所示:

// Note the {{keywords}}, {{description}}, etc. values. 
<!-- Semantic META -->
<meta id="keywords" name="keywords" content="{{keywords}}">
<meta id="desc" name="description" content="{{description}}">

<!-- Facebook META -->
<meta id="fb-app-id" property="fb:app_id" content="{{facebookAppId}}">
<meta id="fb-site-name" property="og:site_name" content="{{siteName}}">
<meta id="fb-title" property="og:title" content="{{title}}">
<meta id="fb-description" property="og:description" content="{{description}}">
<meta id="fb-url" property="og:url" content="{{url}}">
<meta id="fb-image" property="og:image" content="{{imageUrl}}">
<meta id="fb-type" property="og:type" content="website">

<!-- Twitter META -->
<meta id="twitter-title" name="twitter:title" content="{{title}}">
<meta id="twitter-description" name="twitter:description" content="{{description}}">
<meta id="twitter-url" name="twitter:url" content="{{url}}">
<meta id="twitter-image" name="twitter:image" content="{{imageUrl}}">

So ideally I think we want to update these values with Article specific information before rendering the page. 理想情况下,我认为我们希望在呈现页面之前使用特定于文章的信息更新这些值。 The problem is, if the layout gets rendered before Angular even figures out which article data to populate, how can I do this? 问题是,如果在Angular之前渲染布局甚至找出要填充的文章数据,我该怎么做? Again, the Angular route doesn't appear to be available anywhere in the req object, so I'm completely stumped on how to do this. 同样,Angular路径似乎在req对象中的任何位置都不可用,所以我完全不知道如何执行此操作。

So I go back to my original desire - how can I share my articles on social media in a "pretty" way using MEAN.js? 所以我回到原来的愿望 - 如何使用MEAN.js以“漂亮”的方式在社交媒体上分享我的文章? Am I on the right track? 我是在正确的轨道上吗? Is it possible with the current Article setup? 目前的文章设置是否可行? Do I need to build a complete blogging module that doesn't use Angular at all? 我是否需要构建一个完全不使用Angular的博客模块?

I finally got this working for my application without Nginx or anything else outside of the MEANJS framework. 我终于在没有Nginx或MEANJS框架之外的任何其他东西的情况下为我的应用程序工作了。 Your mileage may vary, but I thought I'd share the results anyway. 你的里程可能会有所不同,但我认为无论如何我都会分享结果。 It works for me, but may not for you. 它适用于我,但可能不适合你。

Basically what I already had setup was a way to grab non-hashed URLs and redirect to the hashed URLs. 基本上我已经设置的是一种获取非散列URL并重定向到散列URL的方法。 So a user could share their profile, eg example.com/myprofile and it would redirect to example.com/#!/profile/myprofile . 因此,用户可以共享他们的个人资料,例如example.com/myprofile ,它将重定向到example.com/#!/profile/myprofile

I then created a separate layout strictly for social bots (though in retrospect I'm not sure this was entirely necessary) and served the separate layout when the site is scraped. 然后我创建了一个严格用于社交机器人的单独布局(虽然回想起来我不确定这是完全必要的)并在网站被抓取时提供单独的布局。 This I do thusly: 我这样做:

social-layout.server.view.html 社会layout.server.view.html

...some stuff here...
//Note the variable names, e.g. {{siteName}}
<meta id="fb-app-id" property="fb:app_id" content="{{facebookAppId}}">
<meta id="fb-site-name" property="og:site_name" content="{{siteName}}">
<meta id="fb-title" property="og:title" content="{{socialTitle}}">
<meta id="fb-description" property="og:description" content="{{socialDescription}}">
<meta id="fb-url" property="og:url" content="{{socialUrl}}">
<meta id="fb-image" property="og:image" content="{{socialImageUrl}}">
<meta id="fb-type" property="og:type" content="website">

...other stuff here...

Then in my Express file, I explicitly check user-agents to determine if a new layout is necessary. 然后在我的Express文件中,我明确检查user-agents以确定是否需要新的布局。 If I find a bot, I fetch some key data related to the URL from my DB, then populate the variables, like so: 如果我找到机器人,我会从我的数据库中获取与URL相关的一些关键数据,然后填充变量,如下所示:

express.js express.js

// This code happens just after app.locals variables are set.
    // Passing the request url to environment locals
    app.use(function(req, res, next) {
        // Let's check user-agents to see if this is a social bot. If so, let's serve a different layout to populate the og data so it looks pretty when sharing.
        if(req.headers['user-agent'] === 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)' ||
            req.headers['user-agent'] === 'facebookexternalhit/1.0 (+http://www.facebook.com/externalhit_uatext.php)' ||
            req.headers['user-agent'] === 'facebookexternalhit/1.1 (+https://www.facebook.com/externalhit_uatext.php)' ||
            req.headers['user-agent'] === 'facebookexternalhit/1.0 (+https://www.facebook.com/externalhit_uatext.php)' ||
            req.headers['user-agent'] === 'visionutils/0.2' ||
            req.headers['user-agent'] === 'Twitterbot/1.0' ||
            req.headers['user-agent'] === 'LinkedInBot/1.0 (compatible; Mozilla/5.0; Jakarta Commons-HttpClient/3.1 +http://www.linkedin.com)' ||
            req.headers['user-agent'] === 'Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20110814 Firefox/6.0 Google (+https://developers.google.com/+/web/snippet/)' ||
            req.headers['user-agent'] === 'Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0 (via ggpht.com GoogleImageProxy)') {

            var urlAttempt = req.url;
            urlAttempt = urlAttempt.substr(1);

            Users.findOne({ link: urlAttempt }, function(err, results) {
                if(err) {
                    res.locals.url = req.protocol + '://' + req.headers.host;
                    next();
                } else if (results !== null) {
                    // Found link. Populate data.
                    res.status(200).render('social-index', {

                        // Now we update layout variables with DB info.
                        socialUrl: req.protocol + '://' + req.headers.host + req.url,
                        socialTitle: results.orgName,
                        socialDescription: results.shortDesc,
                        socialImageUrl: req.protocol + '://' + req.headers.host + '/profile/img/' + results.imgName
                    });
                } else {
                    res.locals.url = req.protocol + '://' + req.headers.host;
                    next();
                }
            });
        } else {
            res.locals.url = req.protocol + '://' + req.headers.host;
            next();
        }
    });

Again, your mileage may vary, but this worked for me (partially). 同样,您的里程可能会有所不同,但这对我(部分)有用。 I'm still working on social sharing the whole URL (including the hash). 我还在努力社交分享整个网址(包括哈希)。 Hope it helps in some way. 希望它在某种程度上有所帮助。

I've faced the same problem. 我遇到了同样的问题。 First I installed Mean-Seo module. 首先我安装了Mean-Seo模块。 You can find it on mean.js official github repo. 你可以在mean.js官方github repo上找到它。 Module is essentially doing this: Crawlers (Google etc.) adds an _escaped_fragment_ part to their requests when they encounter a SPA URL. 模块本质上是这样做的:Crawlers(Google等)在遇到SPA URL时会在其请求中添加_escaped_fragment_部分。 Mean-Seo intercepts requests which includes _escaped_fragment_ . Mean-Seo拦截包含_escaped_fragment_请求。 Then using Phantom.Js, renders a static HTML out of dynamic one and saves it, serve this static version to crawlers. 然后使用Phantom.Js,从动态HTML中提取静态HTML并保存它,将此静态版本提供给爬虫。

For Facebook & Twitter, I changed mean-seo.js file of Mean-Seo, and before it caches and saves the static file I replaced meta tags accordingly. 对于Facebook和Twitter,我更改了Mean-Seo的mean-seo.js文件,在它缓存并保存静态文件之前,我相应地替换了元标记。 Since Phantom.Js already rendered whole article page, so you do not need to make another API call. 由于Phantom.Js已经呈现了整篇文章页面,因此您无需再进行其他API调用。 Just parse the HTML. 只需解析HTML。 I also used cheerio.js to parse HTML conveniently. 我还使用cheerio.js来方便地解析HTML。

This kind of solved my problem, but not perfectly. 这种解决了我的问题,但并不完美。 I'm still struggling with the hashbang & HTML5 mode. 我仍然在使用hashbang和HTML5模式。 When my URL is like https://example.com/post/1 Twitter and Facebook do not request _escaped_fragment_ . 当我的网址类似于https://example.com/post/1 Twitter和Facebook不会请求_escaped_fragment_

Update: After a while, I abandoned this aprroach. 更新:过了一会儿,我放弃了这个方法。 Phantomjs seems unreliable and I didn't like to waste system resources, CPU time, RAM, disk space for such a job. Phantomjs似乎不可靠,我不喜欢为这样的工作浪费系统资源,CPU时间,RAM,磁盘空间。 Unnecessary file creation is also silly. 不必要的文件创建也很愚蠢。 My current approach is like this: 我目前的做法是这样的:

I've added a new express route for Twitter and Facebook. 我为Twitter和Facebook添加了一条新的快速路线。 In the server controller, implemented a new function for crawler. 在服务器控制器中,为crawler实现了一个新功能。 Created a simple server template without Angular, Bootstrap and all that shiny things: Only meta tags and simple text. 创建了一个简单的服务器模板,没有Angular,Bootstrap和所有闪亮的东西:只有元标记和简单文本。 Using Swig (already included in Meanjs), rendered this view template accordingly. 使用Swig (已包含在Meanjs中),相应地渲染此视图模板。 I'm also using Nginx as a proxy. 我也使用Nginx作为代理。 So I defined a new Nginx rewrite based on user agent. 所以我根据用户代理定义了一个新的Nginx rewrite Something like this: 像这样的东西:

if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
    rewrite ^/posts/(.*)$ /api/posts/crawl/$1 last;
    }

When a crawler request a post's URL, Nginx triggers my new simple crawler route and gets generated tiny page. 当爬虫请求帖子的URL时,Nginx触发我的新简单爬虫路由并生成小页面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM