0
1

これまでのコードを最大限に活用!ViteでJavaScriptをライブラリー化してみよう

Last updated at Posted at 2024-09-09

ウェブ開発で、過去に作ったUI部品やアルゴリズムを再利用できると便利ですよね!今回は、Viteを使って「Hello World」を表示するシンプルなライブラリーを作成し、どのようにして他のプロジェクトに組み込むかを解説します。

はじめに

再利用可能なライブラリーを作っておくと、コードをメンテナンスしたり、他プロジェクトでの応用するときに非常に役立ちます。この記事では、Viteを使用して、背景色を虹色に輝かせる「Hello World」を表示するJavaScriptライブラリーの作り方をステップ・バイ・ステップで紹介します。

この記事に記載したソースコードはこちらで公開しています。

1. プロジェクトのセットアップ

まず、Viteを使ってプロジェクトをセットアップします。以下の手順に従って進めてください。

Viteのインストール

npm init vite@latest hello-lib

途中で選択肢が出てきます。今回は素の(Valnilla)JavaScriptで開発してみるので、以下を選択してください。

✔ Select a framework: › Vanilla
✔ Select a variant: › JavaScript

プロジェクトの初期化後、依存関係をインストールします。

cd hello-lib
npm install

2. 不要なファイルの削除と、必要なディレクトリー・ファイルの追加

この状態でnpm run devを実行するとViteを使ったカウンターアプリを実行できます。ただ今回は不要なので、削除しておきます。

rm *.html *.css *.js *.svg
rm -rf public

今回、ライブラリーのソースコードはsrcディレクトリーの下に作っていきます。

mkdir src

また、gitで管理するときに、誤って余計なファイルを公開してしまわないよう、.gitignoreファイルを作っておきます。また、gitを初期化しておきます。

curl https://raw.githubusercontent.com/vitejs/vite/main/.gitignore -o .gitignore
git init

3. HTMLテンプレートの作成

次に、表示するコンテンツである「Hello World」のHTMLテンプレートを作成します。さらに、背景色を虹色に輝かせるCSSを追加してスタイルを整えます。

src/template.html
<div class="hello-world">Hello World!</div>
src/style.css
.hello-world {
  font-size: 24px;
  color: white;
  background-image: linear-gradient(
    270deg,
    red,
    orange,
    yellow,
    green,
    blue,
    indigo,
    violet
  );
  background-size: 400% 400%;
  animation: rainbowBackground 5s ease infinite;
  padding: 10px;
  border-radius: 5px;
}

@keyframes rainbowBackground {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

4. Injectionロジックの実装

ここでは、テンプレートとスタイルをウェブページに挿入するJavaScriptコードを実装します。HelloLib.init()関数を作成し、指定されたDOM要素にHTMLとCSSを挿入します。

src/main.js
import template from './template.html?raw';
import style from './style.css?raw';

const HelloLib = {
  init(container) {
    const styleElement = document.createElement('style');
    styleElement.innerHTML = style;
    document.head.appendChild(styleElement);

    container.innerHTML = template;
  }
};

export default HelloLib;

ファイルを文字列としてインポートする?raw

今回制作するライブラリーは、テンプレートのHTMLやCSSを文字列としてインポートして、動的に注入します。Viteでは外部ファイルをimportでインポートする際、ファイル名の末尾に?rawをつければ文字列として扱えます。

外部から参照するためのexport default

モジュールとして定義したHelloLibを外部から参照できるようにするため、export default HelloLib;を記述しておくことは非常に重要です。詳しくはビルドの章で説明します。

5. ライブラリーのビルドとパッケージ化

ライブラリーをビルドしてパッケージ化するには、vite.config.jsファイルを設定し、ライブラリーモードを利用する必要があります。このファイルはプロジェクトのルートディレクトリーに置きます。

vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    lib: {
      entry: './src/main.js',
      name: 'HelloLib',
      formats: ["es", "umd"],
      fileName: (format) => `hello-lib.${format}.js`,      
    },
  },
});

ビルドコマンド

次に、以下のコマンドを実行してライブラリーをビルドします。

npm run build

実行結果は次の通りです:

> hello-lib@0.0.0 build
> vite build

vite v5.4.3 building for production...
✓ 3 modules transformed.
dist/hello-lib.es.js  0.36 kB │ gzip: 0.26 kB
dist/hello-lib.umd.js  0.59 kB │ gzip: 0.41 kB
✓ built in 29ms

ESMとUMDの違い

ビルドが完了すると、distフォルダに2つの形式のファイルが生成されます。

ESM形式 (hello-lib.es.js)

JavaScriptのESモジュール(ESM)形式のファイルです。ESM形式は、モジュールを他のモジュールとしてインポートするための標準的な仕組みです。

ESM形式では、import文を使ってモジュールを読み込みます。例えば、他のJavaScriptファイルで以下のようにインポートします。

import HelloLib from './dist/hello-lib.es.js';
HelloLib.init(container);

モダンなブラウザや、ESMをサポートするNode.js環境で使用されます。

開発時には、ESM形式を使って直接モジュールを利用し、動作確認ができるようにします。

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>HelloLib Example</title>
  </head>
  <body>
    <div id="hello-container"></div>
    <script type="module">
      import HelloLib from './src/main.js';

      const container = document.getElementById("hello-container");
      HelloLib.init(container);
    </script>
  </body>
</html>

UMD形式 (hello-lib.umd.js)

