Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESM Support #163

Open
shishkin opened this issue Jan 20, 2023 · 6 comments
Open

ESM Support #163

shishkin opened this issue Jan 20, 2023 · 6 comments

Comments

@shishkin
Copy link

Hi! I'm trying to use this package as a transitive dependency in Deno via esm.sh. Unfortunately sanitize is not a proper named export. I can't change the way this package is imported (e.g. import * as dompurify from "...") because it's a transitive dependency. What do you think about providing support for ESM natively?

I see that isomorphic-unfetch uses Node's conditional exports and provides separate browser, .cjs and .mjs implementations. Maybe this could be done from a single source file and a tool like rollup to cross-build .cjs and .mjs formats.

@kkomelin
Copy link
Owner

kkomelin commented Jan 21, 2023

Hi @shishkin ,

Thank you for your suggestion. It makes sense.

The isomorhic-unfetch uses microbundle for this purpose, like this:

// package.json
{
    "build": "microbundle src/index.mjs -f cjs,esm,umd && microbundle polyfill/polyfill.mjs -o polyfill/index.js -f cjs --no-sourcemap"
}

However, I'm not sure if the package will work for Deno anyway because of the JSDom dependency which may not work for everywhere.

Anyway, would you like to help with this improvement?

@shishkin
Copy link
Author

I gave it a try but ultimately wasn't able to figure out dynamic imports in the isomorphic ESM case.

After looking at isomorhic-unfetch again, it seems it benefits from the unfetch default export being an async function returning a Promise. That makes it easy to call a dynamic import and chain the promises for a result.

In case of DOMPurify, the default export is an object with functions. And I wasn't able to construct a static export from dynamic imports as I wasn't able to unwrap promises without top level await. And top level await seems only supported on specific targets, so won't cover default ESM case.

Please let me know if I have missed something.

@kkomelin
Copy link
Owner

Thank you @shishkin for experimenting with this. If adding new formats doesn't help, there is no much I can help with.
Let's keep this issue open in case anyone else comes up with a solution.

@ghiscoding
Copy link

ghiscoding commented Apr 18, 2024

I also would like to know if ESM will be supported in the near future? DOMPurify now as Rollup build exposed with "module": "./dist/purify.es.mjs" for its ESM build and isomorphic-dompurify doesn't have any module export. Also taking a look at the code in here, there seem to be an overuse of require() which is CJS only code. I think the code could be migrated to something like what is shown below, which is something I've used in the past to make Rollup/Jest happy with CJS while still getting ESM export when possible.

The import patch below helps for my unit tests to work in Jest (because Jest is still CJS, so default will be used) while it also work as ESM (import without default for ESM)

import * as DOMPurify_ from 'dompurify';
const DOMPurify = ((DOMPurify_ as any)?.['default'] ?? DOMPurify_); // patch for rollup

async function initDOMPurifyWithJSDOM() {
  const { JSDOM } = await import('jsdom');
  const { window } = new JSDOM('<!DOCTYPE html>');
  return DOMPurify(window);
}

function resolveDOMPurify() {
  const isClientSide = typeof window !== 'undefined';
  return isClientSide ? DOMPurify : initDOMPurifyWithJSDOM();
}

To be honest, I didn't try the code yet with this project but I'm wondering if this approach would be acceptable to get ESM exports? The only downside is the JSDOM async import which might be a problem. Basically, this project is the only left as CJS only for my stack to be converted to be fully ESM, it would be great if isomorphic-dompurify could also export ESM builds but it cannot do that until all require() are removed completely

@ZaDarkSide
Copy link

This also prevents this package to work correctly in SvelteKit with SSR.

@EmuMan
Copy link

EmuMan commented Sep 11, 2024

Not really a solution but as a temporary fix if anyone else is having this problem in SvelteKit I've managed to get it working with SSR by installing it as a dependency rather than a devDependency and including the following lines in vite.config.ts:

export default defineConfig({
    /* snip */
    build: {
        rollupOptions: {
            external: [
                'isomorphic-dompurify',
            ]
        }
    }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants