dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

webpack+ES2015でGoogle Apps Scriptローカル開発するためのテンプレート作った

gapps を使って Google Apps Script をローカルで開発するための方法については 以前 Qiita に書いた し、それにより ES2015 や TypeScript で書いて手元でビルド、みたいなことはみんなやるようになったんだけど
webpack を使った構成が探してもあまり見つからなかったので自分用に作った。


特徴

ES2015 で書いて webpack でビルド、ESLint で構文チェック

業務でも使っているスタックで GAS が書けるようになった。 import/export でファイルを適切に分割できてうれしい。
最終的なビルド結果を GAS で使える用にエクスポートする方法がわからなかったんだけど、gas-webpack-plugin というのを使わせていただいた。

// webpack.config.babel.js
import GasPlugin from 'gas-webpack-plugin';

export default {
...
  plugins: [
    new GasPlugin(),
  ]
}

と書き、スクリプト側は

global.hello = function () {
}

とすれば良い。


.env に定義した環境変数を読み込めるように

GAS で何かしたいときって Slack などの外部サービスと連携することが多く、トークンなどの情報をコード中に埋め込むとスクリプトが公開しづらくなるかと思って .env から読み込めるようにした。


watch モードつき

ファイルの変更監視して再ビルド・アップロードをできるように watch コマンドも作っておいた。
https://github.com/mikeal/watch というのがあるらしい。npm scripts だけでいけるんですね。

Meguro.es x Gotanda.js #1 in Drecomに行ってきた

行ってきました。


hyperapp について Jorge Bucaran

  • https://github.com/hyperapp/hyperapp
  • SPA を作るための 1kb の軽量ライブラリ
  • Virtual DOM + Redux/Elm 的な State 管理 + Router
  • Fast
  • React や Vue は framework っぽすぎ
  • "dependencies": {}


API ドキュメンテーションと mock サーバ mizuki_r


JSerのためのブラウザコードリーディング(テスト編) edwardkenfox


大規模静的サイトのためのビルドツール ktsn


仮想domを実装した感想 brn0227


Single File Components++ kazupon


TypeScriptのプラグインについて Quramy


Cycle.js の紹介 ( 改訂版 ) - リアクティブ・プログラミングに特化した JS フレームワーク wakamsha

  • Cycle.js = Observable x Virtual DOM
  • xstream (RxJS の軽量版) と Snabbdom (仮想DOMを操るシンプルなライブラリ) に依存
    • rxjs は Promise のすごいやつ
    • xstream: github.com/staltz/xstream
  • Viewも純粋なJSの関数で組み立てる。のでtypoするとビルドエラーで気づける
  • アプリケーションを main() と driver() に分ける
    • driver はDOM操作、API実行など副作用を扱う
    • main は state を管理する
    • driver は副作用を main に投げ、main は state を更新した結果を driver に Sink する??このサイクルが名前の由来

React/Reduxの設計に関する参考記事まとめ

最近悩んでいる React/Redux でそれなりの規模のアプリケーションを作るための良い設計について、
日頃ネットで気になる記事を漁っていたんだけど、積読がたまってきた&Twitter やら Pocket やら Qiita に散らばってしまったのでここらで一旦整理します。

(★ はその中でも特に読みたいもの)


Redux の設計

実際に GitHub にあるソースコードを読んで得られた知見について。
「Storeはどんな具合に構成すべきか」「Store初期化(hydration)用データの定義はどうすべきか」「Componentはどう整理すべきか」と目次だけ見ても非常に実用的な内容。

Ducks というディレクトリ構成の考え方。

React/Redux に限らず、複雑なアプリケーションをどう設計するかという点で非常に参考になる。
またこの中の 複雑なJavaScriptアプリケーションを考えながら作る話 で Flux の話をしている。
CQRS を理解したい。

無料の Ebook


Immutable.js

Redux にモデル層を云々と言われているやつ。

サンプルは簡単な Todo アプリだが、 Immutable.Record を使ったモデルという考え方を理解するのに一番良い記事に見える。

その他、日本語でも入門的記事はいくつか見つかった。


Redux その他


バリデーション

Redux でバリデーション処理をどこに実装するのが正解なのかなーというのは自分も気になっていたので。


非同期処理

いまは redux-thunk 使っているけど、redux-saga 使うことになったら読みたい記事。
後者は Action を UI 寄りの低レベルのものとビジネスロジック寄りの高レベルのものに分けて考えていて、saga を使わなくてもこういった考え方は参考になる。

こちらは async/await 使えば Middleware なくてもきれいに書けるんじゃないか、という話。


Tips 的な

一回目を通すだけで良さそう。

React の様々なパターンやテクニックについて。


番外編:RxJS

興味はあるがおそらく手を出すのはだいぶ先かなー。。。

Lightning Utility Barを作ってみた

Spring'17 から利用可能になった Utility Bar を作ってみたので、その手順を残しておきます。

f:id:dackdive:20170419225949p:plain

とりあえず Hello, World! と表示するところまで。

こちらの記事が参考になりました。

一応、公式の Implementation Guide とやらもあるみたいだけど、
https://resources.docs.salesforce.com/204/latest/en-us/sfdc/pdf/utility_bar_impl_guide.pdf
おそらく情報が古く、REST API 経由で操作するような記述が見られるが実際には必要ありませんでした。

以下、作り方。


Utility Bar のコンテンツとなる Lightning Component を作る

通常の Lightning Component と同じように作ります。
flexipage:availableForAllPageTypes を implement する必要があります。

<aura:component implements="flexipage:availableForAllPageTypes">
  <div class="slds-text-heading--large">Hello, World!</div>
</aura:component>


FlexiPage メタデータを用意する

Lightning Utility Bar も、メタデータ的には App Builder で作ったページと同じ FlexiPage なんだそうです。
FlexiPage のメタデータについては以下。

FlexiPage | Metadata API Developer Guide | Salesforce Developers

実際には、いきなりローカルでメタデータを作るのではなく

設定 > アプリケーション > アプリケーションマネージャ

より任意のアプリケーションの編集画面を開き、「ユーティリティバー」タブから画面上でユーティリティバーを作成し、できたメタデータをダウンロードする方が早いです。
「追加」を押すと先ほどの Lightning Component も表示されるはず。

f:id:dackdive:20170420000102p:plain

保存したら Force.com Migration Tool や jsforce-metadata-tools などを使って CustomApplication と FlexiPage を retrieve してきます。

retrieve してきた FlexiPage の中身はこんな感じ。

<?xml version="1.0" encoding="UTF-8"?>
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <flexiPageRegions>
        <componentInstances>
            <componentInstanceProperties>
                <name>eager</name>
                <type>decorator</type>
                <value>false</value>
            </componentInstanceProperties>
            <componentInstanceProperties>
                <name>height</name>
                <type>decorator</type>
                <value>480</value>
            </componentInstanceProperties>
            <componentInstanceProperties>
                <name>icon</name>
                <type>decorator</type>
                <value>custom_apps</value>
            </componentInstanceProperties>
            <componentInstanceProperties>
                <name>label</name>
                <type>decorator</type>
                <value>UtilityBarSample</value>
            </componentInstanceProperties>
            <componentInstanceProperties>
                <name>scrollable</name>
                <type>decorator</type>
                <value>true</value>
            </componentInstanceProperties>
            <componentInstanceProperties>
                <name>width</name>
                <type>decorator</type>
                <value>440</value>
            </componentInstanceProperties>
            <componentName>UtilityBarSample</componentName>
        </componentInstances>
        <name>utilityItems</name>
        <type>Region</type>
    </flexiPageRegions>
    <masterLabel>MyFirstUtilityBar</masterLabel>
    <pageTemplate>one:utilityBarTemplateDesktop</pageTemplate>
    <type>UtilityBar</type>
</FlexiPage>

ファイル名は [アプリケーション名]_UtilityBar.flexipage とかになってるはずですが、カスタムアプリケーション側の <utilityBar> 名と一致していれば好きな名前を付けられるはず(未確認)。

また、画面から設定できるユーティリティ項目は、XMLcomponentInstanceProperties >name に対応しますが、その対応付けは確認した限りは以下の通りです。

f:id:dackdive:20170420001905p:plain

eager 以外はわかりやすいですね。

また、 <componentName> は Lightning Component 名と揃える必要があります。


CustomApplication のメタデータに追加する

