npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

swipl-wasm

v7.0.5

Published

SWI-Prolog WebAssembly build as an NPM package. Please see this page for ongoing progress and information: <https://swi-prolog.discourse.group/t/swi-prolog-in-the-browser-using-wasm/5650>

Readme

swipl-wasm

SWI-Prolog WebAssembly build as an NPM package. Please see this page for ongoing progress and information: https://swi-prolog.discourse.group/t/swi-prolog-in-the-browser-using-wasm/5650

Quickly Getting Started

The easiest way to get started is by importing swipl-wasm into your npm project. It can be imported for both Node.js and browser builds as follows:

script.mjs

import SWIPL from "swipl-wasm";

async function main() {
  const swipl = await SWIPL({ arguments: ["-q"] });
  console.log(swipl.prolog.query("member(X, [a, b, c]).").once().X);
}

main();

For those who have not done this before, you will first need to install Node.js and npm. After doing this, you can make a new project as follows:

# Make the project directory
mkdir my-swipl-project && cd ./my-swipl-project
# Initialise the project
npm init
# Install swipl-wasm
npm i swipl-wasm

After this, place the above code in script.mjs in the root of your directory and run node script.mjs to execute the script.

Usage

In browser:

<div id="solution"></div>
<script src="/dist/swipl/swipl-web.js"></script>
<script>
  (async () => {
    const swipl = await SWIPL({
      arguments: ["-q"],
      locateFile: (path) => {
        return `/dist/swipl/${path}`;
      },
    });
    const query = "member(X, [a, b, c]).";
    const solutionElement = document.getElementById("solution");
    const firstSolution = swipl.prolog.query(query).once().X;
    solutionElement.textContent = firstSolution;
  })();
</script>

The function locateFile will help the browser find the necessary files (swipl-web.wasm and swipl-web.data). In this case, the files should be served along with swipl-web.js under the /dist/swipl directory in the web server.

You can run this example by executing npm run test:serve-http and visiting http://localhost:8080/examples/browser.html.

In Node.js:

const SWIPL = require("swipl-wasm");

const swipl = await SWIPL({ arguments: ["-q"] });
console.log(swipl.prolog.query("member(X, [a, b, c]).").once().X);

You can run this example with node examples/run-on-node.js.

Using Single-File Bundle

The swipl-wasm package also comes with a single-file bundle. This does not require distributing the .data and .wasm files, which are now embedded into the .js file instead.

<div id="solution"></div>
<script src="/dist/swipl/swipl-bundle.js"></script>
<script>
  (async () => {
    const swipl = await SWIPL({ arguments: ["-q"] });
    const query = "member(X, [a, b, c]).";
    const solutionElement = document.getElementById("solution");
    const firstSolution = swipl.prolog.query(query).once().X;
    solutionElement.textContent = firstSolution;
  })();
</script>

Generating an Image

Often you will want to bundle a pre-built image of your Prolog file. The easiest way to do this is using the swipl-generate command to generate the image. For example, in ./examples/generation, the script npx swipl-generate ./max.pl ./dist/max.ts will generate a file ./dist/max.ts which contains the image of ./max.pl. This file can then be imported into your project and used as follows:

import SWIPL from './max';

async function main() {
  const Module = await SWIPL();
  const res = Module.prolog.query('max(1, 2, 3).');
  console.log(res.next())
}

main();

Note that this procedure generates a file which imports directly from swipl-wasm/dist/loadImageDefault, so make sure that swipl-wasm is a direct dependency in your project rather than a dev dependency.

To generate the image data without it being pre-loaded into SWIPL, use the --image-only flag.

Running JavaScript from Prolog

This uses eval:

swipl.prolog
  .query("js_run_script(Script)", {
    Script: `console.log('hello')`,
  })
  .once();

Using with Webpack

Webpack is a JavaScript and resources bundler for large-scale frontend projects.

There is an example Webpack project in examples/webpack. It uses Asset Modules to "load" necessary .data and .wasm files. The location of these files is then fed to locateFile (see above).

The package swipl-wasm is linked into the example. In an actual project, you would declare swipl-wasm as a normal dependency.

To start the example:

cd examples/webpack
npm install
npm run build
npm run server

Then visit http://127.0.0.1:8080. You should see the message "Hello world from Prolog".

Webpack Configuration for Browser Builds

