typescriptvitesveltekites6-modulesopenpgp.js

Cannot use OpenPGP.js V6 in the browser: JavaScript module + TypeScript + Vite + SvelteKit


The issue

I am trying to use OpenPGP.js V6 in a webapp made with SvelteKit, TypeScript and Vite.
OpenPGP.js V6 is now declared as a module, and I cannot find a way to import it correctly with my current stack.

What I have tried:

Import it as an ES6 module

I first tried to import openpgp in my Svelte component as suggested by the doc:

<script lang="ts">
    import * as openpgp from "openpgp";
</script>
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>

<p>{ JSON.stringify(openpgp.config) }</p>

I result in a browser error:

TypeError: import_module.createRequire is not a function
    <anonymous> openpgp.mjs:1767

Use the lightweight modules

<script lang="ts">
    import * as openpgp from "openpgp/lightweight";
</script>
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>

<p>{ JSON.stringify(openpgp.config) }</p>

This results in a Vite error:

[plugin:vite:import-analysis] Missing "./" specifier in "openpgp" package

Import the .mjs file directly

It seems that by default, importing from "openpgp" actually imports the node modules. So I tried to import the browser module directly:

<script lang="ts">
    import * as openpgp from "../../node_modules/openpgp/dist/openpgp.mjs";
</script>
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>

<p>{ JSON.stringify(openpgp.config) }</p>

This works in the browser but gives a TypeScript error:

Could not find a declaration file for module '../../node_modules/openpgp/dist/openpgp.mjs'. '/.../test-app/node_modules/openpgp/dist/openpgp.mjs' implicitly has an 'any' type.ts(7016)

I could //@ts-ignore it of course, but it would remove most of the benefits of using TypeScript.

The context

The issue can be reproduced by creating a minimal SvelteKit app (npx sv create my-app with the SvelteKit minimal template).

package.json (please note that I also installed @openpgp/web-stream-tools as the doc suggests):

{
    "name": "test-app",
    "version": "0.0.1",
    "type": "module",
    "scripts": {
        "dev": "vite dev",
        "build": "vite build",
        "preview": "vite preview",
        "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
        "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
    },
    "devDependencies": {
        "@openpgp/web-stream-tools": "^0.1.3",
        "@sveltejs/adapter-auto": "^3.0.0",
        "@sveltejs/kit": "^2.0.0",
        "@sveltejs/vite-plugin-svelte": "^4.0.0",
        "@types/node": "^22.9.0",
        "svelte": "^5.0.0",
        "svelte-check": "^4.0.0",
        "typescript": "^5.0.0",
        "vite": "^5.0.3"
    },
    "dependencies": {
        "openpgp": "^6.0.0"
    }
}

vite.config.ts:

import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';

export default defineConfig({
    plugins: [sveltekit()]
});

svelte.config.js:

import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    preprocess: vitePreprocess(),

    kit: {
        adapter: adapter()
    }
};

export default config;

tsconfig.json:

{
    "extends": "./.svelte-kit/tsconfig.json",
    "compilerOptions": {
        "allowJs": true,
        "checkJs": true,
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "skipLibCheck": true,
        "sourceMap": true,
        "strict": true,
        "moduleResolution": "bundler"
    }
}

Solution

  • So in the end, it was an issue with OpenPGP.js v6.0.0. The bug was fixed on November 21: https://github.com/openpgpjs/openpgpjs/commit/f75447afaa681dc6fa7448a4bf82c63b10265b46