最後に、Utility Bar をアプリケーションに追加した場合の CustomApplication メタデータは以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<CustomApplication xmlns="http://soap.sforce.com/2006/04/metadata">
    <brand>
        <headerColor>#0070D2</headerColor>
    </brand>
    <formFactors>Large</formFactors>
    <label>MyLightningApp</label>
    <navType>Standard</navType>
    <uiType>Lightning</uiType>
    <utilityBar>MyLightningApp_UtilityBar</utilityBar>
</CustomApplication>

<utilityBar>MyLightningApp_UtilityBar</utilityBar> の部分です。


おわりに

画面から Utility Bar を作れるようになったことでずいぶん楽になったんでしょう。
今回は Hello, World! を表示するだけの実用性のないコンポーネントでしたが、いろんな可能性のある機能なので引き続き何か作りたいと思います。

冒頭で紹介した記事のほか、こちらにもサンプルコードがあるので参考になりそう。


GitHub

https://github.com/zaki-yama/lightning-component-samples/tree/master/lightning-utility-bar

FlowtypeのUtility TypesでESLintエラーを出さないようにする

ちょいメモ。
Flowtype の Utilty Types を使っていて

type Exact<T> = T & $Shape<T>;

などと書いたら ESLint でエラーになった。

error  '$Shape' is not defined  no-undef

eslint-plugin-flowtype は導入済みで、各バージョンは以下の通り。

$ npm list --depth=0 | grep eslint
├── babel-eslint@7.2.2
├── eslint@3.19.0
├── eslint-config-airbnb@13.0.0
├── eslint-plugin-flowtype@2.30.4
├── eslint-plugin-import@2.2.0
├── eslint-plugin-jsx-a11y@2.2.3
├── eslint-plugin-react@6.10.3

解決策

.eslintrc に以下の2行を追加すると出なくなった。

   "rules": {
      ...
+    "flowtype/define-flow-type": 1,
+    "flowtype/use-flow-type": 1,
   }

が、それぞれ何を指しているのか、したがってなぜこれでエラーが出なくなったかはよくわかっていない。

ここにたどり着いたのはたしかこの記事を読んでだったと思う。

ctrlp.vimでファイルを検索するときのウィンドウサイズを変更する

前回に続き、ctrlp.vim についてのメモ。

ctrlp.vim でファイルを検索するとき、そのままだと候補の一覧がウィンドウ下部にmax10件ぐらいしか表示されない。
ここのサイズを変更したい。

f:id:dackdive:20170407003231p:plain

設定方法を調べてみたところ、この Issue に書いてあった。

Not enough results · Issue #187 · kien/ctrlp.vim

まず、Issue には

:help g:ctrlp_max_height

で調べてみろとあるのでヘルプを見てみるとわかるが、 g:ctrlp_max_height 自体は別の変数 g:ctrlp_match_window に統合されたのでこちらを設定する。
g:ctrlp_match_window は Example にあるように

let g:ctrlp_match_window = 'bottom,order:btt,min:1,max:10,results:10'

のように、bottommin/max などいくつか設定できるパラメータがあり、カンマ区切りで指定する。

指定できるパラメータは以下の通り。

パラメータ 意味 デフォルト
top/bottom ウィンドウを上下どちらに表示するか bottom
btt/ttb 結果の並び順
ttb: top to bottom
btt: bottom to top
(具体的にどう変わるのかよくわかってない)
btt
min, max ウィンドウの最小高さと最大高さ min:1
max:10
results 結果を最大何件表示するか max height と同期

というわけで、表示する件数を増やしたい場合は max だけ指定すれば良い。

自分は

let g:ctrlp_match_window = 'max:30'

とした。

ctrlp.vimでnode_modulesなどのフォルダを除外する

ちょいメモ。

VimAtomVSCode のような Ctrl + P によるファイル検索ができるようにする ctrlp.vim というプラグイン
便利なんだけど、node_modules があるプロジェクトで使うと起動が遅かったり node_modules 内のファイルまで検索対象になってしまっていたので
特定のフォルダを対象から除外する方法が調べてみたら、Issue にあった。

.vimrc に

let g:ctrlp_custom_ignore = 'node_modules\|DS_Store\|git'

と書くだけでよかった。