open-scd icon indicating copy to clipboard operation
open-scd copied to clipboard

OpenSCD as custom element published on npm

Open trusz opened this issue 10 months ago • 6 comments

PR:

  • https://github.com/openscd/open-scd/pull/1485

trusz avatar Mar 28 '24 21:03 trusz

We have a few global things going on in our index.html

Settings

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="Description"
    content="Open Substation Communication Designer is a bottom-up system configuration tool for projects described using IEC 61850-6 Edition 2 or greater.">
<base href="/">

External Stylesheets

  <!-- Original URL from Google: https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@300&family=Roboto:wght@300;400;500&display=swap -->
  <link href="public/google/fonts/roboto-v27.css" rel="stylesheet">
  <link href="public/google/fonts/roboto-mono-v13.css" rel="stylesheet">
  <!-- Original URL from Google: https://fonts.googleapis.com/css?family=Material+Icons+Outlined&display=block -->
  <link href="public/google/icons/material-icons-outlined.css" rel="stylesheet">
  <link href="public/css/normalize.css" rel="stylesheet">

Favicons

  <link rel="manifest" href="manifest.json">
  <link rel="icon" type="image/png" sizes="16x16" href="public/favicon-16x16.png">
  <link rel="icon" type="image/png" sizes="32x32" href="public/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="192x192" href="public/icon-192x192.png">

Protection of Duplicate Custom Tags

<script>
const _customElementsDefine = window.customElements.define;
window.customElements.define = (name, cl, conf) => {
  if (!customElements.get(name)) {
    _customElementsDefine.call(window.customElements, name, cl, conf);
   }
};
</script>

Registering Services Workers

<script>
  if ('serviceWorker' in navigator)
    navigator.serviceWorker.register('/sw.js');
</script>

Prevention of Data/Work Loss on Closing OpenSCD

  <script>
    const openScd = document.querySelector("open-scd");
    addEventListener("beforeunload", e => {
      if (openScd && openScd.doc) {
        e.preventDefault();
        return e.returnValue = "Are you sure you want to exit?";
      }
    });
  </script>

All these things still need to work when we use OpenSCD as a single custom element. The nice thing is that, the elements does not necessarily need to be in the <head>. We can put them into a wrapper element that behaves like the index.html. However this element would scope everything into its own shadow DOM. For that we can create a light DOM element by using the createRenderRoot function:

  protected createRenderRoot(): Element | ShadowRoot {
    return this;
  }

This opts out a lot of custom element features but in this wrapper we don't need anything.

Our index.html becomes a really bare bones structure

<!doctype html>
<html lang="en">
  <head>
  </head>

  <body>
    <open-scd-wrapper></open-scd-wrapper>
    <script type="module" src="./src/open-scd-wrapper.js"></script>
  </body>
</html>

trusz avatar Apr 02 '24 10:04 trusz

I've managed to setup a build that bundles a big chunk of code into a single file with esbuild:

esbuild --bundle --minify --sourcemap --target=es2020\
        --platform=browser --format=esm --outdir=build src/open-scd-wrapper.ts

this works if I run npm run build before and I use the above mentioned index.html npm run build copies over assets, each file compiled to the src folder _snowpack files and node_modules and a few more things. Unfortunately these things are needed.

We could deploy this as a package maybe or try to figure out how to bundle everything into a smaller package

trusz avatar Apr 02 '24 20:04 trusz

I have tried to do it with Vite, but it does not like dynamic imports, even with plugins it does not compile something that is not referenced so OpenSCD could not load the plugins. There might be some configurations with which I could force vite to compile every file, but I did not find a solution in reasonable time.

Next, I will try to publish the whole build to npm but I think everything it will try to load from the public will fail.

trusz avatar Apr 02 '24 21:04 trusz

image

Publishing the whole build folder works, but the assets are not loading through unkpg.com, but could load if deployed to github pages

trusz avatar Apr 02 '24 21:04 trusz

Deploying to GitHub Pages worked for the plugins. Or at least they load. image

However, the assets are not yet correct. I think I would bundle every asset that we need so you don't have to depend on some setup or fix location for them.

What does not work is the suppression of duplicate custom tags image

I also got this "undefined entity" error image

and the plugins don't seem to work either image

trusz avatar Apr 03 '24 08:04 trusz

After a talk with the team we agreed on that distributions take care of:

  • service workers
  • bundling of favicons
  • plugins and their locaion

Each plugin will have its own package and there will be an essential plugin package that contains the official essential plugins:

  • #1492
  • #1493

trusz avatar Apr 03 '24 18:04 trusz