React SDK 0.2.0 — 21 แพ็กเกจ การเปลี่ยนชื่อ และสิ่งที่โหลดไม่ได้เมื่ออยู่นอกบันเดลอร์

เผยแพร่ 21 แพ็กเกจด้วยเวอร์ชันเดียวกัน พร้อมการเปลี่ยนชื่อ react-geojson-layer การแก้ react-for-mapkit ที่เคยว่างเปล่า และสรุปว่าอะไรโหลดได้หรือไม่ได้เมื่ออยู่นอกบันเดลอร์

MapConductor React SDK ขึ้นเป็น 0.2.0 แล้ว มี 21 แพ็กเกจบน npm ทั้งหมดใช้สัญญาอนุญาต Apache-2.0 มีเพียง @mapconductor/react-for-openlayers ที่เป็น 0.2.1 เหตุผลอยู่ท้ายบทความ

สิ่งที่เปลี่ยนไป

  • ปรับเวอร์ชันของทุกแพ็กเกจให้ตรงกัน พร้อมขยับช่วงเวอร์ชันของดีเพนเดนซีภายในระหว่าง @mapconductor/* ไปด้วย จึงไม่เกิดการปนกันของเวอร์ชันโดยไม่ตั้งใจ
  • เปลี่ยนชื่อ @mapconductor/react-geojson-layer เป็น @mapconductor/react-geojson สิ่งที่เปลี่ยนคือชื่อแพ็กเกจเท่านั้น ส่วน GeoJSONLayer GeoJSONLayerState GeoJSONParser และ API อื่น ๆ ยังเหมือนเดิม แพ็กเกจเดิมยังอยู่บน npm ที่เวอร์ชัน 0.1.3 แต่จะไม่มีการอัปเดตอีก
  • เผยแพร่ 4 แพ็กเกจเป็นครั้งแรก ได้แก่ react-for-arcgis react-for-mappls react-geojson และ react-kml
  • react-for-mapkit มีเนื้อหาแล้ว เวอร์ชัน 0.1.3 มีเพียง LICENSE กับ README เพราะตกหล่นจากรายการเป้าหมายของการบิลด์ ทำให้ files: ["dist"] ไม่ตรงกับอะไรเลย หากใช้ 0.1.3 อยู่ ขอให้อัปเกรด
  • แก้ตัวระบุสัญญาอนุญาตเป็น Apache-2.0 ก่อนหน้านี้เขียนว่า Apache2 ซึ่งไม่ถูกต้องตาม SPDX เครื่องมือต่าง ๆ จึงมองว่าเป็น “สัญญาอนุญาตที่ระบุไม่ได้”

เราอัปเดตดีเพนเดนซีของ SDK แผนที่ให้เป็นรุ่นล่าสุดภายในช่วงที่ประกาศไว้ ที่ขยับจริงมีเพียงสองตัวคือ maplibre-gl (6.3.0 → 6.4.0) และ @turf/turf (7.3.5 → 7.4.0) ส่วนที่เหลือเป็นรุ่นล่าสุดอยู่แล้ว

แพ็กเกจและ SDK แผนที่ที่แต่ละตัวใช้

แพ็กเกจเวอร์ชันSDK แผนที่รีโพซิทอรี
@mapconductor/js-sdk-core0.2.0js-sdk-core
@mapconductor/js-sdk-react0.2.0js-sdk-react
@mapconductor/react-for-arcgis0.2.0@arcgis/core ^5.1.16react-for-arcgis
@mapconductor/react-for-azuremaps0.2.0azure-maps-control ^3.7.0react-for-azuremaps
@mapconductor/react-for-cesium0.2.0cesium ^1.131.0react-for-cesium
@mapconductor/react-for-googlemaps0.2.0@googlemaps/js-api-loader ^2.1.1react-for-googlemaps
@mapconductor/react-for-here0.2.0CDN (global H)react-for-here
@mapconductor/react-for-leaflet0.2.0leaflet ^1.9.4react-for-leaflet
@mapconductor/react-for-longdo0.2.0CDN (api.longdo.com/map3)react-for-longdo
@mapconductor/react-for-mapbox0.2.0mapbox-gl ^3.15.0react-for-mapbox
@mapconductor/react-for-mapkit0.2.0CDN (cdn.apple-mapkit.com)react-for-mapkit
@mapconductor/react-for-maplibre0.2.0maplibre-gl ^6.0.0react-for-maplibre
@mapconductor/react-for-mappls0.2.0mappls-web-maps ^3.8.1react-for-mappls
@mapconductor/react-for-maptiler0.2.0maplibre-gl ^6.0.0react-for-maptiler
@mapconductor/react-for-openlayers0.2.1ol ^10.2.1react-for-openlayers
@mapconductor/react-for-tomtom0.2.0@tomtom-org/maps-sdk ^0.51.0, maplibre-gl ^5.24.0react-for-tomtom
@mapconductor/react-geojson0.2.0react-geojson
@mapconductor/react-heatmap0.2.0react-heatmap
@mapconductor/react-icons0.2.0react-icons
@mapconductor/react-kml0.2.0react-kml
@mapconductor/react-marker-clustering0.2.0react-marker-clustering

มีสามผู้ให้บริการที่ไม่มี SDK แผนที่เป็นดีเพนเดนซี เพราะ SDK ไม่ได้เผยแพร่บน npm ทั้ง HERE Apple MapKit JS และ Longdo จะโหลดจาก CDN ของผู้ให้บริการตอนรัน เวอร์ชันที่ทำงานจริงจึงเป็นเวอร์ชันที่ผู้ให้บริการเผยแพร่อยู่

มีเพียง react-for-tomtom ที่ยังคง maplibre-gl ไว้ที่ 5.x เพราะ @tomtom-org/maps-sdk พึ่งพา maplibre-gl@^5.24.0 หากขยับเป็น 6.x จะมี MapLibre สองชุด และส่งอ็อบเจกต์ map ที่ TomTom SDK ไม่ได้คาดไว้เข้าไป

ESM, CommonJS และ SSR

แพ็กเกจเหล่านี้ตั้งอยู่บนสมมติฐานว่ามีบันเดลอร์ ทั้ง Vite, webpack, Next.js และ Metro แก้ปัญหาการอ้างอิงได้ถูกต้อง และก่อนเผยแพร่เราตรวจการวาดบนเบราว์เซอร์จริงครบทุกผู้ให้บริการแล้ว

แต่กรณีที่ให้ ตัวแก้ปัญหาการอ้างอิงของ Node เอง อ่านโดยตรงนั้นเป็นอีกเรื่อง ไม่ว่าจะเป็น node เปล่า ๆ ทางเข้า SSR ที่ไม่ผ่านบันเดลอร์ หรือสภาพแวดล้อม node ของ Vitest เพราะ SDK แผนที่ที่อยู่เบื้องล่างเป็นไลบรารีสำหรับเบราว์เซอร์ ตารางนี้ได้จากการ import แพ็กเกจที่เผยแพร่แล้วในโปรเจกต์เปล่าจริง ๆ

แพ็กเกจimportrequire()เหตุผล
react-for-arcgisnono@arcgis/core/views/MapView อิมพอร์ตไฟล์ .css ซึ่ง Node โหลดไม่ได้ และแผนที่ทุกแบบต้องใช้ MapView จึงเลี่ยงจากฝั่งเราไม่ได้
react-for-leafletnonoleaflet แตะ window ตั้งแต่ตอนประเมินโมดูล
react-for-azuremapsnonoazure-maps-control แตะ window ตั้งแต่ตอนประเมินโมดูล
react-for-tomtomnonoอ่าน maplibre-gl/package.json ซึ่ง Node จะโหลดให้ก็ต่อเมื่อมี import attribute
react-for-mapplsnoyesmappls-web-maps เป็น CommonJS ตัวโหลด ESM จึงวิเคราะห์ named export แบบสแตติกไม่ได้
react-for-maplibreyesnomaplibre-gl v6 เป็น ESM ล้วน และไม่ประกาศทางเข้าแบบ CommonJS
react-for-maptileryesnoเหมือนกับ react-for-maplibre

อีก 14 แพ็กเกจที่เหลือโหลดได้ทั้งสองแบบ ผลลัพธ์นี้เหมือนกันตั้งแต่ 0.1.3 จึงไม่ใช่เรื่องที่เพิ่งเกิดใน 0.2.0

มีสองข้อที่ควรจำไว้

  • เมื่อทำ SSR ให้ import ผู้ให้บริการแบบ lazy ทางฝั่งไคลเอนต์ หาก import ผู้ให้บริการที่ใช้ได้เฉพาะเบราว์เซอร์แบบสแตติกที่ระดับบนสุด การเรนเดอร์ฝั่งเซิร์ฟเวอร์ที่ไม่ผ่านบันเดลอร์จะพัง ตัวอย่างเว็บอย่างเป็นทางการใช้ lazy(() => import('./providers/...')) การบิลด์ SSR ของ Vite จึงผ่าน
  • react-for-maplibre react-for-maptiler และ react-for-tomtom ประกาศทางเข้าแบบ CommonJS ที่ใช้งานจริงไม่ได้ เพราะ maplibre-gl v6 เลิกรองรับ CommonJS แล้ว ขอให้ใช้สามตัวนี้แบบ ESM ส่วนการถอด require ออกจาก exports จะทำในรุ่นถัดไป

จุดเดียวที่เป็นความผิดของเราเอง

การที่ react-for-openlayers โหลดใน Node ESM ไม่ได้นั้นไม่เกี่ยวกับ OpenLayers เลย ซอร์สของเราเอง import ol/proj โดยไม่ใส่นามสกุลไฟล์ ซึ่ง Node ปฏิเสธเพราะถือเป็นการ import ไดเรกทอรี บันเดลอร์ปล่อยผ่าน เราจึงไม่ทันสังเกต แก้แล้วใน 0.2.1 เปลี่ยนเพียงบรรทัดเดียว และพฤติกรรมเมื่อผ่านบันเดลอร์ไม่เปลี่ยน

การติดตั้ง

bash
npm install @mapconductor/js-sdk-core @mapconductor/js-sdk-react @mapconductor/react-for-maplibre

แต่ละแพ็กเกจอยู่ในรีโพซิทอรีของตัวเอง ดูได้ที่ github.com/MapConductor