mitsuのぶろぐ

基本的にはプログラミングの話のつもり。

Macでテキスト選択するときのキーボードショートカットでいまさら発見したこと

shift + option + 矢印キー なんてやり方があったのか・・・

Mac触ったりWindows触ったりと行ったり来たりしてたらショートカットキーが曖昧になってきます。。。
以下のネタはパソコン触ったばかりの人のような発言ですが、今日地味に感動したので備忘録として残します。 Macで選択するとき、基本的には「Shift + 矢印キー」でテキストを選択していたのですが、何かの拍子に「option + shift + 矢印キー」で押したらいいかんじに選択された!というものです。

TL;DR

Macの普通のテキスト選択において

  • shift + 矢印キー : 左右 -> 一文字ずつ選択されていく。上下 -> カーソル位置から一行分選択される
  • shift + ⌘ or control + 矢印キー : 左右 -> カーソル位置から右端 / 左端まで選択される。上下 -> カーソル位置から最上位 / 最下位まで選択。
  • shift + option + 矢印キー : 左右 -> 単語ごとで選択される。上下 -> カーソル位置から一行分選択される

追記

正直解説もなにもないと思うので、特に言及することはないのですが・・・
Windowsではshift + ctrl + 矢印キーで単語ごとの選択ができていたのに、Macだとできずに(というかshift + ⌘ + 矢印キーでできずに思考停止してた)そんなものかと思っていたのですが、発見することができました。(笑)

最近は会社で使うPCはMac、自宅でやる場合もMacUbuntuとなってある程度環境を統一できるようになってきたので、迷うことは少なくなってきましが、ちょいちょい迷うことはありますね・・・悩ましい。

デザインシステムとコンポーネントライブラリを作っていた経験を振り返って

普遍的なものを作るって難しいよね。という話

先日のInside Frontendでデザインシステムの話をみて、「そういや似たようなことをやってたな」とふと思い出しました。

walk-diagonally.hatenablog.com

せっかくなので前職でデザインシステムや社内向けコンポーネントライブラリを作っていた内容をちょっとまとめて振り返ってみます。
正直具体的な解決策はあまりない気がします。
なんせ難しいもの・・・

*まとめて書こうかと思いましたが一旦難しかったところだけ書きます。時間ができたらupdate
*デザインシステムやコンポーネントライブラリ作成の作業をいいかんじに抽象化して記載ができなかったので、これも時間ができたらupdate

デザインシステム

難しかったこと

イレギュラーケースが出てくる

当たり前以外の何者でもなく恐縮ですが・・・
一回ある程度決まりごとを作っても、サービスで新機能追加や改善をしていくと当初作ったルールと整合性が整わなくなってくる。

対処法
  • 頑張って先を見据えて用意しておく
    なんだか脳筋みたいな書き方ですがこんなかんじかなと・・・
    「Statusカラー」みたいな定義をしたとします。
    初期で想定できるところとして Primary Warning Danger が必要だとなったときに、直近は必要ないとしても Default みたいなものも用意しておく、とかができたらいいのかなと思います。

  • ルール化するところを極力イレギュラーケースが出ないレベル感で設定する
    上のStatusカラーみたいな例でいうと、そもそもStatusカラーなんて定義をもたいないで、「実装で作っていい色一覧」みたいなかんじで使っていいカラーを列挙しておくといったところにとどめておくとイレギュラーケースとかの対応はないのかなと思いました(ex: Default でもないまた別のStatus定義が必要になった、といったときもそのカラー一覧から選んで使うだけで済むといったかんじ)
    *もちろんStatusみたいなところはちゃんと定義はされておくべきだと思います。ドメイン毎でPrimaryの色が違いすぎると迷うと思うので。

いざ実装してみたら実態とあわない

デザインとして完成したものをいざ実装してみたらうまくいかないことって多いですよね

