- 投稿日:
TSでprocess.exit()
をラップしたカスタムexitを作った時に静的解析のフローが壊れたので、その対策。
因みにこの制御フローのことをControl Flow Analysisと呼ぶらしい。TS系の文書ではCFAと略されていることが多い模様。
問題事例
通常のprocess.exit()
例の7-8行目のように次の行から先がデッドコードになって欲しいが、上手くいかないので、これを上手くいくようにする。
カスタムexitのコード例 | 通常のprocess.exit()例 |
---|---|
確認環境
Env | Ver |
---|---|
TypeScript | 4.8.4 |
サンプルコード
オブジェクトでラップして、カスタムexit関数の戻り値をnever
で指定してやると上手くいくようになる。
因みにこれTypeScriptの仕様らしく、上手くやる方法はあんまりなさそう。
実はアロー関数ではなくfunction
を使えば解決したりするが、それはなんか嫌なので…
example.ts
type ErrorPayload = {
message: string;
code: number;
};
type ExampleExit = {
exit: (err: ErrorPayload) => never;
};
const exit = (err: ErrorPayload) => {
process.exit(err.code);
};
export const Example: ExampleExit = { exit };
implements.ts
import { Example } from './example';
Example.exit({ message: 'exit', code: 1 });
console.log(1);
関連記事
- TypeScriptで戻り値型がneverな関数を作る
- オブジェクトに包まれていない、裸の関数に対して同様のことを行うアプローチを書いている
- 投稿日:
レスポンシブにdisplay
を切り替えるCSSを書いててハマったので備忘録。
今回は例として画面幅に応じて表示する項目数を変動させるCSSを書いてみます。media queryとnth-childを使って表示数を切り替えていく感じです。
イメージとしてはこんな感じ。
SP View | PC View |
---|---|
上手くいかないケース
このコードでは画面幅を変えても項目数に変化がありません。理由としてはnth-child(n + 4)
のdisplay: none;
が900pxでも保持されたままだからです。試しにdisplay: none;
をfont-weight: bold;
とかに変えてみると良くわかります。
.example li:nth-child(n + 4) {
display: none;
}
@media screen and (min-width: 900px) {
.example li:nth-child(n + 6) {
display: none;
}
}
上手くいくケース
以下のコードではnth-child
で非表示にしている部分を900pxの時に表示指定にすることで3項目表示と5項目表示が切り替わるようになっています。そりゃ指定してなければ表示されないよねっていう単純な話ですね…。
.example li:nth-child(n + 4) {
display: none;
}
@media screen and (min-width: 900px) {
/** 明示的に表示させる */
.example li:nth-child(n + 4) {
display: list-item;
}
.example li:nth-child(n + 6) {
display: none;
}
}
- 投稿日:
条件分岐でコンポーネントの出し分けをしている時に正しくコンポーネントが出ているかどうかに使えるやつ
UIロジックのリグレッションテストで使える
分岐結果の出力を見てるだけなのでテストとして壊れづらく、運用しやすいと考えている
確認環境
Next.jsで確認してるけど素のReactでも同じだと思う
Env | Ver |
---|---|
@swc/core | 1.2.133 |
@swc/jest | 0.2.17 |
jest | 27.4.7 |
next | 12.0.8 |
react | 17.0.2 |
react-dom | 17.0.2 |
react-test-renderer | 17.0.2 |
typescript | 4.5.4 |
テスト対象
テストのためにコンポーネントを細かくexport
すると名前空間が汚染されるのが悩み…
type BaseProps = {
id: string;
};
type SwitchExampleProps = BaseProps & {
display: 'Foo' | 'Bar';
};
export const Foo = (props: BaseProps) => {
return (
<div id={props.id}>
<p>Foo</p>
</div>
);
};
export const Bar = (props: BaseProps) => {
return (
<div id={props.id}>
<p>Bar</p>
</div>
);
};
export const SwitchExample = (props: SwitchExampleProps) => {
if (props.display === 'Foo') {
return <Foo id={props.id} />;
} else {
return <Bar id={props.id} />;
}
};
テストコード
react-testing-libraryの.toHaveAttribute()
や.toHaveDisplayValue()
を書き連ねるより圧倒的に楽で保守性も良いと思う
import TestRenderer from 'react-test-renderer';
import { Bar, Foo, SwitchExample } from './SwitchExample';
type TestCase = {
name: string;
param: Parameters<typeof SwitchExample>[0];
actual: JSX.Element;
};
describe('SwitchExample', () => {
const testCaseItems: TestCase[] = [
{
name: 'Foo',
param: {
id: 'hoge',
display: 'Foo',
},
actual: <Foo id={'hoge'} />,
},
{
name: 'Bar',
param: {
id: 'piyo',
display: 'Bar',
},
actual: <Bar id={'piyo'} />,
},
];
testCaseItems.forEach((item) => {
// eslint-disable-next-line jest/valid-title
it(`switched condition ${item.name}`, () => {
const result = TestRenderer.create(
<SwitchExample id={item.param.id} display={item.param.display} />
);
const actual = TestRenderer.create(<>{item.actual}</>);
expect(result.toJSON()).toStrictEqual(actual.toJSON());
});
});
});
参考記事
- 投稿日:
Markdownを使って快適にブログを書きたくない?書きたいですよね?そう、書きたい!
ではどうすればいいか?というのをこれから書いていきます。
JAMStackを使ってGitHub PagesとNext.js SSGでMarkdownブログを作ろう!みたいな人はブラウザバックをオススメします。
技術選定
- JAMStack
- はてなブログ
- WordPress
JAMStack
まずJAMStackは真っ先に除外します。ブログを書きたいのであってブログを作りたいわけではないからです。
またSSGだとクライアントサイドのレンダリングコストが重く、リッチなブログにしようとすると負荷がしんどい気がしています。恐らくSEO対策的にもCSRを妥協して極限までSSGしていないと厳しいのではないでしょうか?
はてなブログ
カスタマイズがすんごくだるい上に、真面目にやろうとするとクライアントサイドでHTMLをゴリゴリ書き換えたり、order
などのハックに近いCSSを多用して擬似的に要素を移動させたりする必要があり、レイアウトを組むのが非常に面倒です。
エディタもしょぼいしカテゴリはないし(はてブロのカテゴリは実質的にタグなので)年会費が高い割に出来ることの制限が強い…。あんまSEOも強くなかったし、試しに使ってみたものの流入が激減…正直個人的にこれはですね。
WordPress
多分こいつが一番現実的な選択肢です。WP Githuber MDを使うことで不自由なくMarkdownを扱うことが出来ると思います。但し内蔵のPrism.jsはなんかいい感じに動いてくれないケースがあり、その場合はカスタマイズが必要です。
カスタマイズについてもプラグインやテーマが豊富にあり、改造も容易なのでローコストでリッチなものが実現しやすいと思います。またセルフホストなのでデータの取り回しの自由が効きやすいのも大きなポイントですね。
CMSは色々使ってきましたが、なんだかんだブログはWordPressが一番だなって思います。SEO対策もGoogle謹製のやつがあるし、特に何もしなくてもある程度なんとかなるのは強みだと思います。
カスタマイズ法
CSS
使っているテーマと整合性が取れるようにいい感じにします。私は Dracula for Prism.js を改造して使いました。
JS
私の場合は次のコードをヘッダタグの中に足して対処しました。特に内容の説明はしませんが、行番号とコピーボタンが出るようにしています。
<script src="https://unpkg.com/prismjs@1.28.0/components/prism-core.min.js"></script>
<script src="https://unpkg.com/prismjs@1.28.0/plugins/autoloader/prism-autoloader.min.js"></script>
<script src="https://unpkg.com/prismjs@1.28.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
<script src="https://unpkg.com/prismjs@1.28.0/plugins/toolbar/prism-toolbar.min.js"></script>
<script src="https://unpkg.com/prismjs@1.28.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('pre > code').forEach((codeEl) => {
codeEl.className = codeEl.className === '' ? 'language-none' : codeEl.className;
codeEl.className = codeEl.className.replace(/^sh$/, 'shell');
codeEl.parentNode.className = 'line-numbers';
});
window.Prism.highlightAll();
});
</script>
- 投稿日:
VSCodeでは出来たことがPhpStormだと上手く出来なかったので、その解消法です
Remote Developmentに慣れてるとハマりやすいと思います
PhpStormに類似の機能は多分ないです
PhpStorm編
確認環境
一応Apacheの上に乗っかったLaravelで確認してますがそこらへんの環境情報は端折ってます
Env | Ver |
---|---|
Windows | 11 Pro |
PhpStorm | 2021.3.2 |
Docker | 20.10.11 |
docker-compose | 1.29.2 |
PHP | 8.1.1 |
Xdebug | 3.1.3 |
Dockerfile
PHPが入ってるDockerfileに以下を追記
出来ることならヒアドキュメントで書きたい
RUN pecl install xdebug
RUN docker-php-ext-enable xdebug
RUN echo "zend_extension=xdebug" > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.mode=develop,coverage,debug,trace" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.start_with_request=trigger" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.trigger_value=StartProfileForMe" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
Dockerの設定
適当にDockerを追加してコンテナとローカルのパスをマッピング
PHPインタプリタの設定
CLIインタプリタをDockerに向けて設定します
パスマッピングは勝手にやってくれた気がする
デバッグ
HTTPリクエスト
受話器みたいなところを押してcurlなりPOSTMANなりブラウザなりにXDEBUG_TRIGGER=StartProfileForMe
というCookieを刺してリクエストするとブレークにかかります
初回だけパスマッピングを構成するダイアログが出てくるのでよしなに処理します
PHPUnit
デバッグ構成を作ってデバッグするだけ
おまけのVSCode編
VSCodeだとネイティブに動くのでDockerの存在を考えなくて済むのは楽ですが、IDEとしての性能はPHP Intelephenseに課金してもPhpStormには劣るので微妙なところ(静的解析に問題がある
確認環境
PhpStormと被る部分は端折ってます
Env | Ver |
---|---|
VSCode | 1.64.2 |
ms-vscode-remote.remote-containers | 0.217.4 |
robberphex.php-debug | 1.14.0 |
Dockerfile
PHPが入ってるDockerfileに以下を追記
PhpStormとの違いはxdebug.client_host
が不要なところです
(PhpStormでもCLI Debugだとなくていけるっぽいのでややこしい)
RUN pecl install xdebug
RUN docker-php-ext-enable xdebug
RUN echo "zend_extension=xdebug" > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.mode=develop,coverage,debug,trace" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.start_with_request=trigger" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.trigger_value=StartProfileForMe" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
launch.json
- Listen for Xdebug
- HTTPリクエスト用
- PHPUnit
- PHPUnit用
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003
},
{
"name": "PHPUnit",
"type": "php",
"request": "launch",
"program": "${workspaceFolder}/vendor/phpunit/phpunit/phpunit",
"args": ["${file}"],
"env": {
"XDEBUG_TRIGGER": "StartProfileForMe"
},
"port": 9003
}
]
}
デバッグ
PHPのいるコンテナにAttach Visual Studio CodeしてF5押せばデバッグできます
あとがき
個人的に操作感はVSCodeの方が好みなので使えるならVSCodeでいきたいのですが、今の所PhpStormには敵わないという感じなのが悲しい
まぁJS/TS用のエディタみたいなもんだし仕方がないですね…
ただGitのGUI周りはVSCodeが圧倒的に好みなので、Git操作するときだけVSCode使ってたりはします
しかしPhpStormとVSCodeを共存させるのはxdebug.client_host
の向きの関係で微妙な感じですね…