Closed julienrf closed 5 years ago
Omg, this is huge! Thanks!
The following tests are failing with Scala.js 1.0.0-M7:
The build doesn’t even load and reports the following error:
[info] java.lang.NoClassDefFoundError: org/scalajs/jsdependencies/sbtplugin/JSDependenciesPlugin$
I don’t understand where we have a dependency on that class.
The project loads and some tests pass, but this line fails. This line loads an HTML page that includes the bundle created by scalajs-bundler. The reported JavaScript error is:
TypeError: [object Object] is not a function, it is object. (file:/tmp/sbt_c80d120e/sharedconfig/target/scala-2.11/scalajs-bundler/main/sharedconfig-opt-bundle.js#18)
Of course, line 18 of the file is unreadable because it contains the output of fullOptJS
. The weird thing is that the same test, with fastOptJS
does pass (line 4).
Has anyone any clue of what’s happening or want to help to debug?
For the sbt-web-scalajs-bundler error, that's probably because it unconditionally depends on "com.vmunier" % "sbt-web-scalajs" % "1.0.8-0.6"
which is clearly for Scala.js 0.6.x. I guess the dependency should be adapted according to scalaJSVersion
.
Indeed, then we have another issue: sbt-web-scalajs depends on 1.0.0-M3, which is binary incompatible with 1.0.0-M7. I will make a PR on sbt-web-scalajs to update to 1.0.0-M7.
Of course, line 18 of the file is unreadable because it contains the output of fullOptJS. The weird thing is that the same test, with fastOptJS does pass (line 4).
I am no expert but could it be the new GCC and Common Module?
I think I’ve found the problem with the remaining failing tests. Unless I’m wrong, the problem was present before as well, but just didn’t show up. The fullOptJS
output uses a name that is also used by a library (leaflet) that the program depends on. So, they just clash. Is there a way to tell the Scala.js optimizer to not use certain reserved identifiers?
Is there a way to tell the Scala.js optimizer to not use certain reserved identifiers?
No, that's not possible, because Scala.js shouldn't have to ignore certain identifiers. CommonJS modules have dedicated scopes per spec. The bundler shouldn't mangle the scopes of different modules together.
I’ve pushed a commit that disables the Scala.js optimizer on that test, because I think that’s the only solution for now. In the long run, I would like to remove the LibraryAndApplication
and LibraryOnly
bundling modes, because they are just hacks that try make it possible to execute CommonJS modules in the browser, but this example shows that they are not robust options.
@julienrf
Unless I’m wrong, the problem was present before as well, but just didn’t show up
No. Some time ago Scala.js team removed IIFE wrapper around a module output and the problem with LibraryOnly
mode was introduced. See https://github.com/scalacenter/scalajs-bundler/issues/282 for details.
The LibraryOnly
mode is important feature of scalajs-bundler
, without it the compilation speed is unacceptable. We should found a way to preserve it!
I agree with keeping LibraryOnly and don't mean to pile on, it makes compilation fast for dev, which is basically the only way the Compile->Run loop is tolerable.
The
LibraryOnly
mode is important feature ofscalajs-bundler
, without it the compilation speed is unacceptable. We should found a way to preserve it!
Even with the latest webpack, is it still too slow?
Even with the latest webpack, is it still too slow?
Yes, it is quite slow even with the latest webpack. I don't think webpack can do anything better since the core issue is huge single fastOptJs file (about 27 MB in our case), so webpack has to at least parse it every time and that is going to take significant time.
Until Scala.js produces multiple small js files with only a few changing in each incremental compilation (which would be a wonderful feature by itself, anyway), removing LibraryOnly
mode will be very detrimental to developer productivity.
Even with the latest webpack, is it still too slow?
The latest webpack still parses a huge Scala.js output. So the speed is the same. Thanks @easel for introducing the LibraryOnly
mode, it is the only option to develop a real Scala.js application comfortably.
Our team cannot use LibraryOnly mode for some reasons, so now use default mode with a WebPack configuration like
const webpack = require('webpack');
const merge = require("webpack-merge");
const TerserPlugin = require("terser-webpack-plugin");
const scalajsBundlerConfig = require("./scalajs.webpack.config.js");
module.exports = merge(scalajsBundlerConfig, {
target: 'node',
output: {
libraryTarget: "commonjs2"
},
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
// Disable since Scala.js is already compressed by GCC
compress: false,
// mangling is also disabled due to trade off between optimization-time and space-efficiency
mangle: false,
output: {
comments: false,
},
},
}),
],
},
});
which reduces optJS time reasonable amount.
@exoego Did you write this about a fastOptJS
task? As I know there are all optimizations already disabled (GCC isn't used) in fastOptJS
.
@glmars Sorry, the above config was meant for fullOptJS for production.
Ah, ok, but a speed of fullOptJS
isn't so important for developers. The LibraryOnly
mode is especially significant in fastOptJS
to improve a Change->Compile->Run->Change ... cycle
Thanks to all for your feedback on the usage of the Library*
bundling modes. You convinced me that we should keep it for now ;)
I’ve rebased the PR, I think it is ready to be merged.
Thanks a lot @julienrf. this is a key component for the 1.x ecosystem
One more huge thanks for this, now Scala.js 1.0 milestones are finally useful for me! :)
Specific source directories have been created for Scala.js 0.6 and Scala.js 1.x, but most of the code cross-compiles.
Some tests are stuck on Scala.js 0.6 because they use libraryDependencies that are not yet available for Scala.js 1.x.
Usage of some internal APIs of Scala.js (e.g.
org.scalajs.core.tools.json
), which are not source compatible between 0.6 and 1.x has been replaced with play-json, which scalajs-bundler already depended on.Usage of
JSApp
in tests has been removed.