When bundling swipl-wasm with Webpack for the browser, the underlying Emscripten-generated code may import Node.js built-in modules using the node: scheme (e.g. node:fs, node:crypto). Webpack does not handle the node: scheme by default and will produce errors like:

Module build failed: UnhandledSchemeError: Reading from "node:fs" is not handled by plugins (Unhandled scheme).

To fix this, add the following to your webpack.config.js:

const { NormalModuleReplacementPlugin } = require('webpack');

module.exports = {
  // ...your existing config
  resolve: {
    fallback: {
      path: false,
      fs: false,
      crypto: false,
      perf_hooks: false,
    },
  },
  plugins: [
    new NormalModuleReplacementPlugin(/^node:/, (resource) => {
      resource.request = resource.request.replace(/^node:/, '');
    }),
  ],
};

The NormalModuleReplacementPlugin strips the node: prefix so that the imports are resolved by the resolve.fallback entries, which map them to false (i.e. empty modules) since they are not needed in the browser.

Browser Builds

For convenience, we provide deployed bundled versions of SWI-Prolog on GitHub Pages which can be directly used in an HTML document.

There is a bundled version for each release, which can be found at the URL:

https://SWI-Prolog.github.io/npm-swipl-wasm/vMajor/vMinor/vPatch/index.js

For instance, v3.3.0 has the URL https://SWI-Prolog.github.io/npm-swipl-wasm/3/3/0/index.js. We also have shortcuts for:

  • the latest version https://SWI-Prolog.github.io/npm-swipl-wasm/latest/index.js,
  • the latest of each major version https://SWI-Prolog.github.io/npm-swipl-wasm/vMajor/latest/index.js, and
  • the latest of each minor version https://SWI-Prolog.github.io/npm-swipl-wasm/vMajor/vMinor/latest/index.js

Available versions can be browsed at https://github.com/SWI-Prolog/npm-swipl-wasm/tree/pages.

With this approach, the following script will work:

<div id="solution"></div>
<script src="https://SWI-Prolog.github.io/npm-swipl-wasm/3/3/0/index.js"></script>
<script>
  (async () => {
    const swipl = await SWIPL({ arguments: ["-q"] });
    const query = "member(X, [a, b, c]).";
    const solutionElement = document.getElementById("solution");
    const firstSolution = swipl.prolog.query(query).once().X;
    solutionElement.textContent = firstSolution;
  })();
</script>

Dynamic imports are also available with the dynamic-import.js import name and can be used as follows:

<div id="solution"></div>
<script>
  (async () => {
    const { SWIPL } = await import("https://SWI-Prolog.github.io/npm-swipl-wasm/3/3/0/dynamic-import.js");
    const swipl = await SWIPL({ arguments: ["-q"] });
    const query = "member(X, [a, b, c]).";
    const solutionElement = document.getElementById("solution");
    const firstSolution = swipl.prolog.query(query).once().X;
    solutionElement.textContent = firstSolution;
  })();
</script>

Build

The package can be built using npm. Please use npm to add new dependencies and update the package-lock.json file. The SWI-Prolog WebAssembly version is currently built inside Docker with Emscripten.

Serving Files

When self-hosting the bundled files, ensure your server includes charset=utf-8 in the Content-Type header for JavaScript files:

Content-Type: text/javascript; charset=utf-8

Without the charset, WASM streaming instantiation may fail in headless browsers with errors like:

  • Firefox: CompileError: wasm validation error: at offset 642: byte size mismatch in type section
  • Chromium: CompileError: WebAssembly.instantiate(): section was shorter than expected size

Most static file servers (e.g., express.static()) set this automatically, but custom streaming handlers using createReadStream().pipe(res) may not.

Development

To develop with this package, clone the repository and run:

# Install dependencies
npm ci
# Build the WebAssembly
npm run build
# Run tests
npm t

Note: You need Docker and Node 16 or higher to be installed to build the package.

Versioning

The package uses its own versioning scheme using semver. It is detached from the versioning of SWI-Prolog itself.

To get the underlying SWI-Prolog version:

const swipl = await SWIPL({ arguments: ["-q"] });
const version = swipl.prolog
  .query("current_prolog_flag(version, Version)")
  .once().Version;

The version is returned as integer 10000 × Major + 100 × Minor + Patch.

License

This package uses the same license as SWI-Prolog (BSD-2-Clause): https://github.com/SWI-Prolog/swipl-devel/blob/master/LICENSE