対処法
  • 単なる平面のデザインではなく、モック/プロトタイピングで作る
    理想ですよね。
    正直自分はデザイナーではないので、昨今のツールたちでどこまで簡単にできるのかとかはわかってませんが、ちょっとしたアニメーションとか動きとかつけれるならそっちのほうがいいかなと思います。
  • フロントエンド側もデザインを見たタイミングで動きをイメージする いわゆる歩み寄って気になった点を実装する前になくせるといいですね、というところで。

コンポーネントライブラリ

難しかったこと

良かれと思って修正したら誤爆する

今でこそtypescriptがメジャーな手段になってきたところですが、その前のお話だったので、普通のjsでした。
また、いろいろなサービスで使われてしまっていて、なおかつそのサービス内で魔改造されていたりもしたので、余計な誤爆があったりしました。

対処法
  • typescriptを使う
    言わずもがなです。React使うならpropTypesもちゃんと定義して、固めるところはしっかり固めたほうがいいです。
  • testを書く
    値のやりとりに関してはinputとoutputの担保を一旦しておけば、クリティカルなデグレを引き起こすことはなくなると思います。
    ただし、このあたりはtypescriptで保証されるかもしれないところなので、書き方によってはやらなくてもいいかもしれません。
    でも書いといて損はないと思います。
    見た目に関してもデモサイトを作ってE2Eテストするのいいのかなと思います
  • サポートポリシー的なものを明確化してもよかったかなと
    結局jsなのでなんぼでも魔改造できてしまいます。そこで、こーゆーことするなよ、そんなことをして今後ライブラリをupdateした際に「デグレだ」と言われても対処しません、というような内容を明文化してもいいのかなと思いました。
    ただし、お客様に関係します とか言われたらもうどうしようもないので、やはりこの手の口約束のようなものは難しいです。

汎用性をどこまで / どこに持たせるか

汎用性を高めすぎると上にあるように修正したら誤爆、みたいなことを引き起こす可能性があるかと思います。

対処法
  • できれば汎用性は持たせないようにする
    デザイン側で必要な要素を列挙、ライブラリがそれらを実現できるように充足するようにして実装者がいじれる余地を極力減らしたほうがいいかと思います。

ライブラリする化範囲

Atomic Designでいう Atoms なのか Molecules までやるのか、みたいなところの悩みが多かったです。
あとは良かれと思って「コンポーネントの引数にURL渡して、サーバーサイドをこんなかんじで実装したらいいかんじに実装できるよ!」みたいなコンポーネントもあったのですが、いろいろな社内政治に巻き込まれたりでメンテンナンスがめちゃくちゃ大変になったりしました。

対処法
  • あくまで画面描画のところのみライブラリとしてサポートする
    普通の人からしたら「当たり前では?」みたいなことだと思いますが、その当たり前を普通にやったほうがいいかなと思いました。
    実装する人たちは結局みんなサーバーサイドの連携まで使うし、同様の仕組みで使うからそれならセットで提供したほうがいいとは思いますが、ホントにイレギュラーが少なかったり、そのコンポーネントのアップデートが少ないなら一式で提供してもいいのかなと思います。
    個人的には長期的に考えるとどこかで綻びが出てきてサポートが大変になるように思います
    *現に大変でした。実装側の実装が悪かっただけにも関わらず「コンポーネントの不具合な気がする」みたいなかんじで問い合わせがきたりもしてお互いが不幸だったように思います

  • 組み合わせのコンポーネントに関しても極力一式では提供しない
    上に書いてある内容と似たようなかんじになるのですが、提供するものが増えると結局後々大変になってくる気がするので、組み合わせのコンポーネントあえて用意しない ようにしてもいいのかなと思います。
    ユースケースとしてどう実装したらいいか、みたいなサンプルコードを用意するのはいいかもしれません。

共通

難しかったこと

実際に使う開発者が知らない

せっかく作っても認知されていない

対処法

永遠の課題の一つではないかなと思ってます。
以下がいいところなんじゃないかなと。
- 定期的にMTGなり共有会なりして知らしめる
- コードに埋め込めるものは埋め込んで、各開発者があまり意識する必要がない状態にする

