🚀

Flutter WebにヘッドレスCMSのSpearlyを埋め込んでコンテンツ管理する

2021/07/28に公開

以前にFlutterにヘッドレスCMSのSpearlyを組み込む話を紹介しました。
今回は、Flutter Webがstableで使えるようになったこともあり、Flutter Webに対してSpealryを組み込む検証記事です。

ヘッドレスCMSを組み込むことで、FAQやお知らせなどを特別な実装なく、アプリのアップデートをせずに更新が可能になります。

https://blog.hhg-exe.jp/flutter-spearly-serverless-development

Flutter Webの有効化

大半の人はFlutter Webが有効になっていないと思うので、こちらのドキュメントに沿ってFlutter Webを有効化します。

https://flutter.dev/docs/get-started/web

Flutter Webでのサイト制作上での困りごとはこちらに記載しています。

https://zenn.dev/qst/articles/c11c37a3531ce5476de7

Spearlyの準備

Spearlyについては、こちらの公式ドキュメントかQiitaの記事を参考にコンテンツの作成まで完了させます。

https://docs.spearly.com/cloud/withCms/c-1pmFAfSrvV5GnuyDbzQh

https://qiita.com/Yuta_spade/items/5f7067f6933e74061ff4

Spearlyの組み込み

今回はお手軽なjsタグを貼り付けて埋め込む方法で実装します。
Flutter WebはDartをJavaScriptにコンパイルすることで、SPAとしてWeb上に表示しているようです。
そのためカスタムタグを埋め込むことができない[1]ので、iframeを利用してローカルのHTMLを表示し、そのHTMLに独自タグを設置するように対応しました。

assets/index.html の設定

assets/index.html
<head>
    <!-- ここに貼るタグは公式ドキュメントを見てください -->
    <!-- チーム毎のAPIキーが表示されるので一部を隠しています -->
    <script src="https://static.spearly.com/js/cms.js" defer></script>
    <script>window.addEventListener('DOMContentLoaded',()=>{const t=document.querySelectorAll(':not(:defined)');for(const e of t) {e.style.visibility="hidden";}; window.spearly.config.AUTH_KEY="apiKey"},{once:true})</script>
</head>
<body>
<!-- ここに貼るタグは公式ドキュメントを見てください -->
<sample-list>
    <h1>{%= sample_title %}</h3>
    <p>{%= sample_description %}</p>
</sample-list>
</body>

https://news.spearly.com/release/c-XATOFUazRrtdeQBh2oul

pubspec.yamlの設定

pubspec.yaml
flutter:
  assets:
    - assets/index.html

main.dartの設定

main.dart
import 'dart:html' as html;
import 'dart:ui' as ui;

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  final String _viewId = 'spearly-content';

  
  Widget build(BuildContext context) {

    // ignore: undefined_prefixed_name
    ui.platformViewRegistry.registerViewFactory(
        _viewId,
        (int id) => html.IFrameElement()
          ..width = MediaQuery.of(context).size.width.toString()
          ..height = MediaQuery.of(context).size.height.toString()
          ..src = 'assets/index.html'
          ..style.border = 'none');

    return Scaffold(
      appBar: AppBar(
        title: Text(
          'Spearly Sample' 
        ),
      ),
      // iframeのサイズはこのSizedboxで調整します
      body: SizedBox(
        width: 500,
        height: 500,
        child: HtmlElementView(
          viewType: _viewId,
        ),
      ),
    );
  }
}

ビルド

ビルド時にはHTMLで書き出して欲しいので、以下のコマンドでビルドします。

https://flutter.dev/docs/development/tools/web-renderers#choosing-which-option-to-use

開発プレビュー時

$ flutter run -d chrome --web-renderer html

デプロイ時

$ flutter build web --release --web-renderer html

実際に作成したサイト

https://lp.hhg-exe.jp/

脚注
  1. 調査不足かもしれないので、カスタムタグが利用できる方法があればコメントで教えていただきたいです。 ↩︎

Discussion