Scratch-guiのデフォルトプロジェクトのアセット置き場を変える方法


※ 当ページには【広告/PR】を含む場合があります。
2020/11/01



以前、
独自のScratchアプリをAWS S3から公開するための方法 を解説しました。
実際にはまだ画像ファイルなどのアセットファイルの置き場所に少し課題がありました。
今回はさらに突っ込んで、このアセットファイルの置き場所を変更するための手順を深堀してみようと思います。


合同会社タコスキングダム|蛸壺の技術ブログ【Pschool厳選】Scratchを学べるオンライン・駅前プログラミングスクール5選

はじめに



以前、Scratch3.0の開発者向けのソースコードプロジェクト
scratch-gui を解説しました。
課題としてデフォルトプロジェクトを置き換えただけでは、画像データや音源はscratchの共有アセット置き場(
https://assets.scratch.mit.edu/internalapi/asset )に置かれてしまうようです。

合同会社タコスキングダム|蛸壺の技術ブログ


これはscratch3では原則として
scratch.mit.edu (クラウド側)への保存しなければならない仕様のためです。
簡単に言ってしまうと、Scratchの公式サイトにアップロードされたファイルは全て問答無用でみんなの財産として扱われます。
この辺がScratchアプリ開発の悩ましい問題で、最近の更新された
ぴぽや倉庫さんの利用規約 のScratchの項目が分かりやすいと思います。
ライセンス付きの有料の画材を購入した人がそれを使ってScratch3のアプリを公式サイトから公開してしまった場合、
画材の購入元の利用規約によっては規約違反 になってしまいます。
大抵の場合には、購入した画材の利用規約に従えばよいのですが、中にはクリエイティブ・コモンズなどの面倒なライセンスが付いているものもあります。
Scratch3は三条項BSDライセンス(BSD-3-clause)に基づいているため、開発中のプロジェクト内に色々なライセンスのファイルが存在してくると、そのライセンス同士の衝突する・しないなどアプリ開発とは関係の薄いところに気を配っていかなくてはなりません。
せめて画像置き場は自分専用のストレージにおけると、ライセンスの無用な衝突の問題を分けて考えることができるので、少し気が楽になりそうです。
そんなニーズに応えるためなのか分かりません。
scratch-guiには救済措置としてデフォルトのアセット置き場のURLを変更はできるようになっています。
今回はプライベートのAWS S3のバケット内にプロジェクトのアセットを置いて、そこからScratch3アプリが正常に起動することを検証します。


合同会社タコスキングダム|蛸壺の技術ブログ【Pschool厳選】Scratchをしっかり学ぶためのオススメ書籍まとめ

AWS S3でアセット用のバケットを作成



※この記事ではAWSでのクラウドストレージを利用した方法を紹介します。
他のクラウドストレージやCDNからでも
https://... からアクセスできるエンドポイントがあれば同じように設定できると思います。
AWSを利用するのでなければこの節はスキップして、次に節からお読みください。
まずはAWS S3のコンソールから空のバケットを作成します。
このバケットにとりあえず
project という空のフォルダを追加しておきます。
プロジェクトのファイル(
.sb3 )を解凍して、中身のアセット(png/svg/wavなど)をこの project フォルダにアップロードしておきます。

合同会社タコスキングダム|蛸壺の技術ブログ


外部からアクセスできるようにするためバケットポリシーの追加とCORS設定を行います。

合同会社タコスキングダム|蛸壺の技術ブログ


バケットから
[アクセス許可] タブの [バケットポリシー] および [Cross-Origin Resource Sharing(CORS)] を設定します。
今回は特定のサイトからのみアクセスはせずに、どこのオリジンからでもGETのみ許可するようにしております。
GETのみを許可する時点でこのプロジェクトは
読み込み専用 になります。
アプリの開発も自分専用のクラウドストレージ無いで行いたいときにはここから更に
POST などのメソッドを許可する必要があります。
細かくアクセスコントロールしたい場合には各自の用途に応じた設定に修正してください。
バケットポリシー:

            {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Accsess Policy 1",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<バケット名>/*"
        }
    ]
}

        

CROS設定:

            [
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]

        

特にここでは設定していませんが、
AllowedOrigins に特定のサイトを指定することで、他からのダウンロードは制限することも可能です。
さて、この時点でこのバケットからアクセスが可能かcurlで適当なファイルを取得して試してみます。

            $ curl https://s3-ap-northeast-1.amazonaws.com/バケット名/project/8c84d0a54dc6d808c08b06f4f3880e62.svg
