Leaflet.jsをWebpackでbuildする

今年始めてのブログなんですね。(今年が既に3ヶ月過ぎようとしてるのは…)

なんどか同じような話題を書いてるような気がしますが。 Leaflet.js もnpmで管理されてるのに、公式ページGithubに利用方法が明記されていないようなのでメモ (もしかしたら、見つけられていないだけかもしれないですが)

実行環境

  • node.js v9.7.1
  • leaflet.js v1.3.1
  • webpack v4.0.1
  • webpack-dev-server v3.1.0
  • css-loader v0.28.10
  • styleloader v0.20.2
  • url-loader v0.6.2

環境構築

ライブラリのインストール

yarn add leaflet webpack

HTMLの準備

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Webpack Sample</title>
</head>
<body>
  <div id="map"></div>
  <script src="main.js"></script>
</body>
</html>

JS

import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import './css/map.css'
import iconRetinaUrl from 'leaflet/dist/images/marker-icon-2x.png'
import iconUrl from 'leaflet/dist/images/marker-icon.png'
import shadowUrl from 'leaflet/dist/images/marker-shadow.png'

let map = L.map('map').setView([43.067, 141.35], 16);

delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
  iconRetinaUrl: iconRetinaUrl,
  iconUrl: iconUrl,
  shadowUrl: shadowUrl
});

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
  maxZoom: 18
}).addTo(map);

delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
  iconRetinaUrl: iconRetinaUrl,
  iconUrl: iconUrl,
  shadowUrl: shadowUrl
});

L.marker([43.067, 141.35]).addTo(map)
.bindPopup('札幌駅前だよー')
.openPopup();

import 'leaflet/dist/leaflet.css'node_modules に含まれているleaflet.cssをbundleしている

アイコン用の画像がbundleされないため、以下の処理を追加してDefaultアイコンを再初期化している

delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
  iconRetinaUrl: iconRetinaUrl,
  iconUrl: iconUrl,
  shadowUrl: shadowUrl
});

参考: L.Icon.Default brings a wrong image url · Issue #4968 · Leaflet/Leaflet · GitHub

map表示領域を設定するCSS

#map {
  width: 500px;
  height: 500px;
}

webpack.config.js

module.exports = {
  entry: './src/index.js',
  output: {
    path: `${__dirname}/dist`,
    filename: 'main.js'
  },
  module: {
    rules : [
      // CSS
      {
        test: /\.css/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              url: false
            },
          }
        ]
      },
      {
        test: /\.png/,
        use: [
          'url-loader'
        ]
      }
    ]
  },
  mode: 'development',

  devServer: {
    contentBase: '.',
    open: true
  },
}

実行方法

npx webpack-dev-server

実行結果

f:id:hinosita:20180321235414p:plain

CDNやライブラリをダウンロードして実装するよりは多少手はかかるものの、npmでLeaflet.jsを取得しWebpackと連携することも出来ます。 公式でなんで方法が公開されないんだろう…

今回のサンプルコード一式は公開してあります

github.com