LoginSignup
1
1

npmでインストールしたライブラリをブラウザで利用できるようにする手順(ReactやVue.jsなどフレームワークは未使用)

Last updated at Posted at 2024-04-13

はじめに

(Webアプリの場合)npmでインストールしたライブラリは、CDNから読み込むような感じでは使えません

importrequireでライブラリを読み込み、さらにそれをバンドルする必要があります

モジュール形式でjsファイルを作成すると型定義を利用できたり、JSファイルの読み込み順(依存関係)に悩むことがなくなるなど様々な利点があります

そこで、できるだけ簡単かつ使いまわせる形でバンドルする方法をまとめました(rollup.jsを使います)

※VSCodeでは、npmでインストールしたライブラリを利用すれば(TypeScriptを利用しなくても)型定義のサポートを受けることができます

こんな状況を想定

  • 今までnpmを使ってこなかったWebアプリケーションから、npmのライブラリを利用したい
  • VSCodeが型定義を表示してくれないので不便(全てany型になってしまう)
  • ReactやVue.jsを使えばnpmのライブラリ読み込めるけど、フレームワーク無しでは読み込み方がわからない

サンプルとして、Leaflet という地図ライブラリを使ったアプリを作成します

Leafletは、CDNを利用した従来の読み込み方法と、npmのモジュール両方で利用することができるため、2パターンでWebアプリを作成してみます

①従来のCDN+<script>タグで読み込んで地図を表示

Leaflet公式Quick Start Guideページのサンプルをもとに、地図を国土地理院の地理院タイルに変更したサンプルプログラムです

ポイント

  • ライブラリjsファイルは、公式サンプルの通りCDN(unpkg.com)から読み込む
  • cssを読み込んだ後に、leaflet.jsを読み込む
  • 地図を画面全体に表示するためのstyleを追加
  • js部分はコメント参照 (経度緯度を指定して地図を表示)
leaflet_conventional.html
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>leaflet conventional js sample</title>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
    integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
  <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
    integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
  <style>
    /* 画面全体に地図を表示 */
    body { margin: 0 }
    #map { height: 100vh; }
  </style>
</head>
<body>
  <div id="map"></div>
  <script>
    const latLen = [35.3607411, 138.727262]; // 富士山頂の緯度経度
    const map = L.map('map'); // 地図を生成
    map.setView(latLen, 12);  // 緯度経度、ズームレベルを設定
    // タイルレイヤを生成し、地理院タイルを地図に追加
    L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="https://maps.gsi.go.jp/development/ichiran.html">国土地理院</a>'
    }).addTo(map);
  </script>
</body>
</html>
  • 実行するとこんな感じで富士山が表示されます(拡大、縮小、移動もできます)

img10.png

次は、まったく同じ機能のWebアプリをnpm環境で作成します

②npmでインストールしたライブラリを利用して地図を表示

①で作成したjsソースを流用して、npm環境に移植します(node.jsはインストール済みの前提)

手順

  1. npmで実行とビルド(バンドル)に必要なライブラリをインストールする
  2. 地図を表示するjsファイルを作成する
  3. 作成したjsファイルと、npmでインストールしたライブラリをバンドルするスクリプトを作成する
  4. jsファイルをビルド(バンドル)する
  5. バンドルしたjsを読み込むhtmlファイルを作成する

1. npmで実行とビルド(バンドル)に必要なライブラリをインストールする

まずLeaflet本体と、バンドルに必要なライブラリをインストールします

npm init -y
npm i leaflet
npm i -D rollup rollup-plugin-delete rollup-plugin-import-css @rollup/plugin-node-resolve  rollup-plugin-peer-deps-external @rollup/plugin-commonjs @rollup/plugin-terser
ライブラリ名 概要
leaflet 地図表示ライブラリ
rollup JavaScript 用のモジュール バンドラー(以降はビルド用のプラグイン)
rollup-plugin-peer-deps-external 重複した依存関係を削除(バンドルサイズを削減)
rollup-plugin-delete 出力先を削除するために利用
rollup-plugin-import-css javascriptからcssを読み込むために利用
@rollup/plugin-node-resolve importしたライブラリの依存関係を解決して、node_moduleから見つける
@rollup/plugin-commonjs CommonJSモジュールをES6に変換(バンドルできるようになる)
@rollup/plugin-terser jsファイルを圧縮(minifi)する

