denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
96.29k stars 5.32k forks source link

vite can't resolve local module in deno workspace from a node project #26138

Open cam-mcevenue opened 1 week ago

cam-mcevenue commented 1 week ago

Version: Deno 2.0.0

Reproduction Repo linked below : https://github.com/cam-mcevenue/deno-monorepo-repro/tree/main

I am attempting to build a sveltekit project within a deno monorepo.

I have two directories apps/web which contains the sveltekit demo project and packages/foo which contains a typescript module for testing.

// deno.json (root)
{
  "nodeModulesDir": "auto",
  "workspace": ["./packages/foo", "./packages/bar", "./apps/web"],
}

This is the deno.json that exports a simple function

// deno.json (packages/foo)
{
    "name": "@scope/foo",
    "version": "1.0.0",
    "exports": {
        ".": "./mod.ts"
    }
}

// mod.ts
export const hello = (msg: string) => {
  console.log(`Hello, ${msg}!`);
};

When I try to import this function into any TS file in my apps/web project, vite errors that it can't resolve the module.

Error: Cannot find module '@scope/foo' imported from '/Users/cm/Desktop/repos/playground/deno-repro/apps/web/src/routes/+page.ts'
    at nodeImport (file:///Users/cm/Desktop/repos/playground/deno-repro/node_modules/.deno/vite@5.4.8/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:52990:19)
    at ssrImport (file:///Users/cm/Desktop/repos/playground/deno-repro/node_modules/.deno/vite@5.4.8/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:52857:22)
    at eval (/Users/cm/Desktop/repos/playground/deno-repro/apps/web/src/routes/+page.ts, <anonymous>:3:50)
    at instantiateModule (file:///Users/cm/Desktop/repos/playground/deno-repro/node_modules/.deno/vite@5.4.8/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:52915:11)

Deno's LSP can resolve the path, but vite cannot. Is there a vite plugin or any config changes I can make that will allow it to resolve deno local module paths?

marvinhagemeister commented 6 days ago

Out of the box vite doesn't know about Deno specific resolution. We have a vite plugin for that: https://github.com/denoland/deno-vite-plugin . Does installing it resolve the issue?

To install it:

  1. Run deno install npm:@deno/vite-plugin
  2. Update your vite.config.ts

    import { defineConfig } from "vite";
    + import deno from "@deno/vite-plugin";
    
    export default defineConfig({
    +   plugins: [deno()],
    });
cam-mcevenue commented 6 days ago

@marvinhagemeister Tried the above without luck. Got the same error, can't be resolved by vite.

I also tried adding alias to the deno.json in the project where the vite.config is and still no luck. Still can't be resolved by the bundler.

// deno.json in local sveltekit project directory
{
    "imports": {
        "@scope/foo": "jsr:@scope/foo@1.0.0"
    }
}
marvinhagemeister commented 6 days ago

Can confirm. The vite plugin calls deno info under the hood and that command seems to ignore workspaces. Was able to make a smaller reproduction:

  1. Create a deno.json with these contents:
    {
    "workspace": ["./foo"]
    }
  2. Create folder foo
  3. Create ./foo/deno.json with these contents:
    {
    "imports": {
      "@std/assert": "jsr:@std/assert@1"
    }
    }
  4. Run cd foo && deno info @std/assert -> Error

Debug output:

$ DENO_LOG=debug deno info @std/assert
DEBUG RS - deno_config::deno_json:779 - Config file found at '/<project>/foo/deno.json'
DEBUG RS - deno_config::deno_json:779 - Config file found at '/<project>/deno.json'
DEBUG RS - deno::args:930 - Finished config loading.
DEBUG RS - deno_config::workspace::resolver:315 - Workspace config generated this import map {
  "scopes": {
    "./foo/": {
      "@std/assert": "jsr:@std/assert@1",
      "@std/assert/": "jsr:/@std/assert@1/"
    }
  }
}
DEBUG RS - deno::cache::cache_db:168 - Opening cache /Users/marvinh/Library/Caches/deno/dep_analysis_cache_v2...
DEBUG RS - import_map:1110 - Specifier "@std/assert" was not mapped in import map.
DEBUG RS - deno::file_fetcher:622 - FileFetcher::fetch_no_follow_with_options - specifier: file:///<project>/foo/@std/assert
error: module could not be found

It seems like the deno info command only looks at the root deno.json and isn't aware that it's in a workspace member.

cam-mcevenue commented 6 days ago

@marvinhagemeister so this is an issue with @deno/plugin-vite? Should I link the issue there? Bit of a newb haha thanks for your help

marvinhagemeister commented 6 days ago

No need to, this is an issue in Deno itself.