GoogleSearchConsoleでモバイルフレンドリーでないと判定されてしまう

モバイルユーザビリティでエラーがでている

  • テキストがちいさすぎて読めません
  • クリック可能な要素が小さすぎます
  • コンテンツの幅が画面の幅を超えています

SearchConsole width=640

エラー内容のページで再検査を試みるが……

SearchConsole width=640

検証プロセスを終了できませんで検査できない。

SearchConsole width=640

モバイルフレンドリーテストツールで原因を探る

モバイルフレンドリーのエラーはSearch Consoleにあるモバイルフレンドリーテストツールで検証できる。

SearchConsole width=640

SearchConsole width=640

SearchConsole width=640

検査の結果からエラー原因を突き止める

このページはモバイルフレンドリーではありませんと結果が表示されている。スクリーンショットをみると画面が崩れている。

SearchConsole width=640

エラーの詳細をみるとページが部分的に読み込まれましたとなっており、具体的に読み込めなかったファイルを確認していくと・・・CSSが読み込めていない。

SearchConsole width=640

エラーの原因を改善する

robots.txtテストツールで確認すると、robtos.txtでCSSが読み込めない設定になっている。
このサイトで使用しているHexoではassetsディレクトリーにCSSを含んでいるため、GoogleクローラーがCSSを読めない状態になっている。

1
2
3
4
5
6
7
8
9
User-agent: *
Disallow: /all-categories/
Disallow: /categories/
Disallow: /all-tags/
Disallow: /tags/
Disallow: /all-archives/
Disallow: /assets/images/
Disallow: /assets/
Sitemap: https://www.nullpo.io/sitemap.xml

該当の2行を削除。

1
2
3
4
5
6
7
User-agent: *
Disallow: /all-categories/
Disallow: /categories/
Disallow: /all-tags/
Disallow: /tags/
Disallow: /all-archives/
Sitemap: https://www.nullpo.io/sitemap.xml

修正したページで再検査する

再度検査を実行すると、このページはモバイルフレンドリーですとなり、スクリーンショットも正常。

SearchConsole width=640

SearchConsole width=640

1週間程度経過しても、GoogleSearchConsoleの状態が変わらない・・・

仮説① google側がrobots.txtのキャッシュをもっているのではないか?

robots.txtテストツール送信からGoogleに通知できるようなのでトライする。

SearchConsole width=640

しかし、送信しました。すぐにテスターページを再読み込みしてタイムスタンプを確認してください。という表示がされた。つまり、テスターで読み込めていればGoogle側は更新したrobots.txtを読み込み済ということだ。

SearchConsole width=640

仮説② Googleのロボットが古いコンテンツキャッシュを持っているのではないか?

GoogleSearchConsoleのURL検査から検索ウインドにURLを入力して実行すると、検査ページが現れる。
検査ページではモバイルユーザビリティに問題があると報告されている。

SearchConsole width=640

検査ページで公開URLのテストを実行。

SearchConsole width=640

テストが終わるとライブテストというタブで結果が表示されている。エラーもない。

SearchConsole width=640

もうひとつのGOOGLEインデックスというタブを開くと……エラーのある状態だ。

SearchConsole width=640

表示されているインデックス登録をリクエストをクリック。

SearchConsole width=640

数日後、全ページのエラーが解消

モバイルユーザビリティで発生していたエラーはすべてて解消!

SearchConsole width=640

SearchConsole width=640

コメント・シェア

HexoのGoogleChartプラグイン

hexo-tag-googlechartsのインストール

1
npm install hexo-tag-googlecharts -- save

GoogleChartを読み込む

themes/tranquilpeak/layout/_partial/head.ejs<script type="text/javascript" src="//www.google.com/jsapi"></script>を読み込むように追記する。

1
2
3
    <!-- Google Chart -->
<script type="text/javascript" src="//www.google.com/jsapi"></script>
</head>

チャートを描く

書き方

1
2
3
4
5
6
7
8
9
{% googlecharts ChartType [width [height]] %}
Title for the Graph
{ "customOptions": true }
'Column1', 'Column2', 'Column3'
1000, 28, 5
5000, 71, 19
10000, 143, 37
20000, 282, 68
{% endgooglecharts %}
  • ChartTypeにはチャート名を記載
  • オプションはJSON形式で渡す
  • データはCSV形式で記述

