何をするか
Vite は TypeScript ビルドや、開発用サーバー、バンドリングなどの機能を備えた統合的なフロントエンド開発ツールです。 ここでは、Vite で複数の TypeScript ファイルを 1 つの JavaScript ファイルの形にビルドする方法を説明します(この作業をバンドルと呼びます)。
最終的な成果物として、複数の Web サイトから <script>
要素で読み込み可能な JavaScript ライブラリ を作成することを想定しています。
画像ファイルやスタイルシート (CSS) などのリソースファイルも、単一の JavaScript に埋め込む形でバンドルできます。
Vite プロジェクトの作成
npm create vite
コマンドを使って Vite のプロジェクトを作成します。
React などのフレームワークを使わず、純粋な TypeScript ファイルをビルドするだけであれば、ウィザードに従って、Vinilla
→ TypeScript
と選択していきます。
$ npm create vite@latest myscript
✔ Select a framework: › Vanilla
✔ Select a variant: › TypeScript
$ cd myscript
次のようなファイルが生成されます。
myscript/
+-- .gitignore
+-- index.html # <script> 要素による表示の確認用
+-- package.json
+-- tsconfig.json
+-- public # 最終的には必要なし
| +-- vite.svg
+-- src/ # 最終的には全部書き換える
+-- counter.ts
+-- main.ts
+-- style.css
+-- typescript.svg
+-- vite-env.d.ts
src
ディレクトリにはサンプル実装の TypeScript コードや画像ファイルが入っているので、この中身は最終的には全部書き換えることになります。
その他の package.json
や tsconfig.json
などは大部分は使いまわせるはずです。
プロジェクトが生成されたら、依存パッケージ (tsc, vite) をインストールしておきます。
$ npm install
bundle.js 出力用のプロジェクトに書き換える
他の Web サイトから 1 つの <script>
要素で利用可能なライブラリにするには、複数の TypeScript ファイルを単一の JavaScript ファイルの形にバンドルする必要があります。
テンプレートとして生成されたプロジェクトを npm run build (tsc & vite build)
でそのままビルドすると、Web サイト用の index.html
や各種アセットファイル (.css
, .js
) などが出力されてしまいます。
そこで、下記の設定手順に従い、1 つの JavaScript ファイルとして出力するようカスタマイズする必要があります。
CSS ファイルを .js ファイルに埋め込む
テンプレートプロジェクトの main.ts
ファイルでは、import "./style.css"
のように外部の CSS ファイルを読み込んでいます。
デフォルトでは CSS ファイルは独立したアセットファイルとして出力されてしまうので、1 つの JavaScript ファイルに埋め込むように設定する必要があります。
もちろん、CSS ファイルを使わないプロジェクトではこの設定は必要ありません。
CSS を JavaScript に埋め込むための vite-plugin-css-injected-by-js
という Vite プラグインが公開されているのでこれをインストールします。
$ npm install vite-plugin-css-injected-by-js --save-dev
vite.config.ts の作成
vite.config.ts
(.js
でも可)を作成して、単一の dist/bundle.js
ファイルとして出力するように設定します(この設定を Library Mode と呼びます)。
上記でインストールした Vite プラグインはここで読み込みます。
出力ファイル名は dist/bundle.js
としています。
import { defineConfig } from "vite";
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
export default defineConfig({
plugins: [cssInjectedByJsPlugin()], // CSS を JS に埋め込むプラグイン
build: {
lib: {
entry: "src/main.ts",
formats: ["iife"], // Web サイト組み込み用に即時実行形式 (function(){})() で出力
name: "MyScript", // static API 用のグローバルオブジェクト名
},
rollupOptions: {
output: {
dir: "dist", // 出力ディレクトリ (default: dist)
entryFileNames: "bundle.js", // 出力ファイル名
},
},
},
});
ビルド
リリース用の JavaScript ファイルを生成するには、npm run build
(=tsc & vite build
) コマンドでビルドします。
次のように dist/bundle.js
だけが生成されれば成功です。
$ npm run build
...
✓ 5 modules transformed.
dist/bundle.js 3.81 kB │ gzip: 2.02 kB
bundle.js
ファイルの内容を見ると、svg
ファイルや css
ファイルの内容がインラインで埋め込まれていることを確認できます。
開発用サーバー
Vite の開発サーバーを起動すると、src/main.ts
ファイルの修正を監視してリアルタイムに表示内容を確認できます。
開発中はこの機能を使うと便利です。
$ npm run dev -- --open
次のように index.html
の内容が表示されれば成功です。
ちなみに今回の用途では、index.html
ファイルは完全に開発時の表示確認用になります。

とはいっても、dist/bundle.js
ファイルは特にサーバーサイドで実行する必要はないので、次のような HTML ファイルを作成して、ローカルファイルとして Web ブラウザで開くことでも動作確認できます(public/
ディレクトリ以下の vite.svg
ファイルなどは参照できなくなりますが)。
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test</title>
<script src="./dist/bundle.js" defer></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
その他
public/
ディレクトリには、そのまま Web サイト用のリソースとしてデプロイされる画像ファイルなどが格納されていますが、今回の用途では必要ないのでディレクトリごと削除してしまっても大丈夫です。
public/
ディレクトリを削除した場合は、ソースコード内の vite.svg
を参照している箇所も削除してください。
(応用)UI 部分に Svelte を使う方法
HTML の UI 部分を出力するような JavaScript ライブラリーを作成する場合は、Svelte などのフレームワークを使うと便利です。 React や Vue などのフレームワークも同様に使えますが、最終的なリリース物が大きくなりがちなので、小規模なライブラリーの場合は Svelte を使うことをお勧めします。
- 参考: Svelte 関連メモ|まくろぐ
Vite + Svelte プロジェクトの作成
Vite のプロジェクトを作成する際に、フレームワークとして Svelte を使うよう指定します。
$ npm create vite@latest myscript
✔ Select a framework: › Svelte
✔ Select a variant: › TypeScript
$ cd myscript
$ npm install
先ほどと同様に、CSS コードを JavaScript に埋め込むための Vite プラグインをインストールしておきます。
$ npm install vite-plugin-css-injected-by-js --save-dev
実装
vite.config.ts
ファイルを編集して、Svelte や CSS のコードを単一の JavaScript ファイル (dist/bundle.js
) にバンドルするように設定します。
import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
export default defineConfig({
plugins: [svelte(), cssInjectedByJsPlugin()],
build: {
lib: {
entry: "src/main.ts",
formats: ["iife"], // Web サイト組み込み用に即時実行形式 (function(){})() で出力
name: "MyScript", // static API 用のグローバルオブジェクト名
},
rollupOptions: {
output: {
dir: "dist", // 出力ディレクトリ (default: dist)
entryFileNames: "bundle.js", // 出力ファイル名
},
},
},
});
下記は、Svelte コンポーネントによる UI 実装の例です。
ここでは同じディレクトリにある svelte.svg
という画像ファイルをインポートしていますが、このようにインポートした画像ファイルは、最終的に出力ファイルである JavaScript ファイルにバンドルされます。
<script lang="ts">
import svelteLogo from './svelte.svg';
let count = 0;
function increment() {
count += 1;
}
</script>
<div class="container">
<img src={svelteLogo} alt="Svelte Logo" />
<button on:click={increment}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
</div>
<style>
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
img {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
img:hover {
filter: drop-shadow(0 0 2em #ff3e00aa);
}
</style>
エントリーポイントとなる src/main.ts
では、上記の App.svelte
を読み込んで document.body
にマウントするようにしておきます。
import App from "./App.svelte";
new App({ target: document.body });
テスト
ローカルテスト用の index.html
ファイルでは、<script>
タグでエントリーポイントとなる /src/main.ts
を読み込むようにしておきます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Svelte + TS</title>
</head>
<body>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
開発サーバーを起動して、ブラウザで表示を確認します。
$ npm run dev -- --open
次のように表示されれば成功です。

リリース用ビルド
npm run build
コマンドでリリース用の JavaScript ファイルを生成します。
$ npm run build
出力された dist/bundle.js
は、他の Web サイトから <script>
要素で読み込むことができる単一の JavaScript ライブラリーになっています。
次のように defer
属性を付けて読み込むと、ページの読み込みが完了してから JavaScript ファイルが実行され、自動的に App.svelte
コンポーネントが表示されます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Svelte + TS</title>
<script src="./bundle.js" defer></script>
</head>
<body>
<!-- ... -->
</body>
もちろん、別のサーバーで bundle.js
をホスト(共有)して、各 Web サイトから読み込むことも可能です。
٩(๑❛ᴗ❛๑)۶ わーぃ
関連記事
- Jest で TypeScript コードのユニットテストを記述する
- TypeScriptの型: 既存の型をちょっと変えた型を作る(ユーティリティ型)
- React コンポーネントで入力フォームを作成する (2) react-hook-form 編
- React の props.children の型定義には ReactNode を使う
- TypeScript で JSON オブジェクトに型情報を付加する
- TypeScript で undefined/null をうまく扱う (nullish coalescing (??), optional chaining (?.))
- TypeScript コードを Prettier で自動整形する