JavaScript - Importing with or without a bundler

ESM builds with a bundler

ESM builds must be bootstrapped with their .wasm binaries to initialize. The wasm binaries can be found in their respective dist/wasm directories.

import perspective_viewer from "@finos/perspective-viewer";
import perspective from "@finos/perspective";

// TODO These paths must be provided by the bundler!
const SERVER_WASM = ... // "@finos/perspective/dist/wasm/perspective-server.wasm"
const CLIENT_WASM = ... // "@finos/perspective-viewer/dist/wasm/perspective-viewer.wasm"

await Promise.all([
    perspective.init_server(SERVER_WASM),
    perspective_viewer.init_client(CLIENT_WASM),
]);

// Now Perspective API will work!
const worker = await perspective.worker();
const viewer = document.createElement("perspective-viewer");

The exact syntax will vary slightly depending on the bundler.

Vite

import SERVER_WASM from "@finos/perspective/dist/wasm/perspective-server.wasm?url";
import CLIENT_WASM from "@finos/perspective-viewer/dist/wasm/perspective-viewer.wasm?url";

await Promise.all([
    perspective.init_server(fetch(SERVER_WASM)),
    perspective_viewer.init_client(fetch(CLIENT_WASM)),
]);

You'll also need to target esnext in your vite.config.js in order to run the build step:

import { defineConfig } from "vite";
export default defineConfig({
    build: {
        target: "esnext",
    },
});

ESBuild

import SERVER_WASM from "@finos/perspective/dist/wasm/perspective-server.wasm";
import CLIENT_WASM from "@finos/perspective-viewer/dist/wasm/perspective-viewer.wasm";

await Promise.all([
    perspective.init_server(fetch(SERVER_WASM)),
    perspective_viewer.init_client(fetch(CLIENT_WASM)),
]);

ESBuild config JSON to encode this asset as a file:

{
    // ...
    "loader": {
        // ...
        ".wasm": "file"
    }
}

Webpack

import * as SERVER_WASM from "@finos/perspective/dist/wasm/perspective-server.wasm";
import * as CLIENT_WASM from "@finos/perspective-viewer/dist/wasm/perspective-viewer.wasm";

await Promise.all([
    perspective.init_server(SERVER_WASM),
    perspective_viewer.init_client(CLIENT_WASM),
]);

Webpack config:

{
    // ...
    experiments: {
        asyncWebAssembly: true,
        syncWebAssembly: false,
    },
}

Inline builds with a bundler

import "@finos/perspective-viewer/dist/esm/perspective-viewer.inline.js";
import psp from "@finos/perspective/dist/esm/perspective.inline.js";

CDN builds

Perspective CDN builds are in ES Module format, thus to include them via a CDN they must be imported from a <script type="module">. While this will work fine downloading Perspective's assets directly as a src attribute, as you'll generally want to do something with the library its best to use an import statement:

<script type="module">
    import "https://cdn.jsdelivr.net/npm/@finos/perspective-viewer/dist/cdn/perspective-viewer.js";
    import "https://cdn.jsdelivr.net/npm/@finos/perspective-viewer-datagrid/dist/cdn/perspective-viewer-datagrid.js";
    import "https://cdn.jsdelivr.net/npm/@finos/perspective-viewer-d3fc/dist/cdn/perspective-viewer-d3fc.js";
    import perspective from "https://cdn.jsdelivr.net/npm/@finos/perspective/dist/cdn/perspective.js";

    // .. Do stuff here ..
</script>

Node.js builds

The Node.js runtime for the @finos/perspective module runs in-process by default and does not implement a child_process interface. Hence, there is no worker() method, and the module object itself directly exports the full perspective API.

const perspective = require("@finos/perspective");

In Node.js, perspective does not run in a WebWorker (as this API does not exist in Node.js), so no need to call the .worker() factory function - the perspective library exports the functions directly and run synchronously in the main process.