domoritz / clingo-wasm

Clingo on the web
https://domoritz.github.io/clingo-wasm
Apache License 2.0
32 stars 2 forks source link

"Automatic publicPath is not supported in this browser" in Sveltekit #287

Open see-mike-out opened 1 year ago

see-mike-out commented 1 year ago

Hi authors,

I am experiencing this problem when I was trying to run `clingo-wasm' in a Sveltekit project.

app.js:22 Error: Automatic publicPath is not supported in this browser
    at clingo.web.js:1:59874
    at clingo.web.js:1:60014
    at clingo.web.js:1:60025
    at clingo.web.js:1:81
    at node_modules/clingo-wasm/dist/clingo.web.js (clingo.web.js:1:192)
    at __require (chunk-RSJERJUL.js?v=3631112d:3:50)
    at clingo.web.js:1:60030

For replication,

My setup was: node v18.12.1 / Sveltekit latest (1.5.0) / MacOS Monterey (12.3) / Apple M1 Pro (arm64) / Chrome 113.0.5672.92 (had the same issue with Safari 15.4 (17613.1.17.1.6)

I used the Sveltekit's base example (the counter template, see below for the settings)

┌  Welcome to SvelteKit!
│
◇  Which Svelte app template?
│  SvelteKit demo app
│
◇  Add type checking with TypeScript?
│  Yes, using JavaScript with JSDoc comments
│
◇  Select additional options (use arrow keys/space bar)
│  Add ESLint for code linting, Add Prettier for code formatting
│
└  Your project is ready!

Then, I made a file clingo-test.js under ./src/routes folder.

import * as clingo from "clingo-wasm";

export function test() {
  clingo.run("a. b:- a.").then(console.log);
}

and then added a few lines in ./src/routes/+page.js.

<script>
    import Counter from './Counter.svelte';
    import welcome from '$lib/images/svelte-welcome.webp';
    import welcome_fallback from '$lib/images/svelte-welcome.png';
    import { test } from './clingo-test'; // added line
    test(); // added line
</script>

Then, I got the above error.

I looked up from the Vite's documentation, so added a few lines in ./vite.config.js.

import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import wasm from "vite-plugin-wasm";
import topLevelAwait from "vite-plugin-top-level-await";

export default defineConfig({
    plugins: [
        sveltekit(),
        wasm(), // added
        topLevelAwait(), //added
    ],
    worker: { // added
        plugins: [
            wasm(),
            topLevelAwait()
        ]
    }
});

But this didn't resolve the problme.

Any idea about how to deal with this?

Thanks!

see-mike-out commented 1 year ago

Since the vanilla approach worked, I just copied clingo.web.js and tried to import it. (built using the below webpack config).

 {
    mode: "production",
    target: "web",
    entry: "./src/index.web.ts",
    module: {
      rules: [
        {
          test: /\.worker\.ts$/,
          loader: "worker-loader",
          options: { inline: "fallback" },
        },
        {
          test: /clingo\.js$/,
          loader: "exports-loader",
          options: {
            exports: "Module",
          },
        },
        {
          test: /\.wasm$/,
          type:
            "javascript/auto" /** this disabled webpacks default handling of wasm */,
          use: [
            {
              loader: "file-loader",
              options: {
                publicPath: "/dist/",
                name: "clingo.wasm",
              },
            },
          ],
        },
        {
          test: /\.ts$/,
          use: "ts-loader",
          exclude: /node_modules/,
        },
      ],
    },
    resolve: {
      extensions: [".tsx", ".ts", ".js"],
    },
    output: {
      filename: "clingo.web.js",
      path: path.resolve(__dirname, "./dist"),
      library: "clingo",
      libraryTarget: "umd",
      globalObject: 'this', // modified
    },
  },

However, it shows the same error on console.

see-mike-out commented 1 year ago

💡Some workaround💡

  1. Download this repo, and install requirements (I used npm install).
  2. Open webpack.config.js
  3. Add publicPath: '' in output property of clingo.web.js export (line 46-ish).
  4. Change the libraryTarget from umd to var in the same output property. The output object should look like this:
    output: {
      filename: "clingo.web.js",
      path: path.resolve(__dirname, "./dist"),
      publicPath: "",
      library: "clingo",
      libraryTarget: "var"
    }
  5. Build the library npm run build.
  6. Go to ./dist directory and copy the clingo.web.js file and paste into your SvelteKit application directory (somewhere under src directory is fine). I named it clingo.js but the name doesn't really matter.
  7. (Optional) if you want to host the wasm file as well, save it under static folder (src/lib does not work for this case).
  8. For loading, create a new file (I named it clingo-runner.js) somewhere under src directory.
    
    import { browser } from '$app/environment';

async function loadClingo() { let clingoLib = await import('{path}/clingo.js'); return clingoLib.clingo; }

export async function importClingo() { if (browser) { // to make sure it does not run in a node setting let clingo = await loadClingo(); await clingo.init("{http-or-https url path to your static files}/clingo.wasm"); // clingo.init("https://cdn.jsdelivr.net/npm/clingo-wasm/dist/clingo.wasm"); // if you want to use CDN return clingo; } }

9. In your `.svelte` file or other `.js` file under the `src directory`, run like this:
```{js}
<script>
...
    import { importClingo } from '../../controls/clingo-runner';

    importClingo().then((clingo) => {
        if (clingo) { // optional (just to make sure)
            clingo.run("a(A) :- ab(A). ab(c).").then(console.log);
        }
    });
...
</script>
  1. Console shows: image