ドキュメント化 / ドキュメント更新のコストをどう下げるか

タイトルの通り。

対処法

極力コード(jsDocとか)から生成できるように寄せる
まあいまならstorybookとかあるんで幾分かマシにはなったと思います

また思い出したタイミングで追記します(多分)

Inside Frontend #3 レポート

Inside Frontendに参加してみました。

Inside Frontend card

inside-frontend.com

ゴリゴリのフロントエンド要素が強い内容にも興味はあったのですが、できれば今の仕事にも活かせるような内容を持って帰れるほうがいいなと思い、デザイン関連のものを見てみました。

基本的にはCの部屋にへばりついてました。

以下、資料がupされてるものに関しては、個人的によかったなと思うところをとかAMAであがってた内容を書いていきます(詳細はスライドを見たほうが絶対いい)
* 極力聞いた言葉をそのまま転用するようにしてますが、間違っていたらすみません。
* 全部はとてもじゃないけど拾えない。そろそろgoogle docsに音声入力か・・・

Seminer A-1 : TypeScript: Why and how we adopted it at Slack

Felix Rieseberg
シニアエンジニア @ slack
もともとは OSSエンジニア from マイクロソフト

発表内容

Slackにtypescriptを導入した話

Introduction

  • Battlefield1 is written by react typescript
  • Electronをベースに作られているslackだが、C++のモジュールで書かれているものもあるとのこと
  • アプリがクラッシュすること、クラッシュしてもログがでない(?)ことに対して危機感

巨大なコードhandlingする必要がある

  • ドキュメントをまとめたり、jsDocを書いたりするがだめだった(信用できない)
  • More js More worries
  • vanillaは勉強必要
typescriptを導入
typescriptのいいところ
  • jsのsupersetだから、変える必要がない(筆者注釈 : jsで書いていたものがそのままtsで使える)
  • editorのサポートがいい
  • npmでのインテグレーションができる
  • 型制御
  • 他のモジュールと共有できる
js -> tsに変換する

hoge.js -> hoge.ts - editor上でエラーがわかる - 実行する前にわかる - tsconfi内、jsへのコンパイルes6 と設定すればClassとして書いたものをがes6のClass表記でかかれ、 es5 と設定すればclosureを用いてよしなに変換されていた(といったかんじのデモがあった)

typescriptを導入してみて
  • もともとslackではtypescriptを多用するつもりはなかったが、そっちで書いていったほうがいいよねとなった
  • editorのオートコンプリートが強い
  • 意外と簡単にtypescriptを使えるようになった
  • クラッシュの危機感が低くなってよい
  • コードの書き方が多少汚いPRを混ぜてしまっても、クラッシュは一旦しないだろうという安心感がある
  • tslintがまだ弱い

SEMINAR A-2 : Introduction to Lucet

Adam Foltzer

発表内容

Lucetの紹介

github.com

いろいろメモしてきたけど、WebAssembly まわりの知識がなさすぎてちゃんと書き連ねる自信がないので割愛。
こちらの記事が参考になりそうだなと思いました。

efcl.info

SEMINAR C-3 : デザインエンジニアとフロントエンド

Shinichi Kogiso

speakerdeck.com

pickupしたい点

  • デザインエンジニアという職種に対してまだまだ認知度が低い(UXエンジニアやデザインテクノロジストといった別呼称があったりも)
  • デザインエンジニアはデザイナーとフロントエンドの架け橋となり、開発を円滑に進めていくポジション
  • 専門性とスピードが求められる
  • 違う景色(社内だけでは得られない経験等)を見続けることがだいじ

AMA

app2.sli.do

デザインエンジニアの職能とかワークフローが曖昧。どう振る舞うか

-> デザイナー側やフロントエンド側に足を運び、なにか困ってないかを聞いたりして、手助けする。

意見の対立とかのコミュニケーションを取るか

-> Slackだけだと温かみがない
共有会をしてちゃんと双方向のやりとりを促す
インフラ系はあまり興味がなかったりするところに対してはちゃんと説明してあげる

