Has anyone gotten this to work in TypeScript? I have tried the recommended code above, with some adjustments, and the exporter still cannot find Blob. I think I’m missing something. Thanks!
So, I have my tsconfig set to use DOM apis (eventhough this is a node application)
{
"compilerOptions": {
"strict": true,
"lib": ["ESNext", "DOM"],
"target": "ES2018",
"moduleResolution": "node",
"outDir": "./dist",
"resolveJsonModule": true,
"declaration": true,
"sourceMap": true,
"removeComments": false,
"module": "ESNext",
"noEmitOnError": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
This makes intellisense work when inspecting the globalThis
object. The following does not given any errors. I placed this code in a file named polyfills.ts
for clarity.
// polyfills.ts
impoty * as THREE from 'three';
// createElement, Blob, and FileReader already exist?
globalThis.Blob = Blob;
globalThis.FileReader = FileReader;
globalThis.THREE = THREE;
The actuall application looks something similar to the code below. The problem is that I consitently get the ReferenceError: Blob is not defined
error.
// index.ts
import "polyfills.ts";
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';
// Create a mesh
// const mesh: THREE.Mesh = ...
const gltfExporter = new GLTFExporter();
gltfExporter.parse(
mesh,
(gltf) => {
// Do something
},
(error) => {
// Handle error
}
);
UPDATE
I figured out what I was doing wrong (of course after asking a question). The DOM
entry in tsconfig
made me think that the entries were present, but they werent. I needed to remove that first before attempting to declare global
. Once I got rid of it, I surprisingly had no problems overwriting the global object. What I ended with is shown below. For anyone referencing this later, make sure to import the polyfills file before performing the export.
/* eslint-disable no-var */
// polyfills.ts
import * as THREE from "three";
import { Canvas } from "canvas";
import { Blob as mockBlob, FileReader as mockFR } from "vblob";
declare global {
var Blob: typeof mockBlob;
var FileReader: typeof mockFR;
var document: {
createElement(nodeName: string): Canvas;
};
}
// Patch global scope to imitate browser environment.
globalThis.Blob = mockBlob;
globalThis.FileReader = mockFR;
globalThis.THREE = THREE;
globalThis.document = {
createElement: (nodeName: string): Canvas => {
if (nodeName !== "canvas")
throw new Error(`Cannot create node ${nodeName}`);
const canvas = new Canvas(256, 256);
// This isn't working — currently need to avoid toBlob(), so export to embedded .gltf not .glb.
// canvas.toBlob = function () {
// return new Blob([this.toBuffer()]);
// };
return canvas;
},
};
export {};