2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SvelteKit + Leaflet で preview したらちゃんと動かなかったので修正した話

Last updated at Posted at 2023-03-20

はじめに

以下の投稿では SvelteKitLeaflet を使った地図アプリを作成しました。

本番配備バージョンでちゃんと動くか確認してみました。
まずは、ビルドしてから preview を実行します。

ターミナル
npm run build
npm run preview -- --host 127.0.0.1

そしてブラウザでアクセスしてみると、こんなエラーが表示されます。

ターミナル
/~~~/node_modules/leaflet/dist/leaflet-src.js:230
  var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer;
                  ^

ReferenceError: window is not defined
    at /workspaces/relics-map-svelte/node_modules/leaflet/dist/leaflet-src.js:230:19
    at /workspaces/relics-map-svelte/node_modules/leaflet/dist/leaflet-src.js:7:66
    at Object.<anonymous> (/workspaces/relics-map-svelte/node_modules/leaflet/dist/leaflet-src.js:10:3)
    at Module._compile (node:internal/modules/cjs/loader:1275:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1329:10)
    at Module.load (node:internal/modules/cjs/loader:1133:32)
    at Module._load (node:internal/modules/cjs/loader:972:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:168:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:193:25)

何が原因か?

window というオブジェクが存在しないってことですね。どうやら Leaflet の対象箇所がサーバーサイドで実行されているみたいです。

解決方法

SSR(Server Side Rendering)を強制的にOFFにすることでエラーが発生しなくなりました。
参考:https://kit.svelte.dev/docs/page-options#ssr

以下のファイルを作成します。

src/routes/+page.js
export const ssr = false;

これで地図が表示されるようになりました。

別の問題

マーカーのアイコンが表示されなくなってしまいました。:disappointed_relieved:
image.png

別の問題の原因

マーカーのHTML要素はこのようになっていました。

<img src="marker-icon.png"/>

marker-icon.png という存在していないファイルを参照しているのが原因です。

別の問題の解決方法

いろいろ調べましたが、Leaflet の画像ファイルを static ディレクトリ内にコピーするのが簡単でした。(ChatGPT に教えてもらいました:sweat_smile:)

  1. node_modules ディレクトリ内の leaflet ディレクトリから以下のファイルをコピーします。
    image.png

  2. コピーしたファイルを static/images/leaflet ディレクトリ内に張り付けます。
    image.png

  3. src/routes/+Map.svelte で画像ファイルのパスを修正します。

src/routes/+Map.svelte
<script>
  import { onMount } from 'svelte';
  import L from 'leaflet';
  import artifacts from './artifacts.json';
  import css from 'leaflet/dist/leaflet.css';

  let map;

  onMount(() => {
+    L.Icon.Default.imagePath = '/images/leaflet/';
    map = L.map('map').setView([35.658068, 139.751599], 13);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors',
      maxZoom: 18,
    }).addTo(map);

    artifacts.forEach(artifact => {
      const { name, description, lat, lng } = artifact;
      const marker = L.marker([lat, lng]).addTo(map);
      marker.bindPopup(`<h3>${name}</h3><p>${description}</p>`);
    });
  });
</script>

<div id="map" style="height: 100vh;"></div>

npm run buildnpm run preview -- --host 127.0.0.1 を実行しブラウザで表示したところ、マーカーのアイコンが表示されました。

まとめ

SvelteKit は便利ではありますが、本番環境で稼働させようとするといろいろ対応が必要になることが分かりました。おそらく Leafletに限った話ではないと思われます。

SvelteKit で開発する際は、コミットする前に npm run preview で軽く動作確認すると良いと思います。:smiley:

2
2
1

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?