UMD(Universal Module Definition)形式は、モジュールをブラウザやNode.jsの両方で動作させるために使用される形式です。UMD形式では、グローバルスコープにモジュールが自動的に定義されます。

UMD形式では、<script>タグで読み込むと、HelloLibがグローバルオブジェクトとして定義され、直接利用できます。

<script src="/dist/hello-lib.umd.js"></script>
<script>
  const container = document.getElementById('hello-container');
  HelloLib.init(container);
</script>

UMD形式は、ブラウザやNode.jsの両方で動作するため、幅広い環境で使用されます。

ビルドしたUMD形式のファイルが正しく動作しているかを確認するため、testディレクトリーを作り、その下に確認用のindex.htmlを置いて動作を確認できるようにします。

mkdir test
test/index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>Test of HelloLib Example</title>
  </head>
  <body>
    <h3>Test</h3>
    <div id="hello-container"></div>
    <script src="../dist/hello-lib.umd.js"></script>
    <script>
      const container = document.getElementById("hello-container");
      HelloLib.init(container);
    </script>
  </body>
</html>

6. 動作確認

ホットリロードを活用した効率的な開発

前述した通り、ESM形式を使うindex.htmlと、UMD形式を使うtest/index.htmlを準備したら、動作を確認してみます。

開発用サーバーを実行し、index.htmlでHello Worldが正しく表示されているかを確認します。ホットリロードが有効になっているため、関連するソースコードを変更すると自動的に再読み込みされます。

npm run dev

を実行して、表示されたURLにアクセスしてみましょう。


  VITE v5.4.3  ready in 89 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

ビルドした成果物の動作確認

開発が一段落したら、ビルドで出力されたライブラリーが正しく動作しているかを確認します。

npm run build

でビルドが成功したら、test/index.htmlを開いて正しく表示されることを確認します。

7. ライブラリーの設定をpackage.jsonに追加

ライブラリーがさまざまなJavaScriptの環境でスムーズに動作するよう、公式ドキュメントが推奨するpackage.jsonの記述を追記しておきます。

package.json
{
  "name": "hello-lib",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "files": [
    "dist"
  ],
  "main": "./dist/hello-lib.umd.js",
  "module": "./dist/hello-lib.es.js",
  "exports": {
    ".": {
      "import": "./dist/hello-lib.es.js",
      "require": "./dist/hello-lib.umd.js"
    }
  },
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "vite": "^5.4.1"
  }
}

追記する項目について説明します。

  1. filesフィールド
    files: 公開時にnpmパッケージに含めるファイルを指定します。パッケージを軽量化するため、不要なファイルのみを定義します。

  2. mainフィールド
    main: CommonJS形式のエントリーポイントを指定します。これは、古いJavaScript環境やNode.jsで使われる形式です。ここでは、ビルドしたUMD形式のファイルを指定します("main": "./dist/hello-lib.umd.js")。

  3. moduleフィールド
    module: ESモジュール形式(ESM)でのエントリーポイントを指定します。これは、モダンなブラウザやJavaScript環境で利用される形式です("module": "./dist/hello-lib.es.js")。
    mainmoduleの2つのフィールドを指定することで、ユーザーは自動的に環境に応じて適切な形式を選択してライブラリをインポートできます。

  4. exportsフィールド
    exports: ライブラリがどの形式でエクスポートされるかを詳細に定義します。これにより、環境ごとに適切なビルド形式を提供できます。たとえば、ESM形式が必要な場合と、CommonJS形式が必要な場合のパスを指定できます。以下の例は、importを使用する場合はESMが、requireを使用する場合はUMD/CJSが読み込まれるようになります。

{
  "exports": {
    "./": {
      "import": "./dist/hello-lib.es.js",
      "require": "./dist/hello-lib.umd.js"
    }
  }
}

.cjsファイルについての注意事項

Viteのライブラリーモードでビルドを行う際、vite.config.jsfileNameを指定しないと、UMD形式のファイルはデフォルトで拡張子.cjsとして出力されます。しかし、.cjs拡張子はNode.jsでのCommonJSモジュールとして使用されることが一般的であり、ブラウザでは適切に処理されない場合があります。

特に、Cloudflareなどのホスティングサービスでは、.cjsファイルがapplication/nodeというMIMEタイプで提供されることがあります。このMIMEタイプはブラウザでは実行できないため、次のようなエラーが発生します。

Refused to execute script from 'https://your-site/dist/hello-lib.umd.cjs' because its MIME type ('application/node') is not executable.

このエラーは、ブラウザが.cjsファイルをNode.js専用のモジュールとして認識してしまうためです。この問題を回避するためには、vite.config.jsformatsfileNameを明示的に指定し、UMD形式のファイルを.jsとして出力する設定に変更します。

vite.config.js
  lib: {
    ...
    formats: ["es", "umd"],
    fileName: (format) => `hello-lib.${format}.js`,

これにより、ビルドされたUMD形式のライブラリーは.js拡張子で出力され、クラウドホスティングサービス上でのMIMEタイプエラーを防ぎ、ブラウザで正しく認識・実行されます。

まとめ

今回の記事では、Viteを使って「Hello World」を表示するJavaScriptライブラリーを作成しました。この記事の手順に従うことで、他のプロジェクトに再利用可能なライブラリーを作成できるようになります。

この記事には基本的なことしか書いてありませんが、皆さんがこれまでに開発してきた資産を再利用するきっかけになれば幸いです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1