Skip to content

@bitbybit-dev/occt version 1.0.0-rc.1 no longer builds for browser #123

@adamscybot

Description

@adamscybot

I am a newcomer to this (brilliant!) project.

I first started using @bitbybit-dev/occt at version 0.21.1 which I was able to build and run in the browser, but only if I enabled skipLibCheck: true because of some missing types coming from the lib.

When investigating that problem (skipLibCheck: true is a pet peave of mine), I noticed the activity here and tried 1.0.0-rc.1. The good news is the type errors are all gone and I can turn skipLibCheck off again 🎉.

The bad news is that it won't compile for the browser. I am using bun bundler configured for a browser target which is perhaps quite cutting edge and possibly a factor. But after digging around to find the cause, I beleive it's not the issue here and this is a problem for bundlers generally.

Bun build error output:

1 | ODE){const{createRequire}=await import("module");var require=createRequire(import.meta.url)}var arguments_=[];var thisPr
                                                                                                                                                                                                                                                                                                                                                         ^
error: Browser build cannot import() Node.js builtin: "module". To use Node.js builtins, set target to 'node' or 'bun'
    at ./node_modules/.bun/@bitbybit-dev+occt@1.0.0-rc.1/node_modules/@bitbybit-dev/occt/bitbybit-dev-occt/bitbybit-dev-occt.js:1:342

The problem seems to be it is trying to conditionally import() stuff from node, guarded with runtime checks to detect node.

The issue with this is bundlers can't universally make that choice statically on complex conditions like this to know to eliminate the "dead code" and therefore it has to assume the guard could evaluate to true, and therefore will attempt to create a chunk for nodes stdlib module package in order to make it available for potential dynamic import later in the runtime -- which obviously won't work in the browser anwyays hence the build-time explosion.

I can do some hackery in my own bundler config using build time overrides of the strings used inside the if conditions that wrap this import, in order to rewrite them them to a statically known value of simply an inline false, which would prevent the bundler from trying to do this (since that really can be statically resolved and so it would eliminate it from the graph entirely via dead code elimination). But that is indeed a hack and I beleive not one that needs to exist...

The canonical and correct solution to this problem today is to provide separate entry points in package.json under the exports object for node/browser etc as detailed here. Bundlers targetting browsers will opt to load the browser entry point, which can then be selective about what it imports and passes along to some platform-agnostic shared common "entry point" just underneath.

E.g. the node entry point would export a thin createBitbybitDevOcct wrapper which calls import('module') (though tbh you no longer need dynamic import here anymore, you can just statically import module from 'node:module') and pass the result of that or something abstracted on top of that down to the "common" file createBitbybitDevOcct underneath, via function params.

The browser entry point would import and then pass down different things/do what it neesd to do -- without needing any import statements to node only packages, dynamic or otherwise, within it.

If the common shared file needs the types of those things still you can use a type import import { type thingyouneed } from 'whatever' which is stripped by bundlers/ts compilers before anything gets to the linking step.

Sorry if you already knew about this. I realise im using an RC right now 😀.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions