jsr icon indicating copy to clipboard operation
jsr copied to clipboard

What is the equivalent of npm link to develop locally?

Open trufa opened this issue 1 year ago • 7 comments

I managed to get my package published and I manage to install and run it from my next.js project.

What I don't understand is what is the equivalent of npm link to be able to develop and test locally my package and see how it's working on my next.js project without having to publish the changes.

Thank you very much, very impressed by the ease of use so far!

trufa avatar May 28 '24 00:05 trufa

This is my single biggest concern when considering using JSR (or Deno) more. I need to be able tweak my application's dependencies locally in their original source form and run my application with the modifications. I need to do this when debugging issues with third-party dependencies, and also when developing my own libraries that are used by my application. I especially need to do this when authoring a library that's primarily meant to be used in any non-Deno environment like Node, browsers, or Cloudflare because not all of those environments+tooling can directly use Deno-like Typescript code that contains imports with the ".ts" extension and "jsr:" specifiers.

With a Node(/webpack/Next.js) application and NPM dependencies, it's very easy and standard: I clone the dependency's repo to my computer, run npm install && npm link and maybe some other build command in its folder, and then run npm link DEPNAME in my application's folder. Then I can edit the code in the dependency's folder, maybe re-run a build command there, and then re-run my application with the changes.

With a Deno application and deno.land dependencies, it's also very easy: I can clone my dependency's repo to my computer, and then change my deno.json so the dependency is loaded from that local folder. *(I can also use deno vendor which copies the dependency .ts source files into a vendor directory in my application directory. If I want to work on the dependency and commit my work to it, this is not very convenient because I have to edit it outside of its repo, but it is good enough for throwaway debugging work.)

With a Deno application and JSR dependencies, it's not clear how to do this. I can do the same as the above and set up an importMap in deno.json to import the dependency from my local copy of its repo, but then its deno.json/package.json with its configured exports and dependencies won't get used, so this will only work if I elaborately set up my application's importMap for each of the dependency's exports and make sure my application's direct dependency list is a superset of my dependency's dependencies. In my ideal world, I could set my application's importMap to point to another local directory on my computer that contains a deno.json/jsr.json file and have it be used as it would be for a JSR dependency. (I guess I should be able to do the same thing in a regular import too, as anything that could be done in an import map can be done without one too. Maybe it would look like import foo from "jsr-local:../local-jsr-package-directory-containing-deno-json/:namedEntryPoint";. It's important that there's some way to distinguish the local directory path from a named entrypoint listed in that directory's deno.json's exports field.) *(deno vendor doesn't even work by default for this case: you get this message when trying to run the application after using it: "Warning "importMap" setting is ignored when "imports" or "scopes" are specified in the config file.". If you remove the "imports" section of deno.json, then it works, but with the previous caveats about deno vendor.)

With a Node(/webpack/Next.js) application and JSR dependencies, it seems I'm totally left to the wolves: the previous paragraph applies, plus the issue that my Node/webpack/Next.js application doesn't support Deno-flavored Typescript. JSR's npm compatibility layer does something to transform a folder of .ts ESM files to be Node-compatible esm .js, and I don't know how to do this transformation locally. If I wanted to do a test of a possible change to a JSR package of mine and run it in a Node application, the only official and fully accurate technique seems to be to publish a public pre-release version of the JSR package and make my Node application use that, which is gross. *(I could wrestle with dnt or deno2node to do something similar to JSR's npm compatibility layer, but I'd prefer to be able to do the exact transformation that JSR's npm compatibility layer does so I can be sure I'm getting the exact same results and so I don't have to configure yet another tool.)

(This isn't strictly JSR-related, but for completeness:) With a Deno application and NPM dependencies, it's awkward but do-able: I can switch Deno to use the node_modules directory using --unstable-byonm, and then use npm install and npm link DEPNAME, but I believe this requires me to set up a package.json for my application with all my npm dependencies first, which a usual Deno application will not have.

Macil avatar Jun 26 '24 23:06 Macil

FYI: Adding vendor: true to deno.json copies all dependencies in a project local node_modules and vendor folder. It's essentially what deno vendor should have been. I use it quite frequently to debug something in third party dependencies and we noticed that we're missing docs on that.

marvinhagemeister avatar Jun 27 '24 07:06 marvinhagemeister

I want to support @Macil's concerns. The vendor flag doesn't resolve all the issues related to installing dependencies. I have a monorepo with a collection of packages that have different dependencies, and I would like to be able to import them into a project I'm developing concurrently to test whether the solution makes sense or not. In npm, I could just specify a local path to the npm package in package.json. However, with Deno, I can only specify the path to the source file, and deno.json is ignored in this scenario.

raaymax avatar Jul 19 '24 21:07 raaymax

I recently decided to update an old script I had for converting Deno modules into Node packages. I'm aware of dnt, and it might be stable now, but back then, it wasn't working well with some of my types (particularly with the re-exports in @sinclair/typebox).

So today, I revamped my old script to generate packages similar to those hosted on npm.jsr.io. You can find my local-deploy script here. It uses TypeScript to transpile both JavaScript and types.

This might be helpful for you all until there's an official way to deploy locally.

grenierdev avatar Sep 04 '24 01:09 grenierdev

It seems like self hosting is on the roadmap #203, that could offer a good local development story. Not quite as smooth as npm link but due to the nature of how JSR transpiles the uploaded sources I think this is probably the best approach for local development.

tom-sherman avatar Mar 07 '25 14:03 tom-sherman

Deno is adding a feature to allow an application to substitute out an npm package (https://github.com/denoland/deno/pull/28512), in addition to its support for substituting out a JSR package. The jsr (or deno) CLI could have a link subcommand that makes this edit to deno.json. (Something else would still have to be done to support "npm link" functionality for JSR packages used in Node projects.)

Macil avatar Mar 21 '25 00:03 Macil

In Deno you can do this using the links feature in deno.json. For Node users we need to implement https://github.com/jsr-io/jsr/issues/179.

lucacasonato avatar Jun 26 '25 16:06 lucacasonato