未完 Project Webpack 勉強会
JS のフレームワークを使っていて、ビルド周りを雰囲気でやっていることに気づく
vue-cli
とか
create-react-app
に頼りきってた
そろそろ Webpack を理解りたい
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>依存関係未解決パターン</title>
</head>
<body>
<script src="js/libs/lib.js"></script>
<script src="js/libs/axios.js"></script>
<script src="js/app.js"></script>
</body>
</html>
app.js の実行には lib.js,axios.js というライブラリが必要なため、この順に読み込まれる必要がある
一方でモジュールバンドラを使うと、依存関係を解決したファイルを出力してくれるため
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>依存関係解決パターン</title>
</head>
<body>
<script src="js/bundle.js"></script>
</body>
</html>
これだけでアプリケーションが動作する!
ウェブブラウザとサーバーはHTTP/1.1という通信プロトコルで通信をしている
HTTP1.1 環境 ではブラウザ/サーバー間の同時接続数が制限される(一度に処理できるリクエストの数に制限がある)ことから、複数ファイルのダウンロードは非効率的
そもそものリクエスト数を減らすことで転送効率が向上する
モジュールバンドラーを前提とすることで、コードはクラス・関数単位でファイルを分割できる。これによって下記のようなメリットがある
Loader はリソースをモジュールに変換する
css-loader,style-loader,ts-loader など
create react app を使わず React+TypeScript 環境を最小構成{style=color:#FF8C00;} で構築する
.
├── index.html
├── package.json
├── src
│ ├── Hello.tsx
│ └── index.tsx
├── tsconfig.json
├── webpack.config.development.js
└── webpack.config.production.js
node
v14.17.6
webpack
v5.71.0
webpack-cli
v4.9.2
$ mkdir minimum-react-ts-sample
// webpack v5と必要なもの一式をインストール
$ npm install webpack webpack-cli --save-dev
// TypeScriptをインストール
$ npm install typescript --save-dev
// ts-loaderをインストール
$ npm install ts-loader --save-dev
// Reactをインストール
$ npm install react react-dom
// Reactの型定義をインストール
$ npm install --save @types/react @types/react-dom
+ webpack-cli@4.9.2
+ webpack@5.71.0
+ typescript@4.6.3
+ ts-loader@9.2.8
+ react@18.0.0
+ react-dom@18.0.0
+ @types/react@17.0.43
+ @types/react-dom@17.0.14
$ ls
node_modules package-lock.json
webpack.js を作成する
touch webpack.config.development.js
touch webpack.config.production.js
module.exports = {};
この中のプロパティに値を設定していく
$ ./node_modules/.bin/tsc --init
Created a new tsconfig.json with:
target: es2016
module: commonjs
strict: true
esModuleInterop: true
skipLibCheck: true
forceConsistentCasingInFileNames: true
You can learn more at https://aka.ms/tsconfig.json
// tsconfig.json
{
"compilerOptions": {
"jsx": "react",
}
}
// webpack.config.development.json
module.exports = {
// エントリーポイント(バンドルの構築を開始する場所)を指定する。Webpackはこのファイルを基準に依存関係を解決していく。
entry: "./src/index.tsx",
// Webpackが作成したバンドルをどこに、どのような名前で出力するかを指定する
output: {
filename: "./dist/bundle.js",
},
// source-mapはdevelopmentmodeの場合のみ有効
devtool: "source-map",
resolve: {
extensions: [".ts", ".tsx", ".js"],
},
module: {
rules: [
{
// ローダーを使用することでデフォルトでは対応していないファイルをバンドル対象に加えることができる。testプロパティに変換したいファイルを指定する。
test: /\.tsx?$/,
loader: "ts-loader",
options: {
transpileOnly: true, // 型チェックを行わない。デフォルトはfalse
},
},
],
},
};
パラメーターにdevelopment
,produciton
,none
を与えることで、Webpack の設定を環境に応じて最適化できる
module.exports = {
// デフォルト値はproduction
mode: 'production'
};
{
"name": "minimum-react-typescript-sample",
"version": "1.0.0",
"scripts": {
"build": "webpack --config ./webpack.config.development.js",
"build-production": "webpack --config ./webpack.config.production.js",
"type-check": "npx tsc -p . --noEmit" // typescript compilerを呼び出して型検査をするscriptを定義する。--noEmitオプションを付与すると、ファイルのoutputを行わずに型検査のみを実行する
},
"devDependencies": {
"@types/react": "^17.0.43",
"@types/react-dom": "^17.0.14",
"ts-loader": "9.2.8",
"typescript": "4.6.3",
"webpack": "5.71.0",
"webpack-cli": "^4.9.2"
},
"dependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
import * as React from "react";
export interface Props {
content: number; // number型にした
}
export default class MyComponent extends React.Component<Props, {}> {
render() {
return <div>{this.props.content}</div>;
}
}
$ npm run type-check
src/index.tsx:6:10 - error TS2769: No overload matches this call.
Overload 1 of 2, '(props: Props | Readonly<Props>): MyComponent', gave the following error.
Type 'string' is not assignable to type 'number'.
Overload 2 of 2, '(props: Props, context: any): MyComponent', gave the following error.
Type 'string' is not assignable to type 'number'.
6 <Hello content="hello world" />,
~~~~~~~
src/Hello.tsx:4:3
4 content: number;
~~~~~~~
The expected type comes from property 'content' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComponent> & Readonly<Props> & Readonly<{ children?: ReactNode; }>'
src/Hello.tsx:4:3
4 content: number;
~~~~~~~
The expected type comes from property 'content' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComponent> & Readonly<Props> & Readonly<{ children?: ReactNode; }>'
Found 1 error in src/index.tsx:6
$ npm run build
> minimum-react-typescript-sample@1.0.0 build /home/denham/workspace/minimum-react-ts-sample
> webpack --config ./webpack.config.development.js
asset ./dist/bundle.js 138 KiB [emitted] [minimized] (name: main) 2 related assets
modules by path ./node_modules/ 141 KiB
modules by path ./node_modules/react/ 6.96 KiB
./node_modules/react/index.js 190 bytes [built] [code generated]
./node_modules/react/cjs/react.production.min.js 6.77 KiB [built] [code generated]
modules by path ./node_modules/react-dom/ 130 KiB
./node_modules/react-dom/index.js 1.33 KiB [built] [code generated]
./node_modules/react-dom/cjs/react-dom.production.min.js 128 KiB [built] [code generated]
modules by path ./node_modules/scheduler/ 4.33 KiB
./node_modules/scheduler/index.js 198 bytes [built] [code generated]
./node_modules/scheduler/cjs/scheduler.production.min.js 4.14 KiB [built] [code generated]
modules by path ./src/*.tsx 2.76 KiB
./src/index.tsx 1.47 KiB [built] [code generated]
./src/Hello.tsx 1.29 KiB [built] [code generated]
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
webpack 5.71.0 compiled with 1 warning in 6620 ms
🎉🎉🎉
ご清聴ありがとうございました!