japgolly / scalajs-react

Facebook's React on Scala.JS
https://japgolly.github.io/scalajs-react/
Apache License 2.0
1.64k stars 231 forks source link

A minimal setup fails with Scala 3 #1081

Open Jake6329 opened 1 year ago

Jake6329 commented 1 year ago

I'm new to scalajs-react, and I've set up a minimal project. It works well with Scala 2.13.10 but it fails with Scala 3.2.1 (3.1.3 also shows the same error). When I run the command sbt "Compile / fastOptJS / webpack" in order to bundle my app, I get this error messages:

...
[info] Writing scalajs.webpack.config.js
[info] Bundling the application with its NPM dependencies
[error] /Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-map-generator.js:298
[error]       throw new Error('Invalid mapping: ' + JSON.stringify({
[error]       ^
[error] Error: Invalid mapping: {"generated":{"line":13410,"column":89},"source":"webpack://https:/raw.githubusercontent.com/japgolly/scalajs-react/v2.1.1/coreGeneric/src/main/scala/japgolly/scalajs/react/ReactCaughtError.scala","original":{"line":12,"column":-1},"name":null}
[error]     at SourceMapGenerator.SourceMapGenerator_validateMapping [as _validateMapping] (/Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-map-generator.js:298:13)
[error]     at SourceMapGenerator.SourceMapGenerator_addMapping [as addMapping] (/Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-map-generator.js:110:12)
[error]     at /Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:351:13
[error]     at SourceNode.SourceNode_walk [as walk] (/Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:230:9)
[error]     at SourceNode.SourceNode_walk [as walk] (/Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:226:13)
[error]     at SourceNode.SourceNode_walk [as walk] (/Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:226:13)
[error]     at SourceNode.SourceNode_walk [as walk] (/Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:226:13)
[error]     at SourceNode.SourceNode_walk [as walk] (/Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:226:13)
[error]     at SourceNode.SourceNode_toStringWithSourceMap [as toStringWithSourceMap] (/Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:342:8)
[error]     at exports.getSourceAndMap (/Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/webpack-sources/lib/helpers.js:20:41)
[error] Node.js v19.4.0
[error] Failure on parsing the output of webpack: No content to map due to end-of-input
[error]  at [Source: (ProcessPipeInputStream); line: 1, column: 0]
[error] You can try to manually execute the command
[error] node /Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/node_modules/webpack/bin/webpack --profile --json --config /Users/jakelim/demos/electron/my-scalajs-app/target/scala-3.2.1/scalajs-bundler/main/scalajs.webpack.config.js
[error] 
[error] java.lang.RuntimeException: Non-zero exit code: 1
[error]     at scala.sys.package$.error(package.scala:30)
[error]     at scalajsbundler.Webpack$.$anonfun$run$2(Webpack.scala:286)
[error]     at scala.util.Either.fold(Either.scala:192)
[error]     at scalajsbundler.Webpack$.run(Webpack.scala:286)
[error]     at scalajsbundler.Webpack$.bundle(Webpack.scala:170)
[error]     at scalajsbundler.sbtplugin.WebpackTasks$.$anonfun$webpack$2(WebpackTasks.scala:54)
[error]     at sbt.util.FileFunction$.$anonfun$cached$1(FileFunction.scala:80)
[error]     at sbt.util.FileFunction$.$anonfun$cached$4(FileFunction.scala:153)
[error]     at sbt.util.Difference.apply(Tracked.scala:414)
[error]     at sbt.util.Difference.apply(Tracked.scala:394)
[error]     at sbt.util.FileFunction$.$anonfun$cached$3(FileFunction.scala:149)
[error]     at sbt.util.Difference.apply(Tracked.scala:414)
[error]     at sbt.util.Difference.apply(Tracked.scala:389)
[error]     at sbt.util.FileFunction$.$anonfun$cached$2(FileFunction.scala:148)
[error]     at scalajsbundler.sbtplugin.WebpackTasks$.$anonfun$webpack$1(WebpackTasks.scala:57)
[error]     at scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error]     at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error]     at sbt.std.Transform$$anon$4.work(Transform.scala:68)
[error]     at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
[error]     at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error]     at sbt.Execute.work(Execute.scala:291)
[error]     at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
[error]     at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error]     at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
[error]     at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error]     at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
[error]     at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error]     at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[error]     at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[error]     at java.base/java.lang.Thread.run(Thread.java:829)
[error] (Compile / fastOptJS / webpack) Non-zero exit code: 1
[error] Total time: 11 s, completed Jan 16, 2023, 4:18:53 PM

Here's my build.sbt and the source code:

// project/build.properties
sbt.version=1.7.1

// project/plugins.sbt
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.12.0")
addSbtPlugin("ch.epfl.scala" % "sbt-scalajs-bundler" % "0.21.1")

// build.sbt
val scala3Version = "3.2.1"