若くしてデザインエンジニアを名乗れるか?

-> 可能だと思う。 各会社で新卒から採用してたりする(かも)
募集かけたらくるのでは?(取る側の話) 好奇心がある人が向いている気がする

デザインエンジニアのあとのキャリア設計(その後どうなるか)

-> フルスタックエンジニアかディレクターとかになるんじゃないかな

「なんでもできるようだけど、何が得意なの?」となることがある
弱い人が多気がするけど、なにかひとつ「これ強い」って言えたほうがいいよね

コンポーネント設計に対してデザインからの文脈とエンジニアからの文脈があるけど、どう考える/どう対処する

デザインとしたら1pxのズレや、アニメーションの違和感があったりとか。
エンジニアからしたら、なんでこれ分けるの?これいらなくない?
-> デザイナーはsketchとかでアニメーションをつけて見せたりして齟齬をなくす

実装時のコンポーネント分割と、デザインのコンポーネントの分割がずれるときは?
-> 資料とか作ってちゃんと説明する。命名規則で困ったらそれも都度MTG

デザインエンジニアと名乗るには?

-> ある特筆した能力がある上で、もう一つ能力がある、ってなったときに名乗ったらいいのでは?

副業とかに時間のバランスは?

-> 平均2~3時間、土日どちらかにがっつり時間をとる。

レガシー環境をvueなどを入れて改善したいが・・・

-> チームのモチベーションはあがる
売上とは関連するかどうかは怪しいよね
空きを見て順次導入していくほうがいいのでは。

なんでデザインエンジニアになったのか(どういう思いか)

-> 両方やりたかった

SEMINAR C-4 : いちからデザインシステムを作ってみて学んだこと

Kengo Haruno

speakerdeck.com

pickupしたい点

  • 「componentの名前付けで時間がかかる」ところに対して、「そのcomponentの役割から名前を考える」ということと「全員が納得するまで議論」する(というところがひとつ模範解答だと考える)
  • 将来的にCSSフレームワークとして提供できるよう、またデザイナーがわかりやすいようにsassでcssを書く
  • フロントエンド側(実装都合)がわかる人がコンポーネント作成のところに入ることで、「hover時のアクション」といった平面のデザインだけでは気づきにくい動的なところまで事前に調整することができた
  • デザインシステムは巨大なプロダクトなので、部分的にはじめるのでもよいかもしれない

完全に所管

デザインシステムのくだりを見て、前職でやってたことをちょっと思い出し、書いてみました

walk-diagonally.hatenablog.com

AMA

https://app2.sli.do/event/5ktrtkpp/live/questions

コンポーネントの分割ルールはどうなっていたか?

-> Atomic designを最初やってた
中間層があいまいになった。また他のメンバーとかの認識ズレが起きる
独自コンポーネントなどでAtomsなのかMoleculesなのかと不明瞭に。

-> そのため、特別ルールをつくった Iconやbuttonとかの細分化できないものは element 他は component としてあつかう

storybookのスタイルガイド化はどう?

-> 他plugin(ts用)とかとの相性が悪かったりする。
もし相性がよくなればstorybookによせる
一応挑戦はしているが、まだまだ。仕様とかは手書き

再実装するならどう考え

-> 段階的に実装をするという手法でもよかった。運用フローでばたついた

SEMINAR C-5 : AbemaTVにおけるCSS is too fragile問題に対する解

Shota Kubota

speakerdeck.com

pickupしたい点

AMA

https://app2.sli.do/event/vdvxniys/live/questions

ドメインまたぎの共通コンポーネントは?

-> srcより上にある?
client/src/components-common(?口頭だったので信憑性が低い)

デグレの確認は?

-> 目視確認
QAチームが別途いてその人達が確認

css in jsは人類にはやかったか

-> Webはw3cの規定とかあって、webに向いてなかったかもしれない
react-nativeとかにありなんじゃない?(まあそもそもcssないし)

次かえるとしたら?

