Key-Valueで定数として定義しているオブジェクトの値をUnion型として使いたい
事前に定義されているオブジェクトから値の部分をUnion型として、関数のパラメータの型に使いたい。
const ItemName = { First: "No1", Second: "No2", Third: "No3" } as const; type ItemNameType = keyof typeof ItemName; // "First" | "Second" | "Third" type ItemValueType = typeof ItemName[ItemNameType]; // "No1" | "No2" | "No3" : : const func = (param: ItemValueType):void => { ...
webpackの覚書
なんとなく使ってしまっているwebpackeについて、よく使うところの覚書。
webPackとは
webpackでできること
* コンテンツを構成するファイルを1つにまとめる。
* 複数のファイルを1つにまとめることで、ブラウザでコンテンツを表示するときのファイル転送が1度で済む。
モジュール方式とは
モジュール
* 機能ごとに分割されたJavaScriptファイルのこと
* モジュール読み込み仕様として主要なものはCommonJS ModulesとECMAScript Modules
CommonJS Modules (CJS)
* モジュールでは module.exports で関数を定義し、読み込み側では require で読み込む。
// モジュール定義側 sub.js module.exports = function() { console.log('cjs module'); }
// モジュール読み込み側 const subModule = require('./sub.js'); subModule();
ECMAScript Modules (ESM)
* ES6で定義された仕様で、モジュール側ではexportで関数を定義し、読み込み側ではimportで読み込む。
// モジュール定義側 sub.js export const moduleFunc = function() { console.log('esm module'); }
// モジュール読み込み側 import { moduleFunc } from './sub' moduleFunc();
webpackのインストール
以下のコマンドを実行する。
npm install -D webpack webpack-cli
webpack4以降では設定ファイルがなくてもデフォルト動作で実行できる。
npx webpack
これにより、
コマンドのカスタマイズ
npm scriptsを使ってpackage.jsonにコマンドのショートカットを記述することで、webpackのビルドコマンドを追加できる。
初期状態のpackage.json
npm init -y コマンド実行直後に作成されるpackage.jsonはこのようになっている。
{ "name": "myproject", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^5.75.0", "webpack-cli": "^5.0.1" } }
ここから最低限必要な部分だけ残すとこうなる。
"scripts": {}, "devDependencies": { "webpack": "^5.75.0", "webpack-cli": "^5.0.1" }
ビルドコマンドの追加
script部分にbuildコマンドを追加するとこうなる。
"scripts": { "build": "webpack" }, "devDependencies": { "webpack": "^5.75.0", "webpack-cli": "^5.0.1" }
buildコマンドを実行する場合は
npm run build
webpackの動作のカスタマイズ
設定ファイル
package.jsonと同じ階層にwebpack.config.jsファイルを作成し、このファイルにwebpackの動作を指定することができる。
エントリポイントの指定
webpack.config.jsでentryを指定する。
module.exports = { // entryを指定しなければ src/index.js がエントリーポイントになる // ドットから始まる相対パスか、${__dirname}を使用した絶対パスで指定 entry: './src/index.js' }
出力先の指定
webpack.config.jsでoutputを指定する。
module.exports = { // outputを指定しなければ dist/main.js が出力ファイルになる output: { // 出力先フォルダは絶対パスで指定(存在しないフォルダの場合は自動的に作成される) path: `${__dirname}/dist`, // ファイル名 filename: 'main.js', },
メモ:パスの指定について
webpack.config.js中にパスを指定する場合、path.joinを使ったほうが良さそう。
パスの区切り文字を適切に扱ってくれるため。
ただし、"./" から始まるパスの場合は文字列として指定する必要がある。
const path = require('path') module.exports = { entry: `./src/index.js`, output: { path: path.join(__dirname, 'dist'), filename: 'main.js', }, }
ソースマップ(変換されたコードと元コードのマッピング)
webpack.config.jsでmodeをdevelopmentとして指定する。
module.exports = { // development にするとソースマップが有効になる mode: "development" };
環境別のwebpack動作設定
環境別のwebpack.config.jsの作成
開発用と本番用で別のファイルを作成しておく。
* webpack.dev.config.js
* webpack.prod.config.js
ビルドコマンドを環境別に分ける
package.jsonのscriptsに環境別のコマンドを用意し、webpackコマンドのオプションで環境別の設定ファイルを指定する。
"scripts": { "build-dev": "webpack --config webpack.dev.config.js" "build-prod": "webpack --config webpack.prod.config.js" },
scrollHeightの変更を検出したい
あるdiv要素の中身が動的に変更されるとき、そのdiv要素のscrollHeightの値を取得したい。
ResizeObserverを使う場合
divのサイズ変更のタイミングで通知してほしい場合はResizeObserverで良さそう。
import React, { useEffect, useState, useRef } from "react"; import styled from "styled-components"; const Wrapper = styled.div` width: 200px; height: 200px; overflow: auto; `; export default function App() { const ref = useRef<HTMLDivElement>(null); const [list, setList] = useState<string[]>([]); /* イベント処理 - ここから */ const callback = (e: ResizeObserverEntry[]) => { console.log("Resize", ref.current?.scrollHeight); } useEffect(() => { console.log("MOUNT"); if (!ref.current) return; const observer = new ResizeObserver(callback); observer.observe(ref.current); return () => { observer.disconnect(); } }, [ref]); /* イベント処理 - ここまで */ const onClickAdd = () => { setList((list) => [...list, `${list.length}`]); }; const onClickDelete = () => { setList(list => list.slice(1)); }; return ( <div > <button onClick={onClickAdd}>add</button> <button onClick={onClickDelete}>delete</button> <Wrapper> <div ref={ref}> {/* このdiv要素のheightを監視 */} {list.map((item, index) => { return <p key={index}>{item}</p>; })} </div> </Wrapper> </div> ); }
MutationObserverを使う場合
監視対象の子要素が変化したタイミングでscrollHeightを確認したい場合は、MutationObserverも使えそう。
/* イベント処理部分を置き換え */ const callback = (e: MutationRecord[]) => { console.log("Resize", ref.current?.scrollHeight); } useEffect(() => { console.log("MOUNT"); if (!ref.current) return; const observer = new MutationObserver(callback); observer.observe(ref.current, {attributes:true, childList:true}); return () => { observer.disconnect(); } }, [ref]);