D
Deno

help

Deno, TypeScript, ESBuild, WebGL, VSCode

Ppyzaist12/22/2023
Hello! As the title suggests, I am using these technologies to create a web application: * Deno * TypeScript * ESBuild * WebGL (which uses .glsl shader files) * VSCode My goal is to have a .ts file be able to import a .glsl file as a string, and for there to be no errors or warnings about this in VSCode. This is a very common workflow for frontend development involving WebGL. My understanding is that I need to create a modules.d.ts file at the root of my project that looks like so:
declare module "*.glsl" {
const value: string;
export default value;
}
declare module "*.glsl" {
const value: string;
export default value;
}
and then have Deno use it by having deno.json have a line like so:
{
"compilerOptions": {
"types": ["modules.d.ts"]
}
}
{
"compilerOptions": {
"types": ["modules.d.ts"]
}
}
I believe that this is all that should be needed to have any .ts file be able to import any .glsl as a string like so:
import fragmentShaderSource from "./fragmentShader.glsl";
import vertexShaderSource from "./vertexShader.glsl";
import fragmentShaderSource from "./fragmentShader.glsl";
import vertexShaderSource from "./vertexShader.glsl";
It appears that this actually works with ESBuild and the glsl plugin. However, in VSCode I am getting errors on the above import lines like so: Module '"file:///<root path of my project>/fragmentShader.glsl"' has no default export So what I am doing wrong here, and how can I get VSCode to be happy?
Ppyzaist12/22/2023
Types and Type Declarations | Deno Docs
One of the design principles of Deno is no non-standard module resolution. When
Ppyzaist12/22/2023
hmmmm also when i do "deno check" i get this: error: Expected a JavaScript or TypeScript module, but identified a Unknown module. Importing these types of modules is currently not supported.
Jjavi12/22/2023
You cannot do imports like that. The reason for which you do the declare module … is because under the hood, a bundler like webpack or rollup is used. Deno doesn't have those. One alternative is to just use Deno.readFile and the like
Ppyzaist12/22/2023
Oof, that is sad
ABAltair 680b12/22/2023
Or just a .ts file with a single export
// ./f_shader.ts
export const f_glsl = `
precision lowp float;

attribute vec2 a_position; // Flat square on XY plane
attribute float a_startAngle;
attribute float a_angularVelocity;
attribute float a_rotationAxisAngle;
attribute float a_particleDistance;
attribute float a_particleAngle;
attribute float a_particleY;
uniform float u_time; // Global state
...
`
// ./f_shader.ts
export const f_glsl = `
precision lowp float;

attribute vec2 a_position; // Flat square on XY plane
attribute float a_startAngle;
attribute float a_angularVelocity;
attribute float a_rotationAxisAngle;
attribute float a_particleDistance;
attribute float a_particleAngle;
attribute float a_particleY;
uniform float u_time; // Global state
...
`
import { f_glsl } from './f_shader.ts' /* see above */
const gl = canvas.getContext("webgl");
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
// shaderSource(shader: WebGLShader, source: string): void
gl.shaderSource(fragmentShader, f_glsl);
gl.compileShader(fragmentShader);
import { f_glsl } from './f_shader.ts' /* see above */
const gl = canvas.getContext("webgl");
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
// shaderSource(shader: WebGLShader, source: string): void
gl.shaderSource(fragmentShader, f_glsl);
gl.compileShader(fragmentShader);
https://www.typescriptlang.org/play#example/typescript-with-webgl deno_esbuild will love this simple string import. https://github.com/esbuild/deno-esbuild
A deno_esbuild example from Hot-server: https://github.com/nhrones/Hot/blob/main/builder.ts usage:
import { build } from './builder.ts'
try {
build({entry: "./src/main.ts", minify: true, out: "./dist/bundle.js" })
.then(() => console.log('Built bundle.js!');
}).catch((err) => {
console.info('Build err - ', err)
})
import { build } from './builder.ts'
try {
build({entry: "./src/main.ts", minify: true, out: "./dist/bundle.js" })
.then(() => console.log('Built bundle.js!');
}).catch((err) => {
console.info('Build err - ', err)
})
Ppyzaist12/22/2023
Yeah I currently have a .ts file with a single import of a string, but there’s a few sad things about this: 1) it treats glsl code as second class rather than first class, and more tangibly 2) it doesn’t allow syntax highlighting in vs code Also Deno.readFile won’t work because this is for the front end. So I want the file contents in the bundle
ABAltair 680b12/22/2023
Have you considered WebGPU and the WebGPU Shading Language? WGSL It's now support in Deno https://deno.com/blog/v1.39
Ppyzaist12/22/2023
Hey nice! So I don’t have much experience with WebGPU but my understanding is that it gives more control at the cost of more complexity. So would def prefer WegGL
ABAltair 680b12/22/2023
Good luck. I still think you can edit GLSL with a good extension, and then just save it as text in your build step!
Ppyzaist12/30/2023
Got it. I will play around with some things then and probably post back here with what I come up with, for posterity hmm okay so im checking this out today. it appears that 1) webGPU is not widely supported yet (https://caniuse.com/webgpu) but likely will be soon and 2) even if it was, i would have the same problem with WGSL as i do with GLSL - so it doesnt really benefit me to use it but from what i am reading, this comment does not seem to be true. the import setup i did was for the typescript compiler. it is a part of typescript itself.
Ppyzaist12/30/2023
issue from a long time ago that discusses this: https://github.com/Microsoft/TypeScript/issues/2709
GitHub
Importing files other than TS modules · Issue #2709 · microsoft/Typ...
I've successfully been using SystemJS and TypeScript for a while now. I've been about to use the CommonJS syntax to easily import other TS modules, as well as other resources: var OtherModu...
AAapoAlas12/30/2023
I believe somewhat soonish you'll be able to do:
import data from "./fragmentShared.glsl" with { type: "string" };
import data from "./fragmentShared.glsl" with { type: "string" };
That will then just read the file as plaintext and include it into the module graph.
Bbartlomieju12/30/2023
Correct, we're working on these kind of imports
Ppyzaist12/31/2023
Oh that’s awesome! That would work great Is there somewhere I could follow along on that progress?
Bbartlomieju12/31/2023
GitHub
feat: Allow embedders to load custom module types by bartlomieju · ...
More generic solution than #344 and #357. It allows embedders to load any module type they want. Still some rough edges that need to be fixed. I will probably split this PR into a few more.
Ppyzaist12/31/2023
Awesome, thanks! hmmmmm okay i was going to ask why the plan is not to replicate how typescript does this as i discussed above, but i think im starting to get it. in the non-deno case, there is a loader/bundler that takes all my TS and plaintext imports and handles the actual turning it into runnable JS code. however in the deno case, TS is the native language, so it needs to be able to run the code without all this. so it cant simply say "this file will be a string" to satisfy the type system, it needs to know what particular string it will be. is that getting at the right explanation? until the new import method is available as you mentioned above, im leaning towards having a pre-build step that takes these two files im working in and generating a ts file that outputs the contents as a string. i think thatll do fine for a quick solution. and this is a small hobby project, so it doesnt need to be completely ideal
AAapoAlas12/31/2023
So basically declare module *.foo explains to the TypeScript compiler that you expect Someone (TSC doesn't care who) to convert imports pointing to imports of this style into whatever you declare in the declare declaration. Because Deno handles transforming the code, Deno needs to be the "Someone" from above doing the transformation. But now Deno is both the loader doing the transformation AND the compiler doing the type checking. It doesn't make sense to do the declare *.foo to tell Deno what the types of "*.foo" imports are PLUSA some other declaration to tell Deno that a particular import should be handled as a plaintext import. It's simpler (at least from an implementation standpoint) to only provide the way to implement as plaintext and derive the type directly based on that. (Note that this is more general than the converse as now you can import eg. JS files as plaintext as well.)
Ppyzaist12/31/2023
yeah yeah, exactly. okay that makes a ton of sense. from a user perspective, i will still say that it is unfortunate that i would have to write with { type: "string" } after every GLSL (or CSS, or HTML, or whatever plaintext file i would use) import i do, instead of specify in one place that GLSL files should always be imported in this way. for my use case this is totally fine, but just providing signal to you all for how i would anticipate larger projects would prefer to engage with this topic
Bbartlomieju12/31/2023
The approach were taking plays nicely with other in-progress tc39 proposals and is completely in-bound solution in contrast to having some auxiliary files that need to tell how certain file have to be interpreted. Sure it's a few more keystrokes but give a lot more control and allow ecosystem to unify behind a single solution (import attributes) That said, you can still use a pre build step if it fits your use case better!
Ppyzaist12/31/2023
ah got it, that adds more clarity for me! import attributes are new to me so i will look into them more. very much appreciate the responses and thoughtfulness you all take. thanks again!

Looking for more? Join the community!

Recommended Posts
Possible issue with re-export compatibility with NodeIn https://github.com/japa/runner/issues/35, I have described an issue where Deno seems to be incompMake deno.serve handler asynchronousHow can i make the Deno.serve handler asynchronous? or like make it so that it can execute asynchronWhy my place.x -= 5 not working?At this part if(moveKey.right.pressed) { finishPostion += 5 quota exceededi hit the free limit tonight and upgraded to pro 20 minutes ago— when do my sites stop erroring withDeploying WASM via Deno Deploy Github ActionsHello, I'm trying to deploy a Leptos project that serves a .wasm bundle for the frontend, and uses Get only the first records with deno kv but reversed orderedI'm using Deno KV to store articles. Generating the ID for the articles: ``` export function generaerror: Uncaught (in promise) SyntaxError: Invalid regular expression flagsAfter Updating my fresh to latest version I got following error ``` deno task start Task start deno third party module repo changeI'm the author of a third party deno module: https://deno.land/x/streamdal_protos@v0.0.126. My comDeno.serve get full path instead of only params and urlI need to get params from an url like this `http://localhost:8000/auth#token_type=Bearer&access_tokeSend custom response inside error event listenerIf I add an event listener for errors in Deno to catch anything my middleware error handler doesn't,assertThrows() limitationsassertThrows() seems to only filter on class name and message. Is there an assert function for checkLSP/VSCode stops workingI'm having issues in my fresh project time to time it stops working and I have to restart it or vscoCan the listeners for messages from Deno Deploy Queues timeout?Can the listeners for messages from Deno Deploy Queues timeout like Vercel serverless functions? AreHow to get the path to the compiled binary?`import.meta.url` and `Deno.mainModule` are used to get the current script, but after a binary is crHow to get `require.main.filename` like Node as DenoI am making a module to be published on deno.land/x. I want the user to put a file describing the coChange Web Worker Permissions after the Worker StartedHello, I was wondering if it is possible to change/update the permissions of a web worker after it Missing transpiled source codeI'm trying to generate coverage for my project and I'm getting the following: ``` deno task coverageTrouble validating a requestHi there! I'm trying to validate a Discord HTTP request, but I don't know how to do it (https://discHow to deploy to Deno Deploy from a Github repository's subdirectory?I read somewhere that you can deploy from a subdirectory, but I can't find any documentation on how Convert to exeI have made my Javascript program into an exe with deno: https://docs.deno.com/runtime/manual/tools/