-> 具体的なところはなし

コンポーネント内包したらBEMくずれるのでは?

-> コンポーネント単位で保証しているので崩れることはない またはコードビューではじく

特定のドメインないでしか使われないコンポーネントはどこ?

-> /featureA/src/components/.. みたいなかんじ?

上着きやめる、はなかったの?

-> とりあえずデグレを対処しなきゃいけなかった
コンポーネントの数と使ってる場所が多すぎたので、場当たり的対処になってしまったところはある

コンポーネント感のマージンってどうなってる?

-> Atom / molecules /とかでは極力やってない

コンポーネントガイドとかスタイルガイドとかは?

-> 独自のものがある、がしかしちゃんと運用されてない

lintどの程度きつくしているか

-> Evalとかのやばいのはerror
ほかはコーディングしているのが苦しくなりすぎないようにwarnとかにしておいてる

SEMINAR C-6 : 品質と開発速度を両立させるために捨てたものと守ったもの

Tsuyoshi Wada & Soichi Masuda

docs.google.com

pickupしたい点

  • あたりまえ(過去の実践済み / すでに世の中に知見がある)を積み重ねる
  • Development policy - Accessibility の展開
  • ある程度負債を許容する(見極めつつ)

AMA

https://app2.sli.do/event/5idlaspx/live/questions

ユーザーのフィードバックあんまりないのでは?

-> ユーザー層的には多くはない
きたものは見るようにしてる。 ユーザーの行動から判断とかはやりたい

アクセシビリティの配慮どうやったのか?

-> 開発からディレクターに対してそのあたりは考慮してもらえた。

品質の定義は?

アクセシビリティ
-> マークアップとかはエンジニア間でズレていた(厳密には定義をしなかった) -> develop ment policyを作ってそれで定義する

GraphQLの導入は?

-> server-side側を巻き込むのが難しかったからそもそも考慮していなかった

脱Reactしたかったのか?

-> 飽きたからしたかった笑
Edgeに寄せたくてもっとちっちゃいjsとかの利用は少し検討した
しかし100ページ近くの画面があり、巨大な負債になることを恐れた

spのフォーカスもできているのか

-> componentはレスポンシブに対応させているのでpc共通。そのため双方で対応できている

IEの対応は?

-> 年齢層高いし対応はしている。 Abemaの実況見ながらとかの利用も想定はしている。 全く動かないとかはない

importはページ単位?

-> Yes。チャンクが違う

納期伸びなかったらどっち?

-> 品質を諦めた。速度優先

競輪知らなかったようだがどうしたか?

-> 自分たちで体験とかもした

いろいろやってたことが多岐にわたってたけどどうしてたの?

-> できる人がやっていた(チーム内で自然と)

パフォーマンス手法はどこから?

-> チームメンバーから もしくはツイッターとかから入手

focus管理は?

-> ライブラリは自前で作った

accesibiltyはかるルールは?

-> ない

PWAの理由

-> Google play app にギャンブルないからお察し

ディレクションとの競合は?

-> 与えられた予算で頑張る

jsテストは?

-> visual regression test

アクセシビリティ / パフォーマンスについてどこからやるか


- アクセシビリティ : ユースケース、ユーザー想定とかからちゃんと認識を固定する
- パフォーマンス : 調べ方を調べる、FCPとかの単語とかを把握する(そうしたら検索することができる)

全体を通しての所管

各技術の組み合わせのパターンや、枝葉のところでまだまだ知らないことがあるのかなと思ったので、積極的に情報収集していきたい

HTMLタグの「defer」でちょっと実験してみた

本来であればそのタグが解析されたタイミングでjsの読み込み->実行が行われるところですが、「defer」を使うことにより、HTMLパースを阻害せず、なおかつ DOMContentLoaded より先に実行されるという画面描画をほどよくブロッキングしない仕組みがあったので、少し実験をしてみました。

developer.mozilla.org

混ぜてみる

// sample-1.js
console.log("sample-1 is called");

