2020/01/25 GKE/k8s でscale to zero

cloud.google.com


調べたいこと

  • ノードプールが0個にまでスケールダウンするか
  • どれくらいの早さでスケールダウン可能と検知されるか
  • 初期サイズ0でノードプールが作れるか
  • リージョナルクラスタのとき、特定のゾーンだけでも0個にまでスケールダウンするか(ゾーンごとに不揃いになれるか)
  • kube-systemのpodがあってもちゃんとスケールダウンできるか

実験用クラスタ

  • バージョン v1.15.7-gke.2
  • リージョナルクラスタ
  • プリエンプティブ
  • default-pool: n1-standard-1, autoscale(0~1), inititial: 1
  • pool-1: n1-standard-2, autoscale(0~3), initial: 0

スケールの最小が0であれば初期サイズ0でクラスタ構築できた


スケールアウト確認

適当なJobを、サイズ0状態のノードプールでしか起動できないrequestを付けてデプロイ

https://cloud.google.com/kubernetes-engine/docs/how-to/jobs#creating_a_job

apiVersion: batch/v1
kind: Job
metadata:
  # Unique key of the Job instance
  name: example-job
spec:
  template:
    metadata:
      name: example-job
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl"]
        args: ["-Mbignum=bpi", "-wle", "print bpi(2000)"]
        resources:
          requests:
            memory: "1Gi"
      # Do not restart containers after they exit
      restartPolicy: Never
gke-standard-cluster-1-pool-2-5b0626e0-k4m2         Ready    <none>   73s   v1.15.7-gke.2

スケールアウトした


スケールダウン確認

10分立つとノードが消えた

What are the parameters to CA? github.com

scale-down-unneeded-time パラメータがデフォルトで 10 minutes

GKEだと、組み込みのオートスケーラの設定は変えられない模様

(組み込みのオートスケーラをOFFにして自分でオートスケーラをセットアップする技があるっぽい・・・?)


kube-system podが走っているノードのスケールダウン

I have a couple of nodes with low utilization, but they are not scaled down. Why? github.com

What types of pods can prevent CA from removing a node? github.com

kube-system配下のpodは、DaemonSetやkube-proxyを除いて、デフォルトでは移動されずオートスケールダウンを阻害する模様

How to set PDBs to enable CA to move kube-system pods? github.com

PDBを明示的に付与すると移動させることができる

現状

kubectl describe no | grep -e Name: -e kube-system

Name:               gke-standard-cluster-1-default-pool-4c3839c2-jlcv
  kube-system                fluentd-gcp-v3.1.1-rnnpt                                        100m (10%)    1 (106%)    200Mi (7%)       500Mi (18%)    53m
  kube-system                kube-dns-5dbbd9cc58-flsk8                                       260m (27%)    0 (0%)      110Mi (4%)       170Mi (6%)     53m
  kube-system                kube-dns-autoscaler-6b7f784798-ppj8j                            20m (2%)      0 (0%)      10Mi (0%)        0 (0%)         53m
  kube-system                kube-proxy-gke-standard-cluster-1-default-pool-4c3839c2-jlcv    100m (10%)    0 (0%)      0 (0%)           0 (0%)         53m
  kube-system                prometheus-to-sd-6j4vr                                          1m (0%)       3m (0%)     20Mi (0%)        20Mi (0%)      53m
Name:               gke-standard-cluster-1-default-pool-da57e6c7-pwzb
  kube-system                fluentd-gcp-v3.1.1-v5kqs                                        100m (10%)    1 (106%)    200Mi (7%)       500Mi (18%)    53m
  kube-system                heapster-664fdc77f4-9xjls                                       63m (6%)      63m (6%)    215840Ki (7%)    215840Ki (7%)  53m
  kube-system                kube-dns-5dbbd9cc58-4nfr2                                       260m (27%)    0 (0%)      110Mi (4%)       170Mi (6%)     53m
  kube-system                kube-proxy-gke-standard-cluster-1-default-pool-da57e6c7-pwzb    100m (10%)    0 (0%)      0 (0%)           0 (0%)         53m
  kube-system                l7-default-backend-84c9fcfbb-ffgxf                              10m (1%)      10m (1%)    20Mi (0%)        20Mi (0%)      53m
  kube-system                prometheus-to-sd-94nvv                                          1m (0%)       3m (0%)     20Mi (0%)        20Mi (0%)      53m
Name:               gke-standard-cluster-1-default-pool-ea34b5f9-l0xq
  kube-system                event-exporter-v0.3.0-74bf544f8b-jdzp6                          0 (0%)        0 (0%)      0 (0%)           0 (0%)         53m
  kube-system                fluentd-gcp-scaler-dd489f778-chg6d                              0 (0%)        0 (0%)      0 (0%)           0 (0%)         53m
  kube-system                fluentd-gcp-v3.1.1-fxnhq                                        100m (10%)    1 (106%)    200Mi (7%)       500Mi (18%)    53m
  kube-system                kube-proxy-gke-standard-cluster-1-default-pool-ea34b5f9-l0xq    100m (10%)    0 (0%)      0 (0%)           0 (0%)         53m
  kube-system                metrics-server-v0.3.3-6d96fcc55-jcr2l                           48m (5%)      143m (15%)  105Mi (3%)       355Mi (13%)    53m
  kube-system                prometheus-to-sd-8mc5s                                          1m (0%)       3m (0%)     20Mi (0%)        20Mi (0%)      53m
  kube-system                stackdriver-metadata-agent-cluster-level-59f55f888f-5lsws       40m (4%)      0 (0%)      50Mi (1%)        0 (0%)         53m

DaemonSet

kubectl get ds -n kube-system

NAME                       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                                                              AGE
fluentd-gcp-v3.1.1         3         3         3       3            3           beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/os=linux       99m
metadata-proxy-v0.1        0         0         0       0            0           beta.kubernetes.io/metadata-proxy-ready=true,beta.kubernetes.io/os=linux   99m
nvidia-gpu-device-plugin   0         0         0       0            0           <none>                                                                     99m
prometheus-to-sd           3         3         3       3            3           beta.kubernetes.io/os=linux                                                99m

kube-dns-5dbbd9cc58-flsk8kube-dns-autoscaler-6b7f784798-ppj8j が移動できれば gke-standard-cluster-1-default-pool-4c3839c2-jlcv がスケールダウンできる

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: kube-dns-pdb
  namespace: kube-system
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      k8s-app: kube-dns
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: kube-dns-autoscaler-pdb
  namespace: kube-system
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      k8s-app: kube-dns-autoscaler

PDBを設定してみる

10分待ってもスケールダウンしない・・・


kubectl describe no gke-standard-cluster-1-default-pool-4c3839c2-jlcv

Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource                   Requests     Limits
  --------                   --------     ------
  cpu                        481m (51%)   1003m (106%)
  memory                     340Mi (12%)  690Mi (26%)
  ephemeral-storage          0 (0%)       0 (0%)
  attachable-volumes-gce-pd  0            0

よく見たらギリギリCPUのリクエストが51%だった・・・


手動でリソースをすこし寄せる

cordonしたうえで削除して無理やり別のノードへ配備させる

kubectl cordon gke-standard-cluster-1-default-pool-4c3839c2-jlcv

kubectl delete po -n kube-system kube-dns-5dbbd9cc58-jz78s

Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource                   Requests    Limits
  --------                   --------    ------
  cpu                        221m (23%)  1003m (106%)
  memory                     230Mi (8%)  520Mi (19%)
  ephemeral-storage          0 (0%)      0 (0%)
  attachable-volumes-gce-pd  0           0

10分後

kubectl get ev -w

0s          Normal   ScaleDown            node/gke-standard-cluster-1-default-pool-4c3839c2-jlcv   marked the node as toBeDeleted/unschedulable
0s          Normal   NodeNotReady         node/gke-standard-cluster-1-default-pool-4c3839c2-jlcv   Node gke-standard-cluster-1-default-pool-4c3839c2-jlcv status is now: NodeNotReady
0s          Normal   Deleting node gke-standard-cluster-1-default-pool-4c3839c2-jlcv because it does not exist in the cloud provider   node/gke-standard-cluster-1-default-pool-4c3839c2-jlcv   Node gke-standard-cluster-1-default-pool-4c3839c2-jlcv event: DeletingNode
0s          Normal   RemovingNode                                                                                                      node/gke-standard-cluster-1-default-pool-4c3839c2-jlcv   Node gke-standard-cluster-1-default-pool-4c3839c2-jlcv event: Removing Node gke-standard-cluster-1-default-pool-4c3839c2-jlcv from Controller

kubectl get no

NAME                                                STATUS   ROLES    AGE    VERSION
gke-standard-cluster-1-default-pool-da57e6c7-pwzb   Ready    <none>   118m   v1.15.7-gke.2
gke-standard-cluster-1-default-pool-ea34b5f9-l0xq   Ready    <none>   118m   v1.15.7-gke.2

スケールダウンした

2020/01/21 slow_query / Cypress / @sentry/node

slow_query

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.Concepts.MySQL.html

If log_output = TABLE, you must specify an integer value with second resolution.

出力先を TABLE にしていると秒単位の精度でしか long_query_time が指定できない

log_output = FILE に変える


ログファイルはRDSの画面で見るよりCloudWatchで見たほうが楽


# Time: 2020-01-21T02:05:37.696600Z
# User@Host: xxxxxx[xxxxx] @  [IP ADRESS]  Id: dddddd
# Query_time: 1.270852  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 0
SET timestamp=1579572337;
COMMIT;

みたいなのが多い

これは何?

stackoverflow.com

SET timestamp はslow logに必ず現れるだけのもの

遅いのは COMMIT


stackoverflow.com

アプリ側でtraceも入れないと特定できない?

Cypressでテストケース間でログイン状態が維持される

テストケース間でCookieはクリアされる仕様のはずなのに

github.com

ずっとopenなissueがある


おそらく原因判明

直前のテストの最後で呼び出されたAPIが、テスト終了してCookieクリアしたあとに呼び出し完了し、Cookieをセットしていた

修正して事象が発生しなくなるか様子見

@sentry/node でError.stackTraceLimitがセットされない

@sentry/browser では50に変更される

github.com

むかしの raven-node ではInfinity

github.com

2020/01/19 ReactでCSRF対策調査

docs.nestjs.com

github.com

csurf パッケージあたりから調べ始める


csurf 、ログアウト/ログインしてユーザが変わってもトークンがinvalidにならない

認証とまったく連携してない

CSRFトークンってそういうものなのか


csurf のドキュメントのとおり { cookie: true } にしてるせいだった

これだと独自のcookie storeに保存する

sessionに保存するようにすればログアウト時にsession消してるので消える

RailsCSRF対策まわりのコード読んでみてもそんな感じっぽい(特にcurrent_user_idをトークンに含めて〜とかではなさそう)

github.com

2020/01/18 git log --graph --format


Squashマージが基本なレポジトリだと --date-order の方が見通しがいい感

2020/01/13 CreateReactApp

CreateReactAppのテスト動かす

github.com

masterはCIコケてるので3.3.0タグで

git checkout -b 3.3.0 v3.3.0
yarn
yarn test

pass

create-react-app/test at master · facebook/create-react-app · GitHub

cd packages/react-scripts/ && yarn link; cd ../../test/ && ../node_modules/.bin/jest --watchAll
 PASS  fixtures/issue-5947-not-typescript/index.test.js
 PASS  fixtures/mjs-support/index.test.js (53.148s)
 PASS  fixtures/typescript-typecheck/index.test.js (49.245s)
 PASS  fixtures/relative-paths/index.test.js (10.431s)
 FAIL  fixtures/typescript-advanced/index.test.js (46.686s)
  ● builds in development

    expect(received).toBe(expected) // Object.is equality

    Expected: true
    Received: false

      3 | test('builds in development', async () => {
      4 |   const { fulfilled } = await testSetup.scripts.start({ smoke: true });
    > 5 |   expect(fulfilled).toBe(true);
        |                     ^
      6 | });
      7 | test('builds in production', async () => {
      8 |   const { fulfilled } = await testSetup.scripts.build();

      at Object.<anonymous> (fixtures/typescript-advanced/index.test.js:5:21)

 PASS  fixtures/node_path/index.test.js (42.694s)
 PASS  fixtures/boostrap-sass/index.test.js (10.628s)
 PASS  fixtures/issue-5176-flow-class-properties/index.test.js (8.218s)
 FAIL  fixtures/webpack-message-formatting/index.test.js (123.476s)
  ● helps when users tries to use sass

    expect(received).toMatchSnapshot()

    Snapshot name: `helps when users tries to use sass 1`

    - Snapshot
    + Received

    @@ -3,10 +3,22 @@
      Failed to compile.
      
      ./src/AppSass.scss
      To import Sass files, you first need to install node-sass.
      Run `npm install node-sass` or `yarn add node-sass` inside your workspace.
    + Require stack:
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/sass-loader/dist/getDefaultSassImplementation.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/sass-loader/dist/getSassImplementation.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/sass-loader/dist/index.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/sass-loader/dist/cjs.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/loader-runner/lib/loadLoader.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/loader-runner/lib/LoaderRunner.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/webpack/lib/NormalModule.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/webpack/lib/NormalModuleFactory.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/webpack/lib/Compiler.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/node_modules/webpack/lib/webpack.js
    + - /home/yokomotod/workspace/yokomotod/create-react-app/packages/react-scripts/scripts/build.js
      
      
      ",
        "stdout": "",
      }

       98 | 
       99 |   const { stdout, stderr } = await testSetup.scripts.build();
    > 100 |   expect({ stdout, stderr }).toMatchSnapshot();
          |                              ^
      101 | });
      102 | 
      103 | test('formats file not found error', async () => {

      at Object.<anonymous> (fixtures/webpack-message-formatting/index.test.js:100:30)

 › 1 snapshot failed.
 PASS  fixtures/typescript/index.test.js (5.853s)
 PASS  fixtures/builds-with-multiple-runtimes/index.test.js (36.341s)

Snapshot Summary
 › 1 snapshot failed from 1 test suite. Inspect your code changes or press `u` to update them.

Test Suites: 2 failed, 9 passed, 11 total
Tests:       2 failed, 28 passed, 30 total
Snapshots:   1 failed, 12 passed, 13 total
Time:        142.977s

コケる・・・

$ grep -r "Require stack" ../node_modules/
../node_modules/eslint/lib/shared/relative-module-resolver.js:                error.message += `\nRequire stack:\n- ${relativeToPath}`;

エラーメッセージがeslintから出てきてるっぽい・・・? 根が深そう

yarn e2e:docker

こっちもコケる・・・

2020/01/14 Node.jsにAWS X-Ray入れるのを諦めた


aws-cli、v2がプレビュー中なのか。キャッチアップ出来てなかったpreview厨の名折れ

brewにはまだ無い

rootには入れたくないのでホーム以下に入れる

Ubuntu、デフォルトで ~/.bin~/.local/bin にパスを通すことになってる

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
    PATH="$HOME/.local/bin:$PATH"
fi

~/.local 使って入れる

aws/install --install-dir ~/.local/aws-cli  --bin-dir ~/.local/bin/
$ aws2 --version
aws-cli/2.0.0dev3 Python/3.7.3 Linux/5.3.0-26-generic botocore/2.0.0dev2

AWS Instance-Connect、 インスタンス側はIAMの設定だけで、手元で mssh インストールすれば使い始められるのは手軽

でも mssh コマンドだとport forwardできない?


AWS X-Rayをローカルで動作確認

https://docs.aws.amazon.com/xray/latest/devguide/xray-daemon.html

aws sdk-for-go 製

プロファイルの指定は AWS_PROFILE 環境変数でできる


余裕で動かない

expressのミドルウェアで作られているはずのContextが消失していてエラーになる

NestJSのDIとかのせい?


v3.0alphaで cls を cls-hooked に変えたバージョンが出ている。8日前に

これなのか


VSCodeデバッグで標準出力も出す

https://komari.co.jp/blog/frontend/355/


DEBUG_CLS_HOOKED を有効にしてるとクラッシュする。

async_hooks.currentId is not a function · Issue #52 · Jeff-Lewis/cls-hooked · GitHub

nodejs.org

Node v9で currentIdがrenameされた


github.com

nestjsじゃなくてredisのせいだった

cls-redisというpatchがあるけど最新バージョンで動かない

github.com

PRが出てるけどマージされる気配がない

実際にどうするかはともかく、PR版を入れてためしたらredis問題は突破できた


が、TypeORMのあたりなのか、まだ死ぬ

さすがにもう厳しい(だいぶ前から気づいていた

NewRelicとかほかのツールをためそう

GCP IAM Explorerを公開した作業ログ

gcp-iam-explorer-263803.web.app


目標

  • IAM Roleの一覧取得
  • IAM Permissionの一覧取得
  • Role×Permissionのマトリクスをいい感じに見れる
  • RoleとRoleのdiffを取れる
  • GAは簡単にいれとく
  • OGPタグもちゃんとする

スコープ外

  • 複数Roleのdiffを取れる
  • APIエンドポイントに必要なPermission一覧取得
  • Permission×Endpointのマトリクスをいい感じに見れる

  • 自動化


github.com

github.com

があるの何?

  1. (APIじゃない)Cloud Client Libraryの方が高級らしい

cloud.google.com


パーミッションの一覧あった

cloud.google.com

2574個


CustomRoleサポートレベルという概念を見つけた

cloud.google.com

2545個

パーミッション網羅していない?


$ cat result.json | jq -r 'map(.includedPermissions) | flatten | .[]' | LANG=C sort -u | wc -l

2601

そしてドキュメントよりもRoleから抽出されたパーミッションの方が多い


342d341
< bigtable.tables.getIamPolicy
347d345
< bigtable.tables.setIamPolicy
933a932
> compute.instances.update
1008d1006
< compute.nodeGroups.update
1493d1490
< datacatalog.entries.list
1496d1492
< datacatalog.entries.updateTag
1502d1497
< datacatalog.entryGroups.update
1570,1577d1564
< dataproc.autoscalingPolicies.create
< dataproc.autoscalingPolicies.delete
< dataproc.autoscalingPolicies.get
< dataproc.autoscalingPolicies.getIamPolicy
< dataproc.autoscalingPolicies.list
< dataproc.autoscalingPolicies.setIamPolicy
< dataproc.autoscalingPolicies.update
< dataproc.autoscalingPolicies.use
2052,2053d2038
< logging.cmekSettings.get
< logging.cmekSettings.update
2185,2196d2169
< networkmanagement.connectivitytests.create
< networkmanagement.connectivitytests.delete
< networkmanagement.connectivitytests.get
< networkmanagement.connectivitytests.getIamPolicy
< networkmanagement.connectivitytests.list
< networkmanagement.connectivitytests.rerun
< networkmanagement.connectivitytests.setIamPolicy
< networkmanagement.connectivitytests.update
< networkmanagement.locations.get
< networkmanagement.locations.list
< networkmanagement.operations.get
< networkmanagement.operations.list

compute.instances.update がroleから抽出出来てないけど、どうやらそんなパーミッションは無い(なくなった?)


IAMのロゴ無いかな

あった

cloud.google.com

SVG and PNG Icons にバッチリ正方形背景透過が


material-uiでAppBarがかぶる問題の解決は theme.mixins.toolbar

github.com

stackoverflow.com


Routerまわり

reacttraining.com

reacttraining.com

いまのところreach-routerがreact-router v6の先取りっぽい

が、 TypeScriptのサポートが微妙

github.com

github.com


Reactのパフォーマンスチューニング調べる

medium.com


勉強会で聞いた React.memoの話

const Button = React.memo((props) => {
  // your component
});

ja.reactjs.org


useCallbackとuseMemoの違いってなんだ?

普通に返り値が違った。関数そのままか、関数の返り値か

Since JavaScript has first-class functions, useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

medium.com


Updateがかかってるかどうか知りたい

React Developer Tools の設定に Highlight Update あった

recruit-tech.co.jp


単なるオブジェクトリテラル定数にuseMemo使うのか?

JSX外で定義しろ。そりゃそうだ

gist.github.com


ESLintは

eslint-config-react の no-bind でアロー関数作って渡すのは検知できる

でもrecommendedでもeslint-config-react-appでも有効にはされてない

関数、オブジェクトリテラル、配列リテラル、全部チェックしてくれるやつ

github.com

(でもマイナー?)


丁寧にやってみたけど、そもそもmaterial-uiのAutocompleteがPure化されてないから結局常時Updateされとる


常にPure化すればいいわけじゃない

そのとおり。

とりあえず全部戻した


for-ofでarray.entries()使うとエラー

Type 'IterableIterator<[number, string]>' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.  TS2569

tsconfigのtargetは esnext とかで生成されたほうがいい気がする


長いTableをレンダリングしようとすると遅い

material-ui.com

raect-virtualized を使ったサンプルがドキュメントに

github.com

でも react-window の方がオススメ感ある

https://react-window.now.sh/#/examples/list/fixed-size

github.com

別に普通に react-window でもやれるっぽい

いったん諦めた。

Ctrl-F で検索できなくなるし


react-router スクロール問題

画面遷移後に前の位置のままなのは解決できる

reacttraining.com

でも出来ればブラウザバックしたときは前居たときの位置に戻りたい

developer.mozilla.org

ネイティブでサポートされはじめている?

ライブラリがある が、v4対応の方はPopularityがイマイチ

www.npmjs.com

const ScrollToTop: React.FC = () => {
  const history = useHistory()

  React.useEffect(() => {
    if (history.action === "PUSH") {
      window.scrollTo(0, 0);
    }
  }, [history.location.pathname, history.action]);

  return null;
}

でいいのでは?? 遷移したときだけリセット、ブラウザバック・フォワードだと維持


eslint-config-react-app.ts へのoverridesが、 自分で定義した plugins を上書きしている感

package.json : "extends": "plugin:prettier/recommended" packages/web/package.json : "extends": ["react-app", "prettier/@typescript-eslint"]

という状況で、rootで指定した plugin:prettier/recommended が認識されてないように見える

packages/batch/package.json : "extends": "eslint:recommended"

としてる方は問題ない

わかった

config-react-app で root: true が指定してあるからだ・・・

eslint-configパッケージの方で root: true 指定してくるのって一般的なのか・・・?

もしそうならmonorepoとかでネストしたeslistコンフィグ書くときはサブディレクトリでは root: false を明記すべきなのかとかって気になってくるけど


plugin:@typescript-eslint/recommended-requiring-type-checking

github.com

monorepoの場合、ルートで tsconfigRootDir 以外まで設定して、子パッケージの .eslintrc.jstsconfigRootDir: __dirname


@typescript-eslint/prefer-regexp-exec

ESLint本体でリジェクトされたルールがtypescript-eslintで採用されて、しかもrecommended入りしている・・・

github.com

github.com

typescript-eslint、JSレイヤのルールには関与せずTSでだけ架せれるルールだけ扱う、的なポリシーは特に無い感じなんだろうか


いまさらだけどcss propsって、なんでstyle属性をそのまま使うのよりいいんだ?

reactjs.org

but using the style attribute as the primary means of styling elements is generally not recommended.

非推奨だった

でもなんで?

reactjs.org

Are inline styles bad?

CSS classes are generally better for performance than inline styles.

パフォーマンスが悪い?

ループで何回も描画とかならわかるけど、一箇所でだけ描画されるような要素なら違いなさそう

コンポーネントの設計として、呼び出され方に制限はかけず、どこで何回使われるかわからない想定でいろということかな


GitHubのアイコン

これのためだけにFontAwesome入れるのは違うと思うのでSVGだけ取ってきたい

公式には.aiと.epsだけで、svgに変換してみたらなんか4種類の画像入りなファイルだった・・・

simpleicons.org

から取得


SVGに色をつけたい

そもそもちゃんと理解してなかったけど、 fill はインラインSVGにしか使えない模様

で、

import example from "./example.svg"

じゃなく

import { ReactComponent as Example } from "./example.svg"

でインライン展開されるReactComponentが取得できた・・・

こういうのをSVGRっていうのね

github.com


svgを囲むaタグの高さがsvgのサイズに一致しない

svg: 24 a: 16

aタグをdisplay: blockにしても

a: 29

svgもdisplay: blockにしたらOKだった

なるほど


GAの「業種」設定って目標のテンプレートに影響するだけだったのか


Firebase Analyticsをローカルで止める方法

とりあえずCreateReactAppのserviceWorkerで使ってるのとおなじ isLocal関数コピペして防いでおいた


support.google.com

測定機能の強化、はFirebase Analyticsだとどうやるんだ

データストリームの設定は「Firebase のストリーム設定」となっていて操作できない

github.com

github.com

ソース公開されてるのか

たぶん出来ない感

Webの場合、Firebase側のトラッキング方法は無視して連携されたGAを直接使ったほうがいいのでは・・・?

そうする


OGP対応

実行時のmetaタグの操作はreact-helmet

でも配信時には影響しないのでTwitterCardには効果がない

prerender.io

docs.netlify.com

それ用のサービスやNetlifyを使うという手

create-react-app.dev

Pre-Rendering into Static HTML Files

medium.com

CRAのページからのリンク

www.npmjs.com

weekly: 4,129 dependents: 9

www.npmjs.com

Heavily inspired by prep and react-snapshot, but written from scratch.

weekyly: 7,162 dependents: 17

react-snapshotに載ってるAlternatives

www.npmjs.com

weekly: 27,382 (gatsbyの影響だろう)

github.com

いいまとめ

www.npmjs.com

weekly: 7,433

www.npmtrends.com


react-snap で行ってみる

なにもトラブルなく動いたすごい


metaタグがreact-helmetで変更されない

<meta property="og:title" content="Compare : GCP IAM Explorer">

のまま

<meta property="og:title" content="Compare : GCP IAM Explorer" data-react-helmet="true"> がheadの末尾に追加されてた

data-react-helmet="true" がついてないものには触らない模様

prerenderingするのでindex.htmlから消してしまえば良い

data-react-helmet="true" をつければindex.htmlに書いたやつを拾ってくれはしそう


firebase hostingで末尾スラッシュ無しに統一したい

firebase.google.com

"trailingSlash": false


firebase hostingで404を返す

react-snapでprerenderingしているので初期化時にSPA用としてセットアップして作られたrewriteルールを消せばOK


公開