lazy val root = project
  .in(file("."))
  .enablePlugins(ScalaJSPlugin)
  .enablePlugins(ScalaJSBundlerPlugin)
  .settings(
    name := "my-scalajs-app",
    version := "1.0",

    scalaVersion := scala3Version,
    // scalaVersion := "2.13.10",

    // This is an application with a main method
    scalaJSUseMainModuleInitializer := true,

    libraryDependencies += "com.github.japgolly.scalajs-react" %%% "core" % "2.1.1",

    Compile / npmDependencies ++= Seq(
      "react" -> "17.0.2",
      "react-dom" -> "17.0.2",
    ),
  )
// src/main/scala/tutorial/webapp/TutorialApp.scala
package tutorial.webapp

import japgolly.scalajs.react._
import japgolly.scalajs.react.vdom.html_<^._
import org.scalajs.dom

object TutorialApp {
  def main(args: Array[String]): Unit = {
    val Hello = ScalaComponent.builder[Unit]
      .renderStatic(<.div("Hello!"))
      .build

    val mountNode = dom.document.getElementById("content")
    Hello().renderIntoDOM(mountNode)
  }
}

If I switch to Scala 2.13.10, this works well as expected. Anyone any idea about the issue?

nkgm commented 1 year ago

[error] Failure on parsing the output of webpack: No content to map due to end-of-input

This appears to be more of a scalajs-bundler/webpack build issue. After a failed build, you can try opening a terminal at /Users/jakelim/demos/electron/my-scalajs-app/target/scala-${scalaVersion}/scalajs-bundler/main/ and run npx webpack --config scalajs.webpack.config.js from there to get the full webpack output.

I've been in a similar situation myself with Scala 3, which prompted me to switch to a Vite build and I couldn't be happier. I do love scalajs-bundler and it has served me well in the past, but inevitably sometimes things will break with new Scala/ScalaJS/sbt versions, whereas with Vite (btw it doesn't have to be Vite - any ESM bundler will do) you're in Node land so anything goes.

Jake6329 commented 1 year ago

I tried the suggested command, but I don't have the necessary knowledge on webpack to debug the issue. And then I looked up for Vite and it seems to be a viable alternative to scalajs-bundler. I'll try it instead. Thanks @nkgm

mdr commented 1 year ago

I hit what seems to be the same issue. Here's the output of the Webpack build that @nkgm suggested:

$ npx webpack --config scalajs.webpack.config.js
/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-map-generator.js:298
      throw new Error('Invalid mapping: ' + JSON.stringify({
      ^

Error: Invalid mapping: {"generated":{"line":13609,"column":89},"source":"webpack://https:/raw.githubusercontent.com/japgolly/scalajs-react/v2.1.1/coreGeneric/src/main/scala/japgolly/scalajs/react/ReactCaughtError.scala","original":{"line":12,"column":-1},"name":null}
    at SourceMapGenerator_validateMapping [as _validateMapping] (/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-map-generator.js:298:13)
    at SourceMapGenerator_addMapping [as addMapping] (/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-map-generator.js:110:12)
    at /Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:351:13
    at SourceNode_walk [as walk] (/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:230:9)
    at SourceNode_walk [as walk] (/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:226:13)
    at SourceNode_walk [as walk] (/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:226:13)
    at SourceNode_walk [as walk] (/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:226:13)
    at SourceNode_walk [as walk] (/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:226:13)
    at SourceNode_toStringWithSourceMap [as toStringWithSourceMap] (/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/source-map/lib/source-node.js:342:8)
    at exports.getSourceAndMap (/Users/matt/repos/personal/scala-3-js-test/js/target/scala-3.2.1/scalajs-bundler/main/node_modules/webpack-sources/lib/helpers.js:20:41)`
nkgm commented 1 year ago

Finally got a chance to look into this issue. Was hoping to investigate some more, but this could easily take another week so here's my findings so far.

The sourcemap url's to the published source files are missing a library segment, eg:

404 -> https://raw.githubusercontent.com/japgolly/scalajs-react/v2.1.1/coreGeneric/src/main/scala/japgolly/scalajs/react/ReactCaughtError.scala
200 -> https://raw.githubusercontent.com/japgolly/scalajs-react/v2.1.1/library/coreGeneric/src/main/scala/japgolly/scalajs/react/ReactCaughtError.scala

You can easily verify this by opening each url in a new brower tab.

A quick workaround would be to disable scalajs sourcemaps:

    Compile / fastOptJS / scalaJSLinkerConfig ~= { _.withSourceMap(false) },

fullOptJS should work without issues as sourcemaps are disabled by default.

A PR would be trivial replacing this line with s"$flag:$a->$g/v$ver/library/" :: Nil.

What baffles me still is how this only fails in Scala 3, so I'll be taking a look at the actual sourcemap files next chance I get.

Regarding my previous answer, scalajs-bundler is not at fault here and still a great tool for the job, even though my personal preference stands.

fthomas commented 1 year ago

I had a similar issue and fixed it by bumping the webpack version in the sbt build: webpack / version := "5.76.0". Maybe newer webpack versions do not fail if a source map URL returns 404.