AWS日記46 (Amazon S3 - WebAssembly)

# はじめに
今回は[Amazon S3](https://aws.amazon.com/jp/s3/)の静的ウェブサイトのホスティングを試します
[ウェブサイトのホスティングの有効化](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/EnableWebsiteHosting.html)の手順を参考にしつつ、WebAssemblyを利用したサイトをホスティングします


# 準備
- wasmファイル作成
  - [WebAssembly | MDN](https://developer.mozilla.org/ja/docs/WebAssembly)を参考に、wasmファイルをビルドします。
```bash
wasm-pack build --target web
```
 
- htmlファイル作成
  - index.htmlを作成し、wasmファイルをロード・実行する処理を書きます
```javascript
let wasm;

let cachedUint8Memory0 = new Uint8Array();

function getUint8Memory0() {
    if (cachedUint8Memory0.byteLength === 0) {
        cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
    }
    return cachedUint8Memory0;
}

const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) { return heap[idx]; }

let cachedInt32Memory0 = new Int32Array();

function getInt32Memory0() {
    if (cachedInt32Memory0.byteLength === 0) {
        cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
    }
    return cachedInt32Memory0;
}

...

const imports = {};
imports.wbg = {};
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
    takeObject(arg0);
};

...

WebAssembly.instantiateStreaming(fetch('sample_wasm'), imports).then(obj => {
    wasm = obj.instance.exports;
    cachedInt32Memory0 = new Int32Array();
    cachedUint8Memory0 = new Uint8Array();
});
```


# Amazon S3 設定
- 今回はAmazon S3 コンソールを使用します

### S3 バケット作成
![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/f44e841e-de4b-d807-695e-6a06a56c39fa.jpeg)


### S3 アクセス許可の設定

![02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/896841c9-93b8-a0a7-805e-7287254f114b.jpeg)

![09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/3fbd2329-216a-7628-9632-ea2dfadcd32c.jpeg)

### 静的ウェブサイトホスティングの有効化
- バケットのプロパティの最下部にスクロールします

![05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/4c8970d0-2839-1393-7c24-e32f0050e6a6.jpeg)

![06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/b21956df-ddbc-a3f0-78dc-7f084dd5348a.jpeg)

![07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/e8b0606b-c710-d79c-681b-6b31f3d793ae.jpeg)

- バケットウェブサイトエンドポイントを書き留めます
- ファイルアップロード後、このURLにアクセスします

### バケットのアクセス許可の確認
![10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/7387ef9f-165d-6b5d-bdb9-6b633781763f.jpeg)

### ファイルアップロード・設定
![11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/26df3670-4f44-d709-b6e6-00be7835a293.jpeg)

- アップロードしたwasmファイルのメタデータを編集します
![12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/f5f82031-2960-857a-a97d-59fa65d00481.jpeg)

![13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/74607bfe-5a1f-7deb-ec74-35fc9f794d9a.jpeg)
- メタデータの値を 「application/wasm」 に変更します

# 別の方法で設定 (CloudFormation & AWS CLI)

### S3バケット作成・設定

```yaml
---
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: S3 Static Website

Parameters:
  ApplicationName:
    Type: String
    Default: 'S3StaticWebsite'

Resources:
  StaticWebsiteBucket:
    Type: "AWS::S3::Bucket"
    Properties:
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html

  StaticWebsiteBucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref StaticWebsiteBucket
      PolicyDocument:
        Statement:
          - Action: "s3:GetObject"
            Effect: Allow
            Resource: !Sub "arn:aws:s3:::${StaticWebsiteBucket}/*"
            Principal: '*'

Outputs:
  APIURI:
    Description: "URI"
    Value: !GetAtt StaticWebsiteBucket.WebsiteURL
```

```bash
sam package --output-template-file packaged.yml --s3-bucket {bucket}
sam deploy --stack-name {stack} --capabilities CAPABILITY_IAM --template-file packaged.yml
```


### ファイルアップロード

```bash
aws s3 cp index.html s3://bucket-name --content-type "text/html"
aws s3 cp sample.wasm s3://bucket-name --content-type "application/wasm"
```


# 終わりに
Amazon S3の静的ウェブサイトのホスティングを試しました。
今回は Fetchを使用してWebAssemblyコードのロードを行いました。
[WebAssemblyコードのロードと実行](https://developer.mozilla.org/ja/docs/WebAssembly/Loading_and_running)にあるような別の方法も、今後試していこうと思います。

追記：[パッケージのウェブでの利用](https://developer.mozilla.org/ja/docs/WebAssembly/Rust_to_wasm#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%A6%E3%82%A7%E3%83%96%E3%81%A7%E3%81%AE%E5%88%A9%E7%94%A8) の方法がシンプルです。
wasmファイルと jsファイルをアップロードし、html内に import 処理を書くことでパッケージを利用できます。
特に、[ロード後に1度だけ実行するWebページ](https://wasm.labo.systems/plotters-3d-plot/)の場合 (対話型の処理が無い場合)は有用です。