- 導入
- ブラウザ環境とNode.js環境におけるモジュールシステムの違い
- なぜ、npmパッケージはブラウザから読み込めないのか
- webpackでnpmパッケージをブラウザ環境で使う
- webpack.config.jsの設定
- webpackで開発用サーバー立ち上げ
- フロントのビルドツール界隈の現状把握
- 次世代ビルドツール Vite
- Viteの特徴
- Vite プロジェクトの作成とビルド
- まとめ
導入
- ブラウザとNode.jsでのモジュールの取り扱いの違いについて学ぶ。
- 現在のフロントエンド開発はビルドツールが乱立しているため、それらについて学ぶ。
- 各ツールの役割と特徴を捉えることで今後の指針とする
ブラウザ環境とNode.js環境におけるモジュールシステムの違い
// Common JSの書き方なので、ブラウザでは実行できない const myModule = require("./sub") // ES Modulesの書き方 import { helloFromSub } from "./sub.js" helloFromSub()
function helloFromSub() { console.log("hello, sub") } // Common JSの書き方なので、ブラウザでは実行できない exports.helloFromSub = helloFromSub // or module.exports = { helloFromSub, } // ES Modulesの書き方 export { helloFromSub }
なぜ、npmパッケージはブラウザから読み込めないのか
Node.jsはもともと、Common JSのシステムで動いていたので、Common JSで書かれたパッケージも多い。
インストールしたパッケージはアップデートされるのが一般的。なので、ファイル内を書き換えて使うことはNG行為。
ES Modulesでrequireを使う方法
import { helloFromSub } from "./sub.js" // ブラウザーでの読み込み import isOdd from "./node_modules/is-odd/index.js" // or import { createRequire } from "module" const require = createRequire(import.meta.url) const isOdd = require("is-odd") helloFromSub() const oddy = isOdd(3) console.log(oddy)
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <h1>Hello</h1> <script type="module" src="./dist/main.js"></script> </body> </html>
webpackでnpmパッケージをブラウザ環境で使う
# インストール npm i -D webpack-cli # 実行 npx webpack --entry "./main.js" # 初期化 npm init -y
モジュールバンドラーを使えば、export
やimport
、Common JSの規格に沿ったrequire
やmodule.exports
などが排除された状態のコードが生成される。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <h1>Hello</h1> <!-- <script type="module" src="./dist/main.js"></script> --> <!-- ES Modules形式のexportもimportもないので、`type="module"も必要ない` --> <script src="./dist/main.js"></script> </body> </html>
webpack.config.jsの設定
webpackはCommon JSで実行されるので、package.json
でtype: modules
を設定しているとエラーが発生する。なので、削除する。
const path = require("path") // ES Modulesで書きたい場合 import * as url from "url" // import.meta.url -> 現在のファイルがURL形式で取得できる // url.fileURLToPath -> URL形式をパス形式に変換する const __dirname = url.fileURLToPath(new URL(".", import.meta.url)) console.log(__dirname) module.exports = { mode: "development", // production entry: "./main.js", output: { path: path.resolve(__dirname, "public"), // dist filename: "bundle.js", }, }
webpackで開発用サーバー立ち上げ
npm i -D webpack-dev-server
const path = require("path") console.log(__dirname) module.exports = { mode: "development", // production entry: "./main.js", output: { path: path.resolve(__dirname, "dist"), // dist filename: "bundle.js", }, devServer: { port: 9000, // ブラウザで開くか open: true, // サーバーの対象フォルダ static: { directory: path.resolve(__dirname, "dist"), }, }, }
{ "name": "end", "version": "1.0.0", "main": "main.js", "scripts": { "build": "webpack", "start": "webpack serve" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "is-odd": "^3.0.1" }, "devDependencies": { "webpack": "^5.89.0", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.15.1" }, "description": "" }
フロントのビルドツール界隈の現状把握
様々なビルドツール
フロントエンド開発で用いるツール群
- タスクランナー
- Linter/Formatter
- モジュールバンドラー
- Native ESMビルダー
- トランスパイラー
タスクランナー
リリースに必要なコマンドを実行するツール
- 学習コスト低
- 簡易なビルドに使用
- SassからCSSへの変換
- ファイルの圧縮・フォルダのコピー
- ⭕️Web制作 ✖️複雑な開発
ツール
- Gulp
Linter / Formatter
プログラムがルールに沿って記述されているかどうかを確認&整形するツール
- Linter: 記述ルールチェックツール
- ESLint / TSLint / stylelint
- Formatter: コード整形ツール
- Prettier
Minifier
CSS、JSのコードを圧縮するツール
- JSの圧縮
- Terser
- CSSの圧縮
- CSSNANO
トランスパイラー(JS/TS)
ソースコードをJavaScriptの特定のバージョンのコードに変換する機能
- ES2020 → ES2019
- JSX → JavaScript
- TypeScript → JavaScript
ツール
- SWC
- Babel
- tsc
トランスパイラー(Sass/CSS)
ツール
- Sass
- postcss
バンドラー
モジュールファイルを一つのファイルに統合(バンドル)するためのツール
- webpack
- Parcel
- rollup
- esbuild
なぜバンドルする必要があるのか?
JSに求められる機能の増加。(SPAなど)
↓
AMD、CJS、ESMなどのモジュール管理の仕組みが登場。
↓
ブラウザではモジュールシステム(ESM)がなかったため、バンドルが必要になった。
HTTP/1ではリクエスト数がサイトのパフォーマンスによって大きく影響したため。(HTTP/2では改善)
次世代ビルドツール Vite
開発サーバーとHMR
- 開発サーバー:PC上に立てる開発用のサーバー
- HMR:画面のリロード無しに変更点を画面に反映する機能
Native ESMを使った開発環境
開発時はバンドルせず、NativeのESM機能で動作
Viteの特徴
- 試験用:Native ESMを使用
- ブラウザが読み込めるように依存関係の記述を変換(esbuild)で実行
- 本番用:バンドルされたファイルを使用
- Rollupでモジュールをバンドル
※何千ものモジュールをインターネット越しに読み込むのは時間がかかるため
※esbuildよりも動作が安定している
- Rollupでモジュールをバンドル
Vite プロジェクトの作成とビルド
npm init
とnpm create
は同じ意味。
npm init vite
でViteを使用しプロジェクトを作成できる
{ "name": "040_vite_sample", "private": true, "version": "0.0.0", "type": "module", "scripts": { // 開発用サーバーの立ち上げ、依存関係の解決 "dev": "vite", // rollupによってバンドルファイルを生成 "build": "vite build", // 生成ファイルを確認するためのサーバーの立ち上げ "preview": "vite preview" }, "devDependencies": { "vite": "^5.0.0" } }
HMR (Hot Module Replacement) → コードの修正がリアルタイムで反映される
Viteの基本はSPAを作成するものだが、 PHPやRailsと連携して開発したい場合、下記に設定方法が記載されている。