// sample-2.js
console.log("sample-2 is called");
<script defer src="/js/sample-1.js"></script>
<script src="/js/sample-2.js"></script>

結果

sample-2 is called
sample-1 is called

defer をつけていない方はパースされたタイミングで実行されるので、先に呼び出される。

両方つけてみる

// sample-1.js
console.log("sample-1 is called");

// sample-2.js
console.log("sample-2 is called");
<script defer src="/js/sample-1.js"></script>
<script defer src="/js/sample-2.js"></script>

結果

sample-1 is called
sample-2 is called

defer がついているものに関してはタグが記載されている順番で実行される

所感

今まであった </body>の近くにjsのファイルはおきましょう みたいなことはもうこれ以降気にしなくてよくなるのはありがたいですね。 もっとしっかり描画速度の最適化をしたい、ということだったら関係ないファイルとかは async つけたりして、完全に非同期で読み込むといいのだろうと思います。 ただ、その分類がなかなか手間だと思うので、困ったらひとまず defer をつけるでいいのかなと思います

GASでspreadsheetに追記できるwebアプリを作ってみた。

Webアプリからspreadsheetにデータを送りたかったんですが、大変でした。

TL;DR

簡単にwebappを作るなら

  1. SpreadSheetからgoogle apps scriptを生成する
  2. VueCLI3でプロジェクト作成し、vue.config.jsをいじる
  3. claspインストールし、2で作成したプロジェクトの成果物をpushできるようにする
  4. POSTで書き込みをしようとするのではなく、 google.script.run.○○ で実行する

解説

1. SpreadSheetからgoogle apps scriptを生成する

SpreadSheetからgasを作成します。 この際gasとsheetを分けても問題ないが、呼び出しが少し面倒になるため、個人的にはsheetから生成したほうがいいと思っています。

2. VueCLI3でプロジェクト作成し、vue.config.jsをいじる

vue create gasapp
cd gasapp
npm i -D html-webpack-inline-source-plugin webpack-cdn-plugin

プロジェクトを作成し、以下のvue.config.jsで使うためのモジュールをinstall。 cli.vuejs.org

// vue.config.js
module.exports = {
  chainWebpack: config => {
    // disable prefetch and preload
    config.plugins.delete("prefetch");
    config.plugins.delete("preload");

    // Make js and css files inline into index.html
    config
      .plugin("html-inline-source")
      .use(require("html-webpack-inline-source-plugin"));
    config.plugin("html").tap(args => {
      args[0].inlineSource = "(/css/.+\\.css|/js/.+\\.js)";
      return args;
    });

    // make inline images
    config.module
      .rule("images")
      .use("url-loader")
      .options({});

    // make inline media
    config.module
      .rule("media")
      .use("url-loader")
      .options({});

    // make inline fonts
    config.module
      .rule("fonts")
      .use("url-loader")
      .options({});

    // make inline svg
    config.module
      .rule("svg")
      .uses.delete("file-loader")
      .end()
      .use("url-loader")
      .loader("url-loader")
      .options({});

    // Get npm modules from CDN
    config.plugin("webpack-cdn").use(require("webpack-cdn-plugin"), [
      {
        modules: [
          {
            name: "vue",
            var: "Vue",
            path: "dist/vue.runtime.min.js"
          },
          {
            name: "vue-router",
            var: "VueRouter",
            path: "dist/vue-router.min.js"
          }
        ]
      }
    ]);

    if (process.env.NODE_ENV === "production") {
      // html minify settings for GAS
      config.plugin("html").tap(args => {
        args[0].minify.removeAttributeQuotes = false;
        args[0].minify.removeScriptTypeAttributes = false;
        return args;
      });
    }
  }
};

こちらに記載されていたもののパクりです。 とても感謝してます。

qiita.com

これにより、vueで書いてもgas上で動かせるようになりました。

claspインストールし、2で作成したプロジェクトの成果物をpushできるようにする

qiita.com

こちらを参考にclaspを使えるようにした。

qiita.com