Pie Chart

1
2
3
4
5
6
7
8
9
10
11
{% googlecharts PieChart 100% %}
Pie Chart
{}
'Task', 'Hours per Day'
'Work', 11
'Eat', 2
'Commute', 2
'Watch TV', 2
'Sleep', 7
{% endgooglecharts %}

Donut Charts

1
2
3
4
5
6
7
8
9
10
{% googlecharts PieChart 100% %}
Donut Charts
{"pieHole": 0.4}
'タスク', '時間'
'仕事', 11
'食事', 2
'通勤', 2
'テレビ', 2
'睡眠', 7
{% endgooglecharts %}

Table Charts

1
2
3
4
5
6
7
8
9
{% googlecharts Table 100% 100% %}
Table Charts
{"showRowNumber": true}
'Name', 'Salary', 'Full Time Employee'
'Mike', {v: 10000, f: '$10,000'}, true
'Jim', {v:8000, f: '$8,000'}, false
'Alice', {v: 12500, f: '$12,500'}, true
'Bob', {v: 7000, f: '$7,000'}, true
{% endgooglecharts %}

Bar Charts

1
2
3
4
5
6
7
8
9
{% googlecharts BarChart 100% %}
Bar Charts
{}
'Element', 'Density', { role: 'style' }
'Copper', 8.94, '#b87333'
'Silver', 10.49, 'silver'
'Gold', 19.30, 'gold'
'Platinum', 21.45, 'color: #e5e4e2'
{% endgooglecharts %}

Goe Charts

1
2
3
4
5
6
7
8
9
10
11
{% googlecharts GeoChart 640 480 %}
GeoCharts
{}
'Country', 'Popularity'
'Germany', 200
'United States', 300
'Brazil', 400
'Canada', 500
'France', 600
'RU', 700
{% endgooglecharts %}

Bubble Charts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% googlecharts BubbleChart 640 480 %}
Bubble Charts
{"hAxis": {"title": "Life Expectancy"}, "vAxis": {"title": "Fertility Rate"}, "bubble": {"textStyle": {"fontSize": 11}}}
'ID', 'Life Expectancy', 'Fertility Rate', 'Region', 'Population'
'CAN', 80.66, 1.67, 'North America', 33739900
'DEU', 79.84, 1.36, 'Europe', 81902307
'DNK', 78.6, 1.84, 'Europe', 5523095
'EGY', 72.73, 2.78, 'Middle East', 79716203
'GBR', 80.05, 2, 'Europe', 61801570
'IRN', 72.49, 1.7, 'Middle East', 73137148
'IRQ', 68.09, 4.77, 'Middle East', 31090763
'ISR', 81.55, 2.96, 'Middle East', 7485600
'RUS', 68.6, 1.54, 'Europe', 141850000
'USA', 78.09, 2.05, 'North America', 307007000
{% endgooglecharts %}

コメント・シェア

HexoのTranquilpeakをみやすくカスタマイズ

 
カテゴリー SSG   タグ

フォントを変更する

Webフォントを読み込む

themes/tranquilpeak/layout/_partial/head.ejs<link href="https://fonts.googleapis.com/earlyaccess/notosansjapanese.css" rel="stylesheet">を読み込むように追記する。

1
2
3
    <!-- Web Fonts -->
<link href="https://fonts.googleapis.com/earlyaccess/notosansjapanese.css" rel="stylesheet">
</head>

フォントを使用する

themes/tranquilpeak/source/_css/utils/_variables.scssをカスタマイズする。
Noto Sans Japaneseフォントを読み込み、codeとhighlight以外を置き換える。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Font families
$open-sans: 'Open Sans';
$open-sans-sans-serif: 'Open Sans', sans-serif;
$merriweather-serif: 'Merriweather', serif;
$monospace: Menlo, Consolas, monospace;
$noto-sans-japanese: 'Noto Sans Japanese';

//$font-family-base: $open-sans-sans-serif;
$font-family-base: $noto-sans-japanese;

$font-families: (
//// base
//'headings': $open-sans-sans-serif,
//// components
//'code': $monospace,
//'caption': $merriweather-serif,
//'image-gallery': $open-sans,
//'post-header-cover': $merriweather-serif,
//'post-meta': $open-sans-sans-serif,
//'post-content': $merriweather-serif,
//'post-excerpt-link': $open-sans-sans-serif,
//'highlight': $monospace,
//// layout
//'sidebar': $open-sans-sans-serif
// base
'headings': $noto-sans-japanese,
// components
'code': $monospace,
'caption': $noto-sans-japanese,
'image-gallery': $noto-sans-japanese,
'post-header-cover': $noto-sans-japanese,
'post-meta': $noto-sans-japanese,
'post-content': $noto-sans-japanese,
'post-excerpt-link': $noto-sans-japanese,
'highlight': $monospace,
// layout
'sidebar': $noto-sans-japanese
);

ヘッダーのカスタマイズ

themes/tranquilpeak/layout/_partial/post/meta.ejsをカスタマイズして、見やすくする。

  • 記事投稿日だけでなく記事の更新日も表示する
  • 各メタ情報のアイコンを表示する
  • カテゴリーだけでなくタグもヘッダーに表示する
  • カテゴリーもタグと同じ表示形式にする
  • フォントをtext-smallからtext-mediumにして
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<div class="<%= (classes ? classes.join(' ') : '') %>">
<!-- 記事投稿日 -->
<i class="fas fa-file-alt"></i>
<time datetime="<%= post.date.format() %>">
<span class="text-color-light text-medium">
<% if (post.lang) { %>
<%= post.date.locale(post.lang).format(__('date_format')) %>
<% } else { %>
<%= post.date.locale(page.lang).format(__('date_format')) %>
<% } %>
</span>
</time>
&nbsp;
<!-- 記事更新日 -->
<% if (post.updated) { %>
<i class="fas fa-redo-alt"></i>
<time datetime="<%= post.updated.format() %>">
<span class="text-color-light text-medium">
<% if (post.lang) { %>
<%= post.updated.locale(post.lang).format(__('date_format')) %>
<% } else { %>
<%= post.updated.locale(page.lang).format(__('date_format')) %>
<% } %>
</span>
</time>
<% } %>
<br>
<!-- カテゴリー -->
<% if ((post.categories) && (post.categories.length > 0)) { %>
<i class="far fa-folder-open"></i>
<span class="text-color-light text-medium"><%= __('post.categorized_in') %> </span>
<%- partial('category', {categories: post.categories})%>
<% } %>
&nbsp;
<!-- タグ -->
<% if ((post.tags) && (post.tags.length > 0)) { %>
<i class="far fa-folder-open"></i>
<span class="text-color-light text-medium"><%= __('post.tagged_in') %> </span>
<%- partial('tag', {tags: post.tags})%>
<% } %>
</div>

フッターのカスタマイズ

themes/tranquilpeak/layout/_partial/post.ejsをカスタマイズして、フッターからタグを削除。

  • タグをフッターに表示しない
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    <div id="post-footer" class="post-footer main-content-wrap">
<!--
<% if ((post.tags) && (post.tags.length > 0)) { %>
<div class="post-footer-tags">
<span class="text-color-light text-small"><%= __('post.tagged_in') %></span><br/>
<%- partial('post/tag', {tags: post.tags})%>
</div>
<% } %>
-->
<% if (post.actions === undefined || post.actions) { %>
<%- partial('post/actions', {postContent: postContent}) %>
<% } %>
<% if (post.comments) { %>
<% if (theme.disqus_shortname) { %>
<%- partial('post/disqus') %>
<% } else if (theme.gitment.enable) { %>
<%- partial('post/gitment') %>
<% } else if (theme.gitalk.enable) { %>
<%- partial('post/gitalk') %>
<% } %>
<% } %>
</div>
</article>

ベフォーアフター

元々発生していたGoogleAnalyticsでのエラー

GoogleAnalytics Error width=640

ヘッダーおよびフォントの変化

ビフォー。アルファベットと日本語のバランスが良くない。

Hexo Tranquilpeak width=640

アフター。統一感があって読みやすい。カテゴリーとタグも視認しやすくなったが、ゴチャついてる感じも。

Hexo Tranquilpeak width=640

フッターの変化

ビフォー。記事が長いとアクセスしにくいタグ。

Hexo Tranquilpeak width=640

アフター。すっきり。

Hexo Tranquilpeak width=640

