- 投稿日:2020-02-07T21:44:05+09:00
ローカルホストにスマホからアクセスできたのでメモ
localhost:8080へスマホでアクセスしたかった
正確に言うと
現在のpcのipアドレス:8080にスマホでアクセスしたかった。
自分の場合失敗はnpm run devのタイミング、
jsonの書き換え+Ctrl+Sタイミングが間違っていたこと。
最大の原因は無線ルーターがアクセスポイントとなっているため
「スマホ」と「pc」で別のssidに入っていたこと。
これらを手順通り行っていけばきちんと通信してスマホで見れたのだ。この手順は
・ファイアウォール・セキュリティ無効
・同じアクセスポイントに入る
・jsonの書き換え
・npm run dev
・ブラウザ表示失敗
・ターミナルでCtrl+Cして一旦カレントディレクトリへ戻る
・ipconfig でipv4アドレス確認
・npm run dev
・先ほどのブラウザ画面のアドレスバーにipv4アドレス:8080を入力しリロード
・パソコンでipv4の自作app.vue画面が表示成功
・スマホのブラウザのアドレスバーに先ほどのipv4アドレス:8080を入力しリロード
・スマホでipv4の自作app.vue画面の表示成功なぜ手順飛ばしたら表示されない部分があるのかはわかりません!
間違っていたらすいません!
- 投稿日:2020-02-07T19:26:22+09:00
Vue CLIでFirebase SDKとFirebaseUIを外部から読み込みたい!
Firebase SDKはデカい!
Web用のFirebase SDKは、Node.jsモジュール、CDN、Hosting URLからの3つの方法で導入できます。
https://firebase.google.com/docs/web/setup#add-sdks-initializeしかし、Node.jsモジュールをwebpackでバンドルすると、ビルドされたファイルの大半をFirebase SDKが占める、なんてこともあります。
加えて、FirebaseUIの日本語版のNode.jsモジュールは1.0.0で止まっちゃってるので最新版を使いたいときはCDNを使うしかなさそうです。
そこでCDNから読み込みたいのですが、Vue CLIを使ってビルドする際、CDNとwebpackを共存させる方法で詰まったので記録しておきます。
webpackに外部ファイルの存在を告げる
webpackに「外部ファイルを使うからビルドファイルにはこのモジュールはいらないよ」と教える必要があります。
そのためには
webpack.config.js
にexternals
というプロパティを追加します。
https://webpack.js.org/configuration/externals/Vue CLIの場合、
vue.config.js
に追加できます。
https://cli.vuejs.org/guide/webpack.html#simple-configurationvue.config.jsmodule.exports = { configureWebpack: { externals: { firebase: 'firebase', firebaseui: 'firebaseui' } } }index.htmlにリンクを追加する
Node.jsモジュールの場合、
main.jsimport firebase from 'firebase/app' import 'firebase/firestore' import 'firebase/auth'このように必要な機能を部分的にimportしますが、CDNの場合、
public/index.html<head> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title>タイトル</title> <script src="https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/7.8.0/firebase-auth.js"></script> <script src="https://www.gstatic.com/firebasejs/7.8.0/firebase-firestore.js"></script> <script src="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth__ja.js"></script> <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth.css" /> </head>
index.html
に必要なSDKのCDNリンクを追加して、main.jsimport firebase from 'firebase'このようにimportすれば、必要な機能だけ導入できます。
Hosting URLを使いたい!
これでCDNからの読み込みは出来るはずですが、Firebase Hostingを使っている場合、予約済みURLから読み込んだ方がパフォーマンスが向上するようです。
https://firebase.google.com/docs/hosting/reserved-urlsこれもCDNと同様に
index.html
に追加すれば使えます。public/index.html<head> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title>タイトル</title> <script src="/__/firebase/7.8.0/firebase-app.js"></script> <script src="/__/firebase/7.8.0/firebase-auth.js"></script> <script src="/__/firebase/7.8.0/firebase-firestore.js"></script> <script src="/__/firebase/init.js"></script> <script src="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth__ja.js"></script> <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth.css" /> </head>
/__/firebase/init.js
を追加すれば、初期化処理をコピペする必要はありません。ローカルサーバーでも使いたい!
npm run serve
で立ち上げたローカルサーバーでは/__/firebase/
にアクセスしても「そんなもん無いよ?」と言われてしまいます。
npm run build
+firebase serve
ではfirebase-toolsが/__/firebase/
にアクセスできるようにしてくれるのですが、ファイルを変更するたびにビルドしていたら開発効率が落ちてしまうでしょう。解決するのは簡単で、
/__/firebase/
の頭にFirebase HositingのURLを付けるだけです。public/index.html<head> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title>タイトル</title> <script src="https://~.firebaseapp.com/__/firebase/7.8.0/firebase-app.js"></script> <script src="https://~.firebaseapp.com/__/firebase/7.8.0/firebase-auth.js"></script> <script src="https://~.firebaseapp.com/__/firebase/7.8.0/firebase-firestore.js"></script> <script src="https://~.firebaseapp.com/__/firebase/init.js"></script> <script src="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth__ja.js"></script> <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth.css" /> </head>絶対パスでは速度が落ちるらしいので環境変数を使って開発環境だけで使うといいと思います。
.envVUE_APP_FIREBASE_URL=.env.developmentVUE_APP_FIREBASE_URL=https://~.firebaseapp.compublic/index.html<head> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title>タイトル</title> <script src="<%= VUE_APP_FIREBASE_URL %>/__/firebase/7.8.0/firebase-app.js"></script> <script src="<%= VUE_APP_FIREBASE_URL %>/__/firebase/7.8.0/firebase-auth.js"></script> <script src="<%= VUE_APP_FIREBASE_URL %>/__/firebase/7.8.0/firebase-firestore.js"></script> <script src="<%= VUE_APP_FIREBASE_URL %>/__/firebase/init.js"></script> <script src="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth__ja.js"></script> <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth.css" /> </head>環境変数については以下を参照
https://cli.vuejs.org/guide/mode-and-env.html
- 投稿日:2020-02-07T19:01:41+09:00
FirebaseでSMS認証(Nuxt, Vue.js)
ドキュメント見るの辛い人向けに置いておきます。
1.Firebaseのコンソールで電話番号認証を許可
AuthenticationタブからONにするだけです
これでアプリケーションで使えるようになります
料金体系
Sparkプランは1万/月でいけるので、試しにテストしてみたかったり小規模なサービスではこれで十分かと思います
1万を超過するようなログイン、登録が発生する場合はBlazeプランにあげたほうが確実です。
Blazeプランの場合は従量課金制度で1万を超過した分に対して1件あたりの金額がかかってきます。
2.reCAPTCHAで認証を設定
主に不正行為を防止する目的でこれ設定する必要があります。
例えばよくある画像を選んでロボットではないことを確認するアレです。
//任意の言語を渡すとreCAPTCHAの言語が自動的に変わります firecase.auth().languageCode = 'jp'最近ではユーザーの操作を必要としないreCAPTCHAもあるのですが、firebaseはそれもサポートしています
今回はチェックボックスにチェックするいつものreCAPTCHAを使います
<template> <div> <a id="sign-in-button" @click="sendMessage()"> <span>ログイン</span> </a> <div id="recaptcha-container"/> </div> </template> <script> import firebase, { auth } from 'firebase' export default { data () { return { recaptchaVerifier: null, recaptchaWidgetId: null, confirmationResult: null, verificationCode: null } }, mounted () { this.recaptchaVerifier = window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', { 'size': 'normal', 'callback': responseToken => { // reCAPTCHA solved } }) this.recaptchaWidgetId = await this.recaptchaVerifier.render() } }これでreCAPTCHAのdivがrenderingされます
この
recaptchaVerifier
は signIn時の引数で利用するので保持しておきます3.SMSへのコード送信処理
電話番号は国際番号(+81) + 電話番号で入力されたものを利用します
ここでは決め打ちしていますが、本来はinputタグを用意してそこに入力したものをv-modelなどを利用して取得してきます
async sendMessage() { // ダッシュボードからホワイトリストにいれてテストすることが可能です const phoneNumber = "+818099999999" try { this.confirmationResult = await firebase.auth().signInWithPhoneNumber( phoneNumber, this.recaptchaVerifier) // ここで先ほどのreCAPTCHA認証を利用します } }問題なく送信された場合はconfirmationResultにverificationIdが返ってくるのでそれをユーザー認証に使います
4.SMSで届いたコードを入力させてログイン
3で実施したcofirmationResultとSMSに送信されたコードを利用して実際にユーザーを認証させます
※htmlにはないですが、認証コード入力欄と確認ボタンみたいなものがある前提です
// verificationCodeはv-modelなどで指定しているユーザーが入力した認証コード if (this.confirmationResult && this.verificationCode) { try { const result = await this.confirmationResult.confirm(this.verificationCode) const user = result.user // これでユーザーを取得できる } catch (e) { // 認証コードが間違っている } }以上で電話番号で認証をとることが可能です
- 投稿日:2020-02-07T14:46:49+09:00
nuxt.js(v2) meta情報を1つのjsonに集約、各ページに反映されるようにする
こちらの記事、nuxt.js(v2)でSEOに必要なmeta(OGP)で入力漏れの事故をなくす で紹介されていた、metaまわりの実装をスッキリさせる方法を元に
meta情報を一箇所で管理する方法をまとめます。予め、この記事のもと設定が終わっている条件とします。
実現したいこと
- meta情報の一覧性を高めるため、メタ情報を一箇所で管理できるようにしたい。
- 各ページでmeta情報を定義するのをやめて、すべてのページのメタ情報が含まれるjson形式の定義ファイルを1つ作成しそこにまとめて書いたものが反映されるようにしたい
手順
- メタ情報をまとめた定義ファイルをjsonで作成
- nuxt.config でそれを読み込みを定義し、どこからでも参照できるように
- jsonで定義されたmeta情報は、ファイルパスに基づいて各ページに反映されるように
準備
1. meta情報定義ファイル metadata.jsonを作成
ファイルパスに基づいてmetaデータを切り分けられるような構造にした。
独自のフォーマット。
例は、about、activity、works、projectsページがある場合の定義例。metadata.json{ "/about": { "title": "about title", "description": "about no description" }, "/activity": { "title": "activity title", "description": "activity no description" }, "/works": { "title": "works title", "description": "works no description" }, "/projects": { "title": "projects title", "description": "projects no description" }, }ファイルはasset内に配置した。
@/assets/data/metadata.json2. プロジェクト内で使用できるように、nuxt.config.js に読み込み設定
nuxt.config.jsimport metaData from './assets/data/metadata.json' export default { env: { metaData: metaData },これで、
context.env.metaDataでアクセスできるようになった。
metaに反映
記事 の本題と紹介されている部分 assets/mixins/meta.js の箇所に手を加えていきます。
mixin内で、metaData 値でアクセスできるようにする
metaData 値でアクセスできるように、asyncDataの箇所を追加します。
assets/mixins/meta.jsexport default { asyncData (context) { return { baseName: context.env.baseName, baseDesc: context.env.baseDesc, baseUrl: context.env.baseUrl, baseOgp: context.env.baseOgp, metaData: context.env.metaData, //←追加 } }, . . .head 関数内の調整
次に、head 関数内を調整していきます。
書くページのファイルのパスは、const path = `${this.$router.history.base}${this.$route.path}`;で取れるようなので
やや雑な感じですがこのような感じにします。assets/mixins/meta.jshead() { const head = { meta: [] } if (this.$route.path === '/') { head.meta.push({ hid: 'og:type', property: 'og:type', content: 'website' }) } // ページPath const path = `${this.$router.history.base}${this.$route.path}` if (this.metaData[path]) { // タイトル if (this.metaData[path].title) { const title = `${this.metaData[path].title} - ${this.baseName}` head.title = title head.meta.push({ hid: 'og:title', property: 'og:title', content: title }) } // ディスクリプション if (this.metaData[path].description) { const description = `${this.metaData[path].description}` head.meta.push({ hid: 'description', name: 'description', content: description }) head.meta.push({ hid: 'og:description', property: 'og:description', content: description }) } else if (!this.metaData[path].description && this.metaData[path].title) { const description = `${this.baseName}サイトの${this.metaData[path].title}ページです。${this.baseDesc}` head.meta.push({ hid: 'description', name: 'description', content: description }) head.meta.push({ hid: 'og:description', property: 'og:description', content: description }) } // ページタイプ if (this.metaData[path].type) { head.meta.push({ hid: 'og:type', property: 'og:type', content: this.metaData[path].type }) } // OGP画像URL if (this.metaData[path].image) { const imageUrl = `${this.baseUrl}${this.$router.history.base}${this.baseOgp}${this.metaData[path].image}` head.meta.push({ hid: 'og:image', property: 'og:image', content: imageUrl }) } } // ページURL const url = `${this.baseUrl}${this.$router.history.base}${this.$route.path}` head.meta.push({ hid: 'og:url', property: 'og:url', content: url }) return head }
- 投稿日:2020-02-07T10:29:55+09:00
[Vue.js] どうしてVue.set()で配列の更新が検知できるの?
[Vue.js]配列の変更が検知できない理由の「JavaScriptの制限」って何よ! - Qiita
こちらの記事で配列の更新検知には
Vue.set
を使うと記載したのですが、
どうして検知できるのかな?って思って調べました。結論
内部では
splice()
をしているだけだった。実装を見てみる
公式GitHubを見てみましょう!
export function set (target: Array<any> | Object, key: any, val: any): any { // 中略 if (Array.isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key) target.splice(key, 1, val) //ここだ! return val } ...ありました!
内部でtarget.splice(key, 1, val)
をしていることが確認できました!
だから検知できるんですね!