また、こちらを参考に appsscript.json 等々を配置

package.jsonscript"push": "vue-cli-service build && clasp push -f" を追記してdist以下の生成とそれらのpushをひとまとめにするとラクでした。

4.POSTで書き込みをしようとするのではなく、 google.script.run.○○ で実行する

一番大変なところでした。 詳細は下に記載するとして、まず結論としてページのview部分のファイルはこのようになりました。 *CSSフレームワークにbulmaを使用してます

// index.vue
<template>
  <div class="container">
    <h1>Input Your Data</h1>
    <div class="field">
      <div class="control">
        <input class="input is-info" type="text" placeholder="Text" v-model="text">
      </div>
    </div>
    <div class="field">
      <div class="control">
        <a class="button is-link" @click="onClick">Submit</a>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Index",
  data() {
    return {
      text: ""
    };
  },
  methods: {
    onClick: function(e) {
      google.script.run.addData(
        JSON.stringify({
          text: this.text,
        })
      );
   }
};
</script>

Code.js(google apps script)

function doGet() {
  return HtmlService.createHtmlOutputFromFile("index").addMetaTag(
    "viewport",
    "width=device-width, initial-scale=1"
  );
}

function addData(rawParams) {
  Logger.log("addData");
  var params = JSON.parse(rawParams);
  var ss = SpreadsheetApp.getActive();
  var sheet = ss.getActiveSheet();
  var values = [params.text];
  sheet.appendRow(values);
}

どうにかしてPOSTでできないかと考えていましたが、普通に google.script.run.hogehoge とやったら動きました。

詰まったところ : POST編

詰まった要因として一番大きかったところはPOSTでリクエストを飛ばしてどうにかできないかと考えていたところでした。

一番最初に考えたこと

axiosを入れて普通にpostしようとした

axios.post("https://script.google.com/macros/s/AKfxxxxx/exec", params)

->405エラー OPTIONSのmethodで飛ばされてしまっているらしい。

stackoverflow.com

次に考えたこと

それだと通らないようだったので application/x-www-form-urlencoded で投げるように修正してみました。

const params = new URLSearchParams();
params.append("test", this.test);
axios.post("https://script.google.com/macros/s/AKfxxxxx/exec", params)

Access to XMLHttpRequest at 'https://script.google.com/macros/s/AKfxxxxx/exec' from origin 'https://n-hv3nxxxxx-script.googleusercontent.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

???
どうやらoriginが違う・・・
ブラウザでアクセスしているURLも https://script.google.com/macros/s/AKfxxxxx/exec にもかかわらず、originが違う認識になっている。
デベロッパーツール開いて window.location.href 等でURLを見てみても https://script.google.com/macros/s/AKfxxxxx/exec になっているのでなかなか不思議な現象。
きっとセキュリティ的な問題でこういう仕様になっているのだろうと諦めた。

結果としておかげさまで google.script.run にたどりつけたのでよかったといえばよかった。
そして公式のドキュメントにも実はちゃんと書いていた。

developers.google.com

詰まったところ : Lambda編

ブラウザから叩こうとするからCORSで阻まれるので、何らかの形でサーバー側から実行できたらいいじゃんと考え、なんとなくlambdaでできないかと試してみた。

qiita.com

紆余曲折はあったものの、上記を参考にして一旦動くようにはなったが、定期的にtokenのリフレッシュをしなければいけない、というところで少し面倒+そこまでして動かしたいものではないなということで断念。

その後いろいろ試してみたら

// Lambda
const request = require("request");

const headers = {
  "Content-type": "application/json"
};

const dataString = '{"value":"aaa"}';

var options = {
  url:process.env['url'],
  method: "POST",
  headers: headers,
  body: dataString
};

function callback(error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body);
    const response = {
    statusCode: 200,
    body: JSON.stringify("Hello from Lambda!")
  };
  return response;
  }else{
    console.error(error)
  }
}

exports.handler = event => {
  console.log("POST gas to sheet");
  request(options, callback);
  console.log("Finished");
  // TODO implement
  
};

