mndeveci
mndeveci13mo ago

Bundling a CLI written in JS with Deno

Hi team, Thanks for writing this excellent blog-post (and video) about rolling your own JS runtime with your application using deno_core crate. I am trying to wrap a CLI tool with that approach, however I am hitting different walls when I try to get things working. First of all, I can run this CLI by using Deno runtime directly. I can run deno run npm:{package-name} and it just works. However when I try to use your approach from the blogpost, I am hitting different walls; - If I provide npm:{package-name} in my JS file directly, it says it can't resolve the npm: links (I suppose I need to add more resolvers, but I couldn't find one from the crate documentation.) - If I install all dependencies in a local folder directly, and if I try to run this again, I am getting errors when a particular JS file tries to reference others from node_modules folder (Error: Relative import path "..." not prefixed with / or ./ or ../ from) - If I use esbuild to bundle everything into single JS file, it passes all of the first issues, however I am now hitting problems with core modules like fs or url since esbuild imports them with require("url"), which I believe not compatible with Deno. If I update those imports with the ones that you provided with following import statement import * as uri from "https://deno.land/std@0.173.0/node/url.ts"; I am getting following error: Error: Provided module specifier "https://deno.land/std@0.173.0/node/url.ts" is not a file URL. Can you help me what will be the best approach here and how can I resolve my problems above? Appreciate for your responses 🙏
Deno Blog
Roll your own JavaScript runtime, pt. 2
We'll implement fetch, read command line arguments, and add native support for TypeScript and TSX.
2 Replies
Deno AI Helper
Deno AI Helper13mo ago
Hello there! 🦕 It sounds like you're working on an interesting project, and I'm here to help you navigate through the issues you're encountering. Let's address each of your concerns step by step: 1. Resolving npm: links in your custom runtime: The npm: specifier is a feature specific to Deno that allows you to run npm packages directly. When you're building your own runtime using deno_core, you won't have this feature out of the box. The documentation doesn't provide a direct solution for adding npm: resolution to your custom runtime. You might need to implement a custom resolution logic that mimics Deno's behavior or use a third-party library that can handle npm package resolution. 2. Relative import paths from node_modules: The error you're seeing is because Deno expects imports to be fully specified with either a relative path (./ or ../) or an absolute path (/). When you're dealing with a Node.js-style node_modules directory, this can be problematic. One way to address this is by using import maps to map the bare specifiers to actual file URLs. However, this can become quite complex if you have many dependencies. 3. Bundling with esbuild and core module issues: The deno bundle command has been deprecated, as mentioned in the documentation, and it's recommended to use deno_emit, esbuild, or rollup instead. However, when you bundle with esbuild, it uses Node.js-style require statements, which are not compatible with Deno. To use Node.js core modules in Deno, you need to import them with the node: prefix, as described in the documentation. For example, import fs from "node:fs";. Regarding the error you're getting with the url module, it seems like you're trying to import a Deno standard library module
Deno AI Helper
Deno AI Helper13mo ago
meant to provide Node compatibility. However, the error message suggests that the specifier is not being treated as a file URL, which might be due to how your custom runtime is handling module resolution. Given these challenges, here are some potential approaches you could take: - Use Deno's Node compatibility layer: If you're running your CLI tool with Deno directly, you can leverage Deno's built-in Node compatibility features. Make sure to use the node: prefix for core modules and adjust your code to align with Deno's import syntax. - Custom module resolution: If you're building a custom runtime, you may need to implement a module resolution system that can handle npm: specifiers and Node.js-style module resolution. This could involve a significant amount of work and understanding of both Deno's and Node's module systems. - Bundle with Deno compatibility in mind: When bundling your application, configure esbuild or another bund