scala-js / vite-plugin-scalajs

Vite plugin for integration of Scala.js
Apache License 2.0
51 stars 9 forks source link

Issue with sourcemap pointing to missing file #4

Open KristianAN opened 1 year ago

KristianAN commented 1 year ago

Hi. I'm having some strange errors similar to what has been reported in this react vite plugin https://github.com/vitejs/vite/issues/5438.

I'm not confident that it's not me doing something wrong though.

scalajs version 1.13.1 Error:

Sourcemap for "/home/kristian/projects/tyrian-vite/target/scala-3.2.2/vitexp-fastopt/example.vitexp$.js" points to missing source files
Sourcemap for "/home/kristian/projects/tyrian-vite/target/scala-3.2.2/vitexp-fastopt/example.Msg.js" points to missing source files
Sourcemap for "/home/kristian/projects/tyrian-vite/target/scala-3.2.2/vitexp-fastopt/example.Msg$.js" points to missing source files
Sourcemap for "/home/kristian/projects/tyrian-vite/target/scala-3.2.2/vitexp-fastopt/internal-5f6e416ac81ce4a9894441232bcec3b9f7270ddb.js" points to missing source files
Sourcemap for "/home/kristian/projects/tyrian-vite/target/scala-3.2.2/vitexp-fastopt/example.Msg$$anon$1.js" points to missing source files

package.json

{
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "@scala-js/vite-plugin-scalajs": "^1.0.0",
    "process": "^0.11.10"
  }
}

main.js

import { 
  TyrianApp
} from 'scalajs:main.js'

TyrianApp.launch("vitexp");

build.sbt contains following config

      scalaJSLinkerConfig ~= {
        _.withModuleKind(ModuleKind.ESModule)
          .withModuleSplitStyle(
            ModuleSplitStyle.SmallModulesFor(List("example"))
          )
      },

The app is started from this definition.

package example

import cats.effect.IO
import tyrian.Html.*
import tyrian.*

import scala.scalajs.js.annotation.*

@JSExportTopLevel("TyrianApp")
object vitexp extends TyrianApp[Msg, Model]:
...

The app works, but I think this error will cause the bundle size to grow large? I tried digging into this, but I'm out of my depth now. Hopefully it's just some stupid mistake I've made in the way I've set it up.

Thanks for the nice plugin :)

KristianAN commented 1 year ago

This might also be unrelated to this plugin as I have reproduced the same issue simply using Vite without the plugin while using Tyrian.

DanielMoss commented 1 year ago

Hi. I've just spent a bunch of time looking into this as I've been seeing the same warning in my own project. I thought I'd post here what I've found out, in case anyone else comes across this issue:

What's the impact?

To be honest, I don't really know. If you load your app up in the browser and use your dev tools to check sources, you can clearly see that the browser is able to load both the remote and local source files. I don't know what Vite is using the sourcemaps for.

What's going on?

The warning from Vite comes from this line of code. If you modify your package.json to add debugging

"scripts": {
  "dev": "vite --debug",

and set an environment variable named DEBUG with value vite:sourcemap, then when you next run npm run dev you'll see the following in the new output logs:

Sourcemap for "C:/path/to/project/target/scala-2.13/fastopt/package.MyClass.js" points to missing source files      
  vite:sourcemap Missing sources:
  vite:sourcemap   C:\path\to\project\target\scala-2.13\fastopt\file:\C:\path\to\project\src\main\scala\package\MyClass.scala
  vite:sourcemap   C:\path\to\project\target\scala-2.13\fastopt\https:\raw.githubusercontent.com\raquo\Laminar\ebb55cd79ffbd2906a0be9cbc17e80fcad210ef0\src\main\scala\com\raquo\laminar\api\package.scala
...

In the above example, I've got two sources. One is to a local class in my project, and the other is to a remote source file for one of my dependencies.

It's a little clearer what the problem is now. You can see that vite is attempting to load the sources from the directory the Scala JS linker outputs sourcemaps to, but for some reason the URI is incorrect. If you navigate to C:/path/to/project/target/scala-2.13/fastopt/package.MyClass.js.map, you'll see something like this:

{
  "version": 3,
  "file": "package.MyClass.js",
  "mappings": "<redacted>",
  "sources": ["file:///C:/path/to/project/src/main/scala/package/MyClass.scala", "https://raw.githubusercontent.com/raquo/Laminar/ebb55cd79ffbd2906a0be9cbc17e80fcad210ef0/src/main/scala/com/raquo/laminar/api/package.scala", "..."],
  "names": ["redacted"],
  "lineCount": 45
}

So Scala JS is outputting the URIs correctly. The problem is these two bits of code in Vite: link, link Together, these prepend the values from sources in your sourcemap with the path to the directory your sourcemap is stored in. That's why we're getting those malformed URIs.

What can I do about it?

Project files

I came across this trick in the scala-js channel of the Scala discord (use -P:scalajs:mapSourceURI in Scala 2):

scalacOptions += {
  val baseURI = baseDirectory.value.toURI.toString
  val hack = "../../../"
  s"-scalajs-mapSourceURI:$baseURI ->$hack/"
}

This transforms the project sources in your sourcemaps from file:///C:/path/to/project/src/main/scala/package/MyClass.scala to ../../../src/main/scala/package/MyClass.scala. Then when Vite prepends this with C:/path/to/project/target/scala-2.13/fastopt/, the resulting URI becomes C:/path/to/project/src/main/scala/package/MyClass.scala - the correct URI!

However, we've changed the actual sourcemap definition and this breaks the sourcemap for the browser! It gets rid of the warning from Vite, but now you have a new (and real) problem.

Remote files

I found this issue from someone running into similar problems with Webpack. There's good discussion in the issue, and @DominikGuzei was graceful to share an SBT task which can be used to download the remote sources referenced in your sourcemaps and modify the sourcesto reference the now local sourcemaps.

Unfortunately for us, as mentioned in the project files section I haven't found a solution that allows Vite to find the local files that doesn't simultaneously break the browser's ability to find the sourcemaps.

TL;DR

I don't know why Vite is emitting the sourcemap warning, but your browser should be able to find the sourcemaps with ScalaJS' default config. I've resigned to just living with the warning for now.