コメント・シェア

仮想通貨マイニングプラットフォームNiceHash

仮想通貨マイニングとは?

送金者は、金額や受取人などの取引情報(トランザクション)を、ネットワークを構成するマイナー(miner, 採掘者)と呼ばれるノードにブロードキャストする。マイナーは、受け取った取引情報をブロックという形でまとめ、ブロックチェーンの末尾に追加する。ただし、新しいブロックを記録するためには計算量の大きな問題を解く必要がある。マイナーたちは競ってその問題を解き、最初にブロックを追加することに成功したマイナーだけが一定額の報酬を得ることができる。二重支払いなどの不整合性は、ブロックをブロックチェーンに記録する際に他のノードによってチェックされる。

問題は10分ほどで解けるように難易度が調整されており、送金者は、取引の整合性がマイナーたちによって確認され、ブロックチェーンに記録されるまで同程度の時間を待たねばならない。流通するすべての ビットコイン通貨は、このようにマイナーへの報酬という形で市場に供給される。

仮想通貨(CryptCurrency)のマイニングは、ハッシュ計算(ハッシュパワー)の対価に報酬を得る仕組み。

nicehash?

nicehashはスロベキアに本拠地を置くハッシュパワーを取引するハッシュパワ取引所サービス。仮想通貨(CryptCurrency)のマイニングプラットフォーム。
2017年12月7日、約4700BTCを奪われる事件が発生。2017年12月22日に営業を再開したがCEOのマルコ・コバル氏は辞任。その後サービスは再開されている。

なにをつかってマイニングするか?

GPUを使ってマイニングする。どの程度掘れるかの目安はminerstatで確認できる。
現在使用しているNvidia RTX 2070だと、2021年1月末ごろのレートで1日あたり大体2.5USD~3.5USDぐらい。

nicehashの導入

NiceHashのダッシュボードにアクセスする

a. NiceHashへアクセス

NiceHash width=640

b. NiceHashのアカウントを登録

NiceHash width=640

c. 登録したアカウントでログイン

NiceHash width=640

d. ダッシュボード

NiceHash width=640

NiceHash Minerのインストール

NiceHash Quick Minerというものもあるが、NiceHash Minerをダウンロードする
ダウンロードセンターからもダウンロードできる。

a. RIGの構築をはじめる

NiceHash width=640

b. 指示されている以下の設定を実施する

  • Method 1: Disabling Windows Defender real-time protection and making an exclusion
  • Method 2: Allowing and restoring the false-positive files (recommended)

NiceHash width=640

c. NiceHash Minerをダウンロード

NiceHash width=640

NiceHash width=640

d. ダウンロードしたインストーラーを実行

e. License AgreementにI Agree

NiceHash width=640

f. Finish

NiceHash width=640

g. NiceHash Minerを実行

h. TERMS OF SERVICEにI ACCEPT

NiceHash width=640

i. Disclaimer on usage of 3rd party softwareにI ACCEPT

NiceHash width=640

j. Choose LanguageはEnglishNEXT

NiceHash width=640

k. LOGIN

NiceHash width=640

l. NIceHashのアカウントでログイン

NiceHash width=640

m. マイナーアルゴリズムなどのモジュールがダウンロードされる。

NiceHash width=640

NiceHash width=640

HashMinerの調整

a. インストールしたNiceHash MinerがMyRigsに表示されている

NiceHash width=640

b. BenchmarkタブのSTART BENCHMARKからベンチマークを行う

ベンチマークは時間がかかるのでしばらく時間を置く必要がある。

NiceHash width=640

NiceHash width=640

c. Pluginsタブで利用可能なマイナーモジュールを確認できる

マイニングに使用するアルゴリズムは自動選択されるが、特定のアルゴリズムで不具合が生じた場合はここで無効化できる

NiceHash width=640

d. MyRigsに設定したRigが表示される

NiceHash width=640

e. CPUでのマイニングを無効化

NiceHash width=640

マイニング状況

インストール後から1週間後のマイニング状況

NiceHash width=640

この1日後(おおむね $3/DAY)

NiceHash width=640

コメント・シェア

パスワードマネージャー

主要なパスワードマネージャー

比較

項目 1Password LastPass Dashlane Bitwarden
ブラウザ拡張
モバイルアプリ
多要素認証
オープンソース × × ×
無料プラン × ×
有料プラン(年間) 36USD 36USD 40USD 10USD

Bitwardenのコスパがすごくいい。

Bitwarden

特徴

  • パスワードマネージャーの機能としては必要十分
  • 無料プランで十分実用的
  • OpenSource(GitHub)
  • Bitwardenクラウドを利用できるが、パスワードマネージャーサーバを構築することも可能

End-to-End Encryption

end-to-end AES-256 bit encryption, salted hashing, and PBKDF2 SHA-256.

個人情報やパスワードはエンドエンド間で暗号化。暗号化アルゴリズムはAES256。ハッシュはPBKDF2。PBKDF2は安全なハッシュ方式でSHA-256をベースにソルトやストレッチ(複数回ハッシュ化を繰り返して解析耐性を上げる)。

Cross-Platform Applications

クロスプラットフォーム対応。主要なものは対応している。

  • Desktop(Windows, macOS, Linux)
  • Web Browser(GoogleChrome, Safari, Mozilla Firefox, Vivaldi, Opera, Brave, Microsoft Edge, Tor Browser)
  • Mobile(Apple, Google)
  • Command Line(Windows, macOS, Linux
  • Web(Access Web Vault)

BitWartdenアカウントの作成

Create Your Free Accountからアカウント作成

Bitwarden width=640

Bitwarden width=640

保管庫にアカウントデータが保存される。

Bitwarden width=640

Bitwarden width=640

パスワード生成ツールによってポリシーに従ったランダムパスワードを付与できる

Bitwarden width=640

2段階認証で多要素認証の設定が可能。

Bitwarden width=640

Chromenに保存したID/パスワードのエクスポート

Chromeに保存されたID/パスワードをエクスポートする。設定->自動入力->パスワードから。

Bitwarden width=640

Bitwarden width=640

エクスポートにはWindowsの認証が必要。

Bitwarden width=320

Chromenに保存したID/パスワードのインポート

データをインポートから、ChromeのCSVを選択して、エクスポートしたデータをインポート。

Bitwarden width=640

Bitwarden width=640

Bitwarden width=640

保管庫にインポートされる。

Bitwarden width=640

BitwardenのChromeアドオン

Bitwarden無料パスワードマネージャーを追加。

Bitwarden Chrome width=640

Bitwarden Chrome width=320

Bitwarden Chrome width=640

アドオンにログインすれば、保管庫のID/パスワードを自動入力できるようになる。

Bitwarden Chrome width=320

Bitwarden Chrome width=320

Bitwarden Chrome width=320

コメント・シェア

動かない

コード0x8004de40
インターネットにはつながっていますか?のようなものを除き主要な対策は3つ。

Onedrive Error width=480

対策1: TLSが有効であることを確認する

  1. inetcpl.cplを実行
  2. 詳細設定でTLS1.0、TLS1.1、TLS1.2にチェックが入っていることを確認

対策2: Windows Socket (Winsock)カタログをリセットする

  1. cmdを管理者で実行
  2. 起動したコマンドプロンプトでnetsh winsock reset catalogを実行

Onedrive Error width=480

対策3: OneDriveをリセットする

大量にファイルがあると、時間がかかるので注意。

  1. %localappdata%\\Microsoft\\OneDrive\\onedrive.exe /resetを実行
  2. %localappdata%\\Microsoft\\OneDrive\\onedrive.exeで再起動

それでも動かない

これら主要なワークアラウンドでこの時は結局解決しなかった。
しかし、溜まっていたWindowsUpdateを適用したらなぜか解消……。なにそれ。

コメント・シェア

OneDriveの個人用Vaultとは

Office365を利用していると1TBのストレージと制限なしの個人用Vaultが使える。

個人用Vault、表記によってはPersonal Vaultになっている。使用しているプランによって使えるファイル数制限がある。
個人用Vaultは普段ロックされ、多要素認証を行うことで保護したフォルダーにアクセスすることができる。利用しない場合は20分(モバイルアプリでは3分)で自動ロックされる。

項目 Microsoft 365 Personal OneDrive Standalone 100GB OneDrive Basic 5 GB
合計ストレージ 1 TB 100 GB 5 GB
個人用Vault 制限なし 3ファイル 3ファイル

個人用Vaultを使う

OneDriveのフォルダー内にある個人用Vaultのアイコンからセットアップ開始

OneDriveVaultwidth=320

OneDriveVaultwidth=320

OneDriveVaultwidth=320

個人用Vaultアイコンから再度実行すると、本人確認を促される。

OneDriveVaultwidth=320

OneDriveVaultwidth=320

OneDriveVaultwidth=320

本人確認後、フォルダーを読み書きできるようになる。

OneDriveVaultwidth=320

個人用Vaultフォルダーのロック

手動でロックすることもできる。

OneDriveVaultwidth=480

ロックするとフォルダーへのアクセスはエラーに。

OneDriveVaultwidth=480

同期もできなくなっている。

OneDriveVaultwidth=320

ロックを解除するとOneDriveの設定画面でも確認できる。ここからロックすることもできる。

OneDriveVaultwidth=320

多要素認証を変更する

メールではなくGoogleAuthenticatorのようなアプリを利用するように変更することができる。

  1. Microsoft アカウントにアクセス

OneDriveのアカウントでサインイン

OneDriveVaultwidth=640

OneDriveVaultwidth=640

OneDriveVaultwidth=640

セキュリティ情報を更新する。

OneDriveVaultwidth=640

OneDriveVaultwidth=640

OneDriveVaultwidth=640

OneDriveVaultwidth=640

OneDriveVaultwidth=640

認証アプリでのコード入力を追加する。身元を証明する方法のサインインまたは確認の新しい方法を追加から追加する。

OneDriveVaultwidth=640

アプリを使う。

OneDriveVaultwidth=640

Microsoft Authenticatorは使わないのでスキップ。

OneDriveVaultwidth=640

自分のAuthenticatorアプリでQRコードを読み込み設定。

OneDriveVaultwidth=640

認証アプリからコードを入力するが追加されている。

OneDriveVaultwidth=640

個人用Vaultにアクセスしようとすると、今度は認証アプリでコード入力が求められる。

OneDriveVaultwidth=320

自動ロックの時間を設定する

OneDriveのアカウント設定で設定できる。標準は20分。

OneDriveVaultwidth=480

コメント・シェア

ExpoのWebIDE環境Snack

 
カテゴリー JavaScript Mobile SaaS   タグ

Expo Snack

Expoに登録するとSnackというWeb IDE環境を利用できる。ローカルにExpoの環境を準備しなくても開発を行うことができる。iOSやAndroidのエミュレーション環境を含めひととおりの環境がある。

Snackをつかう

Snacksから一覧を確認できる。New Snackから新しいSnackを作成。

Expo Snacks width=640

適当に付与されたSnack名(ここではthrilled pizzaになった・・・ワクワクピザ?)でプロジェクトが生成される。

Expo Snacks width=640

右側のMy DeviceiOSAndroidWebから選択して各画面のテストを行うことができる。変更はリアルタイムで反映。

Expo Snacks width=640

iOSTap to playを実行すると、エミュレーターと思われる環境が起動する。

Expo Snacks width=640

コードを変更すると画面も表示が変更される。

Expo Snacks width=640

自分のデバイスで動作させる

Expo Clientアプリをデバイスにインストールする。

カメラでQRコードを撮影すると、Expo Clientアプリから起動を促される。

コメント・シェア

GitHub Actions Result width=640

Expoでできること

The fastest way to build an app

With Expo tools, services, and React, you can build, deploy, and quickly iterate on native Android, iOS, and web apps from the same JavaScript codebase.

Access to device capabilities like camera, location, notifications, sensors, haptics, and much more, all with universal APIs.

Build service gives you app-store ready binaries and handles certificates, no need for you to touch Xcode or Android Studio.

Over-the-air updates let you update your app at any time without the hassle and delays of submitting to the store.

  • Android、iOS、Webアプリの構築からデプロイを迅速に行うことができる
  • カメラ、位置情報、通知、センサー、触覚などにユニバーサルAPIでアクセス
  • ネイティブ開発環境(Xcode、Android Studio)など必要なし
  • Over-the-airアップデートにより、いつでもアプリをアップデートできる

Over-the-airアップデート

ストアでの審査をとおさず、かんたんにアプリを端末配布することができる。
配布はクライアント・サーバ型で行い、端末にはこのためのクライアントアプリをインストールする必要がある。

環境さえととのえてしまえば、これだけでアップデートできる。

1
expo publish

GitHub Actions Result width=640

AppStoreやGooglePlayでの配布

開発したアプリはクライアントアプリなしで、通常のプロセスで配布することができる。
この公開用アプリのビルドは以下を実行するだけである。

1
2
exp build:ios
exp build:android

Expoでできないこと

Expo SDKがReact Native、iOS SDK、Android SDKをラップして抽象化しているため、ネイティブレイヤーには直接アクセスできない。

何が利用できるかはSDKのドキュメントから確認できる。

上の方からいくつか見てみても、

マネタイズのための広告Google Admob

Webビュー経由での認証ならAuthSession

ライトモード・ダークモードのAppearance

など、最新の機能でなければ多くの機能が提供されている。

Expoに登録する

右上のアイコンからサインアップすることができる。

ReactNative Expo width=640

ログイン。シンプルなメニュー構成。

ReactNative Expo width=640

ビルド状況などを確認することができる。

ReactNative Expo width=640

コメント・シェア

Django REST frameworkチュートリアル

公式のQuick Startからチュートリアルへ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
$ mkdir tutorial
$ cd tutorial
$ django-admin startproject tutorial .
$ cd tutorial
$ django-admin startapp quickstart
$ pwd
/work/tutorial/tutorial
$ cd ..
$ find .
.
./manage.py
./tutorial
./tutorial/__init__.py
./tutorial/asgi.py
./tutorial/quickstart
./tutorial/quickstart/__init__.py
./tutorial/quickstart/admin.py
./tutorial/quickstart/apps.py
./tutorial/quickstart/migrations
./tutorial/quickstart/migrations/__init__.py
./tutorial/quickstart/models.py
./tutorial/quickstart/tests.py
./tutorial/quickstart/views.py
./tutorial/settings.py
./tutorial/urls.py
./tutorial/wsgi.py
$ ./manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
$ ./manage.py createsuperuser --email admin@example.com --username admin
Password: ********
Password (again): ********
Superuser created successfully.

Serializers

Serializertutorial/quickstart/serializers.py)を定義。
SerializerはデータをPythonデータ型に変換し、JSONなどのコンテンツタイプにレンダリングする処理を担う。
既定のクラスを継承して実装する。ここでは主キーフィールドの変わりにurlフィールドを使用するHyperlinkedModelSerializerを使用している。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.contrib.auth.models import User, Group
from rest_framework import serializers


