Skip to content

Build module as stand alone plugin for Vue/ol using umd #427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
disarticulate opened this issue May 4, 2025 · 2 comments
Open

Build module as stand alone plugin for Vue/ol using umd #427

disarticulate opened this issue May 4, 2025 · 2 comments

Comments

@disarticulate
Copy link

Is your feature request related to a problem? Please describe.
I'm trying to build a page without a bundler and importing scripts like:

    <!-- Quasar -->
    <script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@2.18.1/dist/quasar.umd.prod.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@v2/dist/icon-set/fontawesome-v6.umd.prod.js"></script>

    <!-- Open Layers -->
    <script src="https://cdn.jsdelivr.net/npm/ol@10.5.0/dist/ol.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/ol-contextmenu"></script>
    <script src="https://cdn.jsdelivr.net/npm/ol-ext@4.0.31/dist/ol-ext.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue3-openlayers@11.6.0/dist/vue3-openlayers.umd.cjs"></script>

Describe the solution you'd like
vue3-openlayers.umd.cjs does not import as a umd module usually does because commonjs isn't used by browsers. I tried the ESM module, but the stack above (quasar, et al) would all need to be re worked. Future libraries would also be limited to ESM.

If I could use a script vue3-openlayers and introduce my vue app and inject the necessary open layers packages, it should work.

Describe alternatives you've considered
The alternative is to find ESM versions of all the libraries I'm using now and in the future. Typically, there's not much needed to get a UMD module, but there needs to be a bootstrap pointing to the correct libraries (vue, ol) or checking globals. When using vue in umd the global is Vue. When using openlayers the global is ol.

It looks like we'd need to augment: https://github.com/MelihAltintas/vue3-openlayers/blob/main/src/index.ts and create some kind of loader function from global variables. I'm not versed in typescript.

I can provide a working template to test if needed.

@disarticulate
Copy link
Author

disarticulate commented May 4, 2025

OK, so it does look like it's a build config issue. Here's what I had to do to get a useable umd:

import vue from "@vitejs/plugin-vue";
import { fileURLToPath, URL } from "url";
import { defineConfig } from "vite";
import dts from "vite-plugin-dts";