<svg version="1.1" width="7.579999923706055" height="11.640000343322754" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="3.4549999237060547 1.0399999618530273 7.579999923706055 11.640000343322754">
#...中略
  </g>
</svg>

        

レスポンスが返ってきているようなので、AWS S3からファイルが供給できている状態になりました。


scratch-guiの修正



デフォルトではプロジェクトのプロジェクトファイル・アセットファイルが以下のように配置されている仕様です。

            project.json:
    https://projects.scratch.mit.edu/[project_id値]
assets:
    https://assets.scratch.mit.edu/internalapi/asset/[resource_id.(png|svg|wav)]/get/

        

これを先程の設定したような任意のクラウドストレージを参照するようにしていきます。

project-fetcher-hoc.jsx



まずはリソースファイルのホスト先の情報が格納されている
project-fetcher-hoc.jsx を覗いてみます。 このファイルは scratch-gui/src/lib/project-fetcher-hoc.jsx にあります。
このコードの中身に以下の部分を探します。

            //...中略
ProjectFetcherComponent.defaultProps = {
    assetHost: 'https://assets.scratch.mit.edu',
    projectHost: 'https://projects.scratch.mit.edu'
};
//...以下略

        

この設定がデフォルトのアセット置き場のURLの設定になります。
先程のAWS S3バケットに仕込みなおすと、

            //...中略
ProjectFetcherComponent.defaultProps = {
    // assetHost: 'https://assets.scratch.mit.edu',
    // projectHost: 'https://projects.scratch.mit.edu'
    assetHost: 'https://s3-ap-northeast-1.amazonaws.com/<バケットの名前>/project',
    projectHost: 'https://s3-ap-northeast-1.amazonaws.com/<バケットの名前>/project'
};
//...以下略

        

でデフォルトのリソースファイル置き場が変更できました。


storage.js



もう一つ修正すべきなのが、
storage.js という保存先のアクセス方法を実装しているファイルです。 場所は scratch-gui/src/lib/storage.js にあります。
デフォルトでは、

            //...中略
setProjectHost (projectHost) {
    this.projectHost = projectHost;
}
getProjectGetConfig (projectAsset) {
    return `${this.projectHost}/${projectAsset.assetId}`;
}
getProjectCreateConfig () {
    return {
        url: `${this.projectHost}/`,
        withCredentials: true
    };
}
getProjectUpdateConfig (projectAsset) {
    return {
        url: `${this.projectHost}/${projectAsset.assetId}`,
        withCredentials: true
    };
}
setAssetHost (assetHost) {
    this.assetHost = assetHost;
}
getAssetGetConfig (asset) {
    return `${this.assetHost}/internalapi/asset/${asset.assetId}.${asset.dataFormat}/get/`;
}
getAssetCreateConfig (asset) {
    return {
        // There is no such thing as updating assets, but storage assumes it
        // should update if there is an assetId, and the asset store uses the
        // assetId as part of the create URI. So, force the method to POST.
        // Then when storage finds this config to use for the "update", still POSTs
        method: 'post',
        url: `${this.assetHost}/${asset.assetId}.${asset.dataFormat}`,
        withCredentials: true
    };
}
//...以下略

        

という部分が、そのままでは
getAssetGetConfig メソッド返すURLが専用のWeb Api形式になっています。
そこで
AWS S3 に合わせるように書き換えます。

            //...中略
getAssetGetConfig (asset) {
    // return `${this.assetHost}/internalapi/asset/${asset.assetId}.${asset.dataFormat}/get/`;
    return `${this.assetHost}/${asset.assetId}.${asset.dataFormat}`;
}
//...以下略

        

ここらへんはアセット置き場として利用したいクラウドストレージのアクセス方法によって異なるエンドポイントになるかも知れません。
その際は
storage.js を多少変更することになると思います。
これでScratch-guiをビルドして、デフォルトのプロジェクトを読み込んだ際に、指定したクラウドストレージからリソースが読み込まれていたら設定完了です。

合同会社タコスキングダム|蛸壺の技術ブログ

合同会社タコスキングダム|蛸壺の技術ブログ【Pschool厳選】Scratchをしっかり学ぶためのオススメ書籍まとめ

まとめ



今回はスクラッチプロジェクトのアセットファイルの置き場所をカスタマイズする方法を解説しました。
特に今回のテクニックでは、スクラッチアプリは公開したいけれど、そこで利用している一部のライセンス付きの画像のアクセスは制限したい場合に役立つと思います。