palantir / blueprint

A React-based UI toolkit for the web
https://blueprintjs.com/
Apache License 2.0
20.72k stars 2.18k forks source link

[FR] [BP4] Basic Deno Support #5160

Open samthecodingman opened 2 years ago

samthecodingman commented 2 years ago

Environment

Feature request

Implement early Deno support by supporting Deno's environment variable parsing methods.

Changes

The NS variable in @blueprintjs/core/common/classes.ts would need to support looking on both process.env and Deno.env for BLUEPRINT_NAMESPACE and REACT_APP_BLUEPRINT_NAMESPACE before falling back to the default. Here, I have implemented an example of this using a IIFE.

// only accessible within this file.
declare let process: { env: any };
declare let Deno: { env: { get(key: string): string | undefined } };

const NS = ((defaultNS)=>{
    if (typeof process !== "undefined")
        return process.env?.BLUEPRINT_NAMESPACE ?? process.env?.REACT_APP_BLUEPRINT_NAMESPACE ?? defaultNS;
    if (typeof Deno !== "undefined")
        return Deno.env?.get("BLUEPRINT_NAMESPACE") ?? Deno.env?.get("REACT_APP_BLUEPRINT_NAMESPACE") ?? defaultNS;
    return defaultNS;
})("bp4");

The isNodeEnv function in @blueprintjs/core/common/utils/jsUtils.ts would also need to be expanded to encompass Deno's environment variables (at this time, the major one would be ALEPH_ENV = 'development' | 'production' from alephjs/aleph.js).

// only accessible within this file, so use `Utils.isNodeEnv(env)` from the outside.
declare let process: { env: any };
declare let Deno: { env: { get(key: string): string | undefined } };

/** Returns whether `process.env.NODE_ENV`/`Deno.env.get("ALEPH_ENV")` exists and equals `env`. */
export function isNodeEnv(env: string) { // rename to isRuntimeEnv?
    return (typeof process !== "undefined" && process.env && process.env.NODE_ENV === env) ||
           (typeof Deno !== "undefined" && Deno.env && Deno.env.get("ALEPH_ENV") === env);
}

The final piece in the puzzle would be @blueprintjs/core/common/configureDom4.ts. While this makes logical sense, it seems when processed through esm.sh that dom4 is loaded synchronously right at the start of the file which rightfully fails because Deno is not a browser environment. Even skypack.dev struggles with this dynamic import (Ctrl+F "dom4"). I'm not quite sure if this is something to be explored on your side or the side of the web bundlers. Currently I work around it by reaching into the locally cached version (at ./.aleph/development/-/cdn.esm.sh/v66/@blueprintjs/core@4.0.0-rc.0/deno/core.development.js) and forcing the dom4 module to be loaded using the __require helper method generated by the web bundler. This then prevents dom4 being loaded in Deno/Aleph while it's performing its SSR steps.

adidahiya commented 2 years ago

I'm open to adding Deno support. The first two parts make sense and seem straightforward. The last part, the conditional import, has been discussed recently in https://github.com/palantir/blueprint/issues/131#issuecomment-1049980138... I haven't done a lot of investigation yet on this topic, but it seems like something the bundlers ought to provide better support for.

adidahiya commented 1 year ago

I've gotten rid of dom4 in Blueprint v5.0 on the next branch. So implementing Deno support should be simple to add at this point.