export default defineConfig({
  plugins: [
    dts({
      // logLevel: 'warn',
      // copyDtsFiles: false,
      outDir: ["dist"],
      // include: ['src/index.ts'],
      exclude: ["src/main.ts"],
      aliasesExclude: [/^@demos/],
      staticImport: true,
      // rollupTypes: true,
      insertTypesEntry: true,
    }),
    vue(),
  ],
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
      "@components": fileURLToPath(
        new URL("./src/components", import.meta.url),
      ),
      "@demos": fileURLToPath(new URL("./src/demos", import.meta.url)),
    },
    preserveSymlinks: false,
    dedupe: ["vue"],
    extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
  },
  build: {
    cssCodeSplit: true,
    lib: {
      entry: fileURLToPath(new URL("./src/index.ts", import.meta.url)),
      name: "vue3-openlayers",
      fileName: (format, entryName) =>
        `vue3-openlayers-${entryName}.${format}.js`,
      formats: ["es", "cjs", "umd"],
    },
    minify: false,
    rollupOptions: {
      // make sure to externalize deps that should not be bundled
      // into your library
      input: {
        main: fileURLToPath(new URL("./src/index.ts", import.meta.url)),
      },
      external: ["vue", /^ol.*/, /^@turf.*/], // Avoid bundling ol imports into the final build
      output: {
        name: "Vue3OpenLayers",
        inlineDynamicImports: true,
        exports: "named",
        globals: {
          vue: "Vue",
          ol: "ol",
          "ol/Feature": "ol.Feature",
          "ol/geom": "ol.geom",
          "ol/format": "ol.format",
          "ol/loadingstrategy": "ol.loadingstrategy",
          "ol/events/condition": "ol.selectconditions",
          "ol/extent": "ol.extent",
          "ol/easing": "ol.animations",
          "ol/Geolocation": "ol.Geolocation",
          "ol/Map": "ol.Map",
          "ol/interaction/defaults": "ol.interaction.defaults",
          "ol/Overlay": "ol.Overlay",
          "ol/proj/proj4": "ol.proj4",
          "ol/proj/Projection": "ol.proj.Projection",
          "ol/View": "ol.View",
          "ol/proj": "ol.proj",
          "ol/tilegrid": "ol.tilegrid",
          "ol/events/condition": "ol.events.condition",
          "ol/easing": "ol.easing",

          "ol/layer": "ol.layer",
          "ol/layer/Heatmap": "ol.layer.HeatmapLayer",
          "ol/layer/Image": "ol.layer.ImageLayer",
          "ol/layer/Group": "ol.layer.LayerGroup",
          "ol/layer/Tile": "ol.layer.Tile",
          "ol/layer/Vector": "ol.layer.Vector",
          "ol/layer/VectorTile": "ol.layer.VectorTile",
          "ol/layer/VectorImage": "ol.layer.VectorImage",
          "ol/layer/WebGLPoints": "ol.layer.WebGLPoints",
          "ol/layer/WebGLVector": "ol.layer.WebGLVector",
          "ol/layer/WebGLTile": "ol.layer.WebGLTile",

          "ol/tilegrid/WMTS": "ol.tilegrid.TileGridWMTS",

          "ol/source/BingMaps": "ol.source.BingMaps",
          "ol/source/Cluster": "ol.source.Cluster",
          "ol/source/ImageStatic": "ol.source.ImageStatic",
          "ol/source": "ol.source",
          "ol/source/ImageWMS": "ol.source.ImageWMS",
          "ol/source/GeoTIFF": "ol.source.GeoTIFF",
          "ol/source/OSM": "ol.source.OSM",
          "ol/source/StadiaMaps": "ol.source.StadiaMaps",
          "ol/source/TileDebug": "ol.source.TileDebug",
          "ol/source/WMTS": "ol.source.WMTS",
          "ol/source/TileArcGISRest": "ol.source.TileArcGISRest",
          "ol/source/TileJSON": "ol.source.TileJSON",
          "ol/source/TileWMS": "ol.source.TileWMS",
          "ol/source/Vector": "ol.source.Vector",
          "ol/source/VectorTile": "ol.source.VectorTile",
          "ol/source/XYZ": "ol.source.XYZ",
          "ol/source/Tile": "ol.source.Tile",
          "ol/source/Image": "ol.source.Image",

          "ol/control": "ol.control",
          "ol/control/OverviewMap": "ol.control.OverviewMap",
          "ol/control/Rotate": "ol.control.Rotate",
          "ol/control/Attribution": "ol.control.Attribution",
          "ol/control/FullScreen": "ol.control.FullScreen",
          "ol/control/MousePosition": "ol.control.MousePosition",
          "ol/control/ScaleLine": "ol.control.ScaleLine",

          "ol-contextmenu": "ContextMenu",

          "ol-ext/layer/AnimatedCluster": "ol.AnimatedCluster",
          "ol-ext/control/Button": "ol.control.Button",
          "ol-ext/control/Bar": "ol.control.Bar",
          "ol-ext/control/LayerSwitcher": "ol.control.LayerSwitcher",
          "ol-ext/control/LayerSwitcherImage": "ol.control.LayerSwitcherImage",
          "ol-ext/control/PrintDialog": "ol.control.PrintDialog",
          "ol-ext/control/Swipe": "ol.control.Swipe",
          "ol-ext/control/Search": "ol.control.Search",
          "ol-ext/control/Toggle": "ol.control.Toggle",
          "ol-ext/control/VideoRecorder": "ol.control.VideoRecorder",
          "ol-ext/control/MapZone": "ol.control.MapZone",
          "ol-ext/control/Profile": "ol.control.Profile",
          "ol-ext/style/FlowLine": "ol.control.FlowLine",
          "ol-ext/interaction/SelectCluster": "ol.interaction.SelectCluster",
          "ol-ext/interaction/Transform": "ol.interaction.Transform",
          "ol-ext/featureanimation/Drop": "ol.featureAnimation.Drop",
          "ol-ext/featureanimation/Fade": "ol.featureAnimation.Fade",
          "ol-ext/featureanimation/Path": "ol.featureAnimation.Path",
          "ol-ext/featureanimation/Shake": "ol.featureAnimation.Shake",
          "ol-ext/featureanimation/Slide": "ol.featureAnimation.Slide",
          "ol-ext/featureanimation/Teleport": "ol.featureAnimation.Teleport",
          "ol-ext/featureanimation/Zoom": "ol.featureAnimation.Zoom",

          "ol/control/Zoom": "ol.control.Zoom",
          "ol/control/ZoomSlider": "ol.control.ZoomSlider",
          "ol/control/ZoomToExtent": "ol.control.ZoomToExtent",

          "ol/geom/Circle": "ol.geom.Circle",
          "ol/geom/LineString": "ol.geom.LineString",
          "ol/geom/MultiLineString": "ol.geom.MultiLineString",
          "ol/geom/MultiPoint": "ol.geom.MultiPoint",
          "ol/geom/MultiPolygon": "ol.geom.MultiPolygon",
          "ol/geom/Point": "ol.geom.Point",
          "ol/geom/Polygon": "ol.geom.Polygon",
          "ol/geom/Geometry": "ol.geom.Geometry",

          "ol/interaction": "ol.interaction",
          "ol/interaction/Link": "ol.interaction.Link",
          "ol/interaction/Draw": "ol.interaction.Draw",
          "ol/interaction/DragBox": "ol.interaction.DragBox",
          "ol/interaction/Modify": "ol.interaction.Modify",
          "ol/interaction/Pointer": "ol.interaction.Pointer",
          "ol/interaction/MouseWheelZoom": "ol.interaction.MouseWheelZoom",

          "ol/style/Style": "ol.style.Style",
          "ol/style/Circle": "ol.style.CircleStyle",
          "ol/style/Fill": "ol.style.Fill",
          "ol/style/Stroke": "ol.style.Stroke",
          "ol/style/Icon": "ol.style.Icon",
          "ol/style/Text": "ol.style.Text",

          "ol/interaction/DragRotate": "ol.interaction.DragRotate",
          "ol/interaction/DragRotateAndZoom":
            "ol.interaction.DragRotateAndZoom",
          "ol/interaction/Select": "ol.interaction.Select",
          "ol/interaction/Snap": "ol.interaction.Snap",

          "ol/renderer/webgl/VectorLayer": "ol.renderer.webgl.VectorLayer",
        },
        assetFileNames: (assetInfo) => {
          return assetInfo.name === "main.css"
            ? "styles.css"
            : assetInfo.name || "";
        },
      },
    },
  },
});

So, notes:

globals:

  • We're loading the ol module globally, so all imports need to reference ol.*
  • ol-ext adds additional Classes, so just need to rewire to ol.*
  • ol-contextmenu loads a class into global called ContextMenu. Thats probably problematic, but doesn't stop this hotfix

output

  • Added name: "Vue3OpenLayers" which goes global

lib.fileName

  • renders filenames using the entry.format style

So I believe this could be made as a separate output. Might be worth minifying the output then it might not interfere with existing users.

@d-koppenhagen
Copy link
Collaborator

Hey, would you like to send a PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants