scalajs-bundler icon indicating copy to clipboard operation
scalajs-bundler copied to clipboard

...-loader.js refers window even if target is node

Open exoego opened this issue 7 years ago • 7 comments

I am trying to use scalajs-bundler to bundle app and node_modules into one file, targeting to node.js runtime. However, when the bundled file (...-bundle.js) is invoked on node. a ReferenceError (window is not defined) occurs.


Environment

  • sbt-scalajs-bundler: "0.12.0"
  • sbt-scalajs: "0.6.22"
  • build.sbt
lazy val foo= Project("foo")
  .enablePlugins(ScalaJSPlugin)
  .enablePlugins(ScalaJSBundlerPlugin)
  .settings(
    webpackBundlingMode := BundlingMode.LibraryAndApplication(),
    emitSourceMaps := false,
    webpackConfigFile in fastOptJS := Some(baseDirectory.value / "webpack.config.js"),
    webpackConfigFile in fullOptJS := Some(baseDirectory.value / "webpack.config.js")
  )
  // other settings
  • webpack.config.js (Since scalajs-bundler is very limited to configure webpack):
var config = require("./scalajs.webpack.config.js");
config.target = "node";
config.output.libraryTarget = "commonjs2";
config.externals = ["aws-sdk"];
module.exports = config;

What happens

In the above circrumstance, the generated foo-opt-loader.js is like below

var exports = window;
exports.require = window["ScalaJSBundlerLibrary"].require;

I believe these lines causes window is not defined error.


I referred Output- Webpack and tried several output.libraryTarget such as var (default of scalajs-bundler), this, commonjs and commonjs2.

It looks like foo-opt-library.js respects output.libraryTarget config and changes its form. However, foo-opt-loader.js does not respect the config and keep var exports = window line.

Any ideas?

exoego avatar Jun 08 '18 03:06 exoego

I suspects these lines. https://github.com/scalacenter/scalajs-bundler/blob/b80a1b9763769d5ab43bc4e54c7abf75c60a4ac1/sbt-scalajs-bundler/src/main/scala/scalajsbundler/util/JSBundler.scala#L9-L13

exoego avatar Jun 08 '18 04:06 exoego

I am trying to use scalajs-bundler to bundle app and node_modules into one file, targeting to node.js runtime.

If you target the Node.js runtime, you shouldn't even bundle. Node.js can load the non-bundled CommonJS module in the regular fastopt.js.

Bundling is for browsers. It doesn't make sense for Node.js.

sjrd avatar Jun 08 '18 06:06 sjrd

Ah, I see why it generates var exports = window.

I expected webpack, not only to bundle dependencies, but also to minify them, for environment where sizes matter. More specifically, it is AWS Lambda and similar Function as a Service. Minifying node_module is not uncommon for the domain. E.g., https://github.com/serverless/serverless-optimizer-plugin is for such purpose.

exoego avatar Jun 08 '18 09:06 exoego

Webpack can minimize but you need to configure it. E.g. with the uglify plugin

cquiroz avatar Jun 08 '18 11:06 cquiroz

@cquiroz Thanks for let me know the uglify plugin.

Can we use such plugin with scalajs-bundler, without fixing loader script (var exports = window)?

exoego avatar Jun 08 '18 13:06 exoego

Those are independent concepts. I think the window call is very much fixed on the creation of webpack’s config for scala js

cquiroz avatar Jun 09 '18 11:06 cquiroz

any idea what can cause this error to occur? I randomly get it also. I usually need to delete my target directories in my sbt project and rebuild.

In my chrome browser console, it says:

Uncaught TypeError: Cannot read property 'require' of undefined at client-fastopt-loader.js:3

and all there is in that file is:

var exports = window;
exports.require = window["ScalaJSBundlerLibrary"].require;

evbo avatar Jul 07 '19 22:07 evbo