2. 地図を表示するjsファイルを作成する

①従来のCDN+<script>タグで読み込んで地図を表示で作成したスクリプトをそのまま流用します

ソースの変更(追加)は下記2か所です

  • 必要なライブラリ、cssをimportする
  • 外部から利用可能にするためにexportする
./src/leaflet_rollup.js
// npmでインストールしたライブラリをimport
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';

const latLen = [35.3607411, 138.727262]; // 富士山頂の緯度経度
const map = L.map('map'); // 地図を生成
map.setView(latLen, 12); // 緯度経度、ズームレベルを設定
// タイルレイヤを生成し、地理院タイルを地図に追加
L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="https://maps.gsi.go.jp/development/ichiran.html">国土地理院</a>',
}).addTo(map);

// mapをエクスポートする
export default map;

3. 作成したjsファイルと、npmでインストールしたライブラリをバンドルするスクリプトを作成する

rollup.jsを利用して、モジュールをバンドルするスクリプトを作成します

(ファイルの拡張子はmjsにします。jsだとrollup.jsがcommonJSとして読み込みエラーとなるため)

rollup.config.mjs
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import resolve from '@rollup/plugin-node-resolve';
import css from 'rollup-plugin-import-css';
import commonjs from '@rollup/plugin-commonjs';
import del from 'rollup-plugin-delete';
import terser from '@rollup/plugin-terser';

export default {
  input: './src/leaflet_rollup.js', // バンドル対象のファイル名。このファイルを元に読み込まれているjsを探してまとめる
  output: {
    file: './dist/bundle.js', // 出力ファイル名
    format: 'esm', // ESモジュール形式で出力する
    sourcemap: true, // ソースマップを作成(元jsファイルでデバッグできる)
  },

  plugins: [
    peerDepsExternal(), // 重複した依存関係を削除(バンドルサイズを削減)
    del({ targets: 'dist/*' }), // 出力先を削除
    css({ output: 'bundle.css' }), // importしたcssファイルの出力先
    resolve(), // importしたライブラリの依存関係を解決して、node_moduleから見つける
    commonjs(), // commonjs形式のライブラリを読み込み可能にする
    terser(), // minify(圧縮)
  ],
};

4. jsファイルをビルド(バンドル)する

バンドルはrollupを直接呼び出すか

$ npx rollup -c

./src/leaflet_rollup.js → ./dist/bundle.js...
created ./dist/bundle.js in 532ms

package.json の`scripts'に登録して実行します

package.json
  "scripts": {
    "build": "rollup -c"
  },
$ npm run build

> npm_leaflet_rollup@1.0.0 build
> rollup -c

./src/leaflet_rollup.js → ./dist/bundle.js...
created ./dist/bundle.js in 532ms

./dist フォルダにバンドルされたファイル(とmapファイル)が生成されます

img20.png

  • mapファイルとは

    変換前のコードと変換後のコード(行の位置)を紐づけるファイルです。
    jsファイルをビルドすると、圧縮や結合されることによりデバッグが困難になりますが、mapファイルがあれば、変換前のjsソースでデバッグを行うことができるようになります。

5. バンドルしたjsを読み込むhtmlファイルを作成する

バンドル後のjsファイル./dist/bundle.jsをhtmlファイルで読み込みます

  • jsファイルはESモジュール形式なので、type="module"が必要です
leaflet_rollupjs.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>leaflet npm bundle js sample</title>
  <style>
    /* 画面全体に地図を表示 */
    body { margin: 0 }
    #map { height: 100vh; }
  </style>
  <link rel="stylesheet" href="./dist/bundle.css"> <!-- cssを読み込む -->
  <script type="module">
    // バンドルしたファイルを読み込む
    // type="module"なので、DOMのロード後に実行される
    import map from './dist/bundle.js';
  </script>
</head>
<body>
  <div id="map"></div>
</body>
</html>

ブラウザに表示すると①従来のCDN+&lt;script&gt;タグで読み込んで地図を表示と全く同一の地図が表示されます

img10.png

minifyしてありますが、mapファイルを生成しているためバンドル前のjsファイルでデバッグすることができます。

img30.png

1
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
1
1