class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'groups']


class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ['url', 'name']

Views

Viewtutorial/quickstart/views.py)を定義。
ViewSetsでモデルのCRUD操作を暗黙的に実装している。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer


class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer


class GroupViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Group.objects.all()
serializer_class = GroupSerializer

URLs

urltutorial/urls.py)を定義。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.urls import include, path
from rest_framework import routers
from tutorial.quickstart import views

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

Pagination

settingstutorial/settings.py)をカスタマイズ。

  • SECRET_KEYを環境変数で定義する
  • INSTALL_APPSでrest_frameworkを追加する
  • Pagenation(次のページ)を有効化する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ['SECRET_KEY']

…略…

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
]

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}

アクセス

Viewとしてusersgroupsが定義されている

1
2
3
4
5
$ curl -H 'Accept: application/json; indent=4' -u admin:adminadmin http://127.0.0.1:8000/
{
"users": "http://127.0.0.1:8000/users/",
"groups": "http://127.0.0.1:8000/groups/"
}

Django REST framework quickstart width=640

Paginationを設定したので、応答にnextpreviousが追加されている。アイテム数が少ないので、値はnull。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ curl -H 'Accept: application/json; indent=4' -u admin:adminadmin http://127.0.0.1:8000/users/
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"url": "http://127.0.0.1:8000/users/1/",
"username": "admin",
"email": "admin@example.com",
"groups": []
}
]
}
$ curl -H 'Accept: application/json; indent=4' -u admin:adminadmin http://127.0.0.1:8000/groups/
{
"count": 0,
"next": null,
"previous": null,
"results": []
}

Django REST framework quickstart width=640

Django REST framework quickstart width=640

コメント・シェア



nullpo

めも


募集中


Japan