だいぶてきとーに書いてますが、普通に request で飛ばしたらいけました。
tokenとか全然関係ないのか・・・

余談

実装してみたサンプルコード

github.com

jsでパスワードのvalidationのようなものを書いてみた

ちょっとしたvalidationのようなものを書いてみたので、備忘録として残しておきたい。

前提

HTMLはシンプルに

<input type="password" id="passwordInput"/>

こんなかんじの想定です。
あとjs上での下処理は

let passwordText = document.getElementById('passwordInput').value;

とします。

文字数の確認

passwordの文字が 8文字以上 で良しとしたい場合の想定です。 これはシンプルにlengthで取れますね

if(passwordText.length < 8){
  // 何らかのエラー処理
}else{
  // 正常時の処理 
}

HTMLタグのmaxlength

そういえばHTML5の仕様でタグ上に記載することができますね。

<input type="password" id="passwordInput" maxlength="8"/>

こうすることでjs側での処理は不要になりますね。

同じ文字がいないかどうか

aa11 みたいに連続した文字がいた場合にエラーとしたいときのロジックです。

let passwordTexts = passwordInput.split('');
let previousCharacter = '';
let conuter = 1;
let hasSameCharacter = passwordTexts.some((character) => {
  if(character === previousCharacter){
    conuter++;      
  }else{
    previousCharacter = character;
    conuter = 1;      
  }
  return conuter === 2
});
if(hasSameCharacter){
  // エラー処理
}

特定の文字入力があるかどうかの判定

今回の想定では英字と数字、どちらも入ってるかどうかチェックするというものです。

let strMutcher = passwordText.match(/[a-z]/gi);
let numMutcher = passwordText.match(/[0-9]/gi);
if(strMutcher === null || numMutcher === null){
 // エラー時処理等
}

match でokだった場合は配列が返ってくるので、できれば .length > 0 あたりで判定したいところなのですが、
NGだった場合にnullしか返してこないので上記のような書き方をしました。
(個人的にもう少し改良の余地はあるように思える)
(正規表現がちょっと適切ではない気がするので、もっと勉強が必要)

HTMLタグで正規表現

<input type="password" pattern="^[0-9A-Za-z]+$">

と、いったかんじでタグ上でも正規表現を用いてチェックすることができるようです。 www.htmq.com

ちょっとしたポップアップも出て、便利ですね。
ただしこれ、formタグとセットで使わなければいけないので(ポップアップが出るのもきっとsubmitされるとき)
ページの作り方によっては使いにくいかもしれません。

余談

HTMLやjsでvalidationをする方法を上に書きましたが、結局クライアント側ではどうとでもできるので、本格的な処理はやはりjsで書かなければいけませんね。

あとはHTMLとjs、双方向からできるにしても、どの処理がどっちで担当しているか、というのがごちゃ混ぜになると管理が大変になると思うので、 個人的にはある程度jsに寄せたいなと思う派です。

以上、備忘録でした

Vue CLI3のproductionでconsole.logを消した方法

やりたかったこと

本題の通りなのですが、productionの状態でbuildしたソースからよろしくconsole.logを消せないかなと思ったのでいろいろ調べてみました。

結論

uglifyjs-webpack-plugin を入れて、vue.config.jsにconsole.logを消す設定を書く。

pluginのインストール

npm i -D uglifyjs-webpack-plugin

vue.config.jsに書き足す

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const isProd = process.env.NODE_ENV === "production";
module.exports = {
  configureWebpack: {
    optimization: {
      minimizer: isProd ? [
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: {
              drop_console: true
            },
          }
        })
      ] : []
    }
  }
}

こちらで発見しました

forum.vuejs.org

所感

これを試したのは個人的につくった実装物なので、一旦これでいいんですが、もう少し大きい実装で、コードを難読化したら発生したbugとかに関してはlogがでなくてちょっとつらいのかなと思いました。
もう少しいろいろ設定ができそうなので、折を見て試して追記できたらと思います