yagish履歴書で今後のアップデートのお知らせ用にはてなブログProを利用しようと考えている。
rirekisho.yagish.jp
(関係ないけどはてブ800超えてうれしい)
もちろんRSSがあるので、これをVue.jsアプリ内で読み込んでもいい。
でも、RSSとかXMLとかを扱うとなると、クライアント側にそれだけのためにライブラリがいくつも必要になる。
せっかくLighthouse対策でjsを減らすのがんばったのに嫌。
そこでCloud Functionsを使って、jsonに変換して返せないか考えた。
そうすれば、もともと使っているaxiosだけで済むし、コードも減るし、使いやすい。
まず、RSSをJSONに変換するのはそのまんまのライブラリがあった。
すごいシンプルで言うことない。
次にajaxで読み込むのでCORS対策。
Firebase HostingでCloud Functionsにリライトして接続すれば同一ドメインになるのでいらない。
Cloud Functions による動的コンテンツの配信 | Firebase
でも今回はローカルでもテストしやすいのでCORSで許可することにした。
検索したらまさにのstackoverflowがあった。
stackoverflow.com
複数ドメインを動的に処理するのはcorsのドキュメントにあったのを使う。
github.com
これを組み合わせたのが下記。
これをCloud Functionsに作ってHTTPトリガーでデプロイする。
RSSの量によるかもだけどメモリは128MBでも良さげ。
Cloud FunctionsはCDNを通してるのでCache-Controlをつけておけば爆速で返せるので成功時だけつけておく。
期限は必要に応じてもっと短くてもいいかも。
res.set('Cache-Control', 'public, max-age=300, s-maxage=600');index.js
const Feed = require('rss-to-json');
const RssURL = 'https://blog.yagish.jp/rss';
const whitelist = ['http://192.168.0.1', 'https://rirekisho.yagish.jp/']
const corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
const cors = require('cors')(corsOptions)
/**
* Responds to any HTTP request.
*
* @param {!Object} req HTTP request context.
* @param {!Object} res HTTP response context.
*/
exports.RssToJson = (req, res) => {
Feed.load(RssURL, function(err, rss){
cors(req, res, () => {});
if(err){
res.status(503).send(err);
}else{
res.set('Cache-Control', 'public, max-age=300, s-maxage=600');
res.status(200).send(rss);
}
});
};package.json
{
"name": "sample-http",
"version": "0.0.1",
"dependencies": {
"rss-to-json": "^1.0.4",
"cors": "^2.8.4"
}
}whitelistを変えてみてエラーになったり、ならなかったりを確認した。
元のRSS
https://blog.yagish.jp/rss
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>yagishのブログ</title>
<link>https://blog.yagish.jp/</link>
<description></description>
<lastBuildDate>Wed, 18 Jul 2018 18:36:13 +0900</lastBuildDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>Hatena::Blog</generator>
<item>
<title>バックアップ機能アップデートのお知らせ</title>
<link>https://blog.yagish.jp/entry/2018/07/18/183613?utm_source=feed</link> <description><p>バックアップ機能アップデートのお知らせ</p>
</description> <pubDate>Wed, 18 Jul 2018 18:36:13 +0900</pubDate>
<guid isPermalink="false">hatenablog://entry/10257846132602357979</guid>
<enclosure url="https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png" type="image/png" length="0" />
</item>
</channel>
</rss>こんなのが返ってきた。まだ記事数も文章もないので速度は速い。
{
"items": [
{
"title": "バックアップ機能アップデートのお知らせ",
"description": "<p>バックアップ機能アップデートのお知らせ</p>",
"link": "https://blog.yagish.jp/entry/2018/07/18/183613?utm_source=feed",
"url": "https://blog.yagish.jp/entry/2018/07/18/183613?utm_source=feed",
"created": 1531906573000,
"enclosures": [
{
"url": "https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png",
"type": "image/png",
"length": "0"
}
]
}
],
"title": "yagishのブログ",
"description": "",
"url": "https://blog.yagish.jp/",
"image": ""
}pubDateはタイムスタンプに変換されcreatedという名前になってる。
こういうクライアント側でもできなくはないけど、サーバーでやった方がユーザー&クライアント側に優しいものにCloud Functionsは最適なので今後も使い所を探していこうと思う。
2018/07/23追記
Python3.7が使えるようになったので作ってみた
uyamazak.hatenablog.com
- 作者: 吉積礼敏,福田潔
- 出版社/メーカー: インプレスR&D
- 発売日: 2016/03/25
- メディア: Kindle版
- この商品を含むブログを見る
- 作者: 阿佐志保,中井悦司
- 出版社/メーカー: 翔泳社
- 発売日: 2017/06/02
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る