Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Scala.js Webpack loader

[![npm](https://img.shields.io/npm/v/scalajs-loader.svg)](https://www.npmjs.com/package/scalajs-loader)
[![npm](https://img.shields.io/npm/v/scalajs-loader.svg)](https://www.npmjs.com/package/@aappddeevv/scalajs-loader)

This is an updated version from [https://github.com/mrdziuban/scalajs-loader](https://github.com/mrdziuban/scalajs-loader).

### Usage

Expand Down Expand Up @@ -31,3 +33,30 @@ Make sure you have the `sbt` binary somewhere in your `PATH`.
### Example

Check out the [example](example) directory for a simple Hello World example.

### Options
Options can be provided to specify the scalajs stage, fullOptJS or fastOptJS.
```js
... as above ...
{
test: /\.scala$/,
loader: 'scaljs-loader',
options: {
jsStage: 'fullOptJS',
clean: true
}
}
```
An additional option `dirSegment` appends a directory segment after the standard
scalajs target output directory (such as target/scala-2.12) in case you are
using a sbt plugin like scalajs-bundler that alters the output directory.

To reduce build times, you may want to keep `clean: false` for dev work and run
clean only for the production build.

All options:
* verbose: Print messages during processing.
* clean: Clean prior to build.
* dirSegment: Directory segment inserted into the constructed path to find the .js file.
* removeSoruceMapUrl: Remove the source map URL.
* jsStage: "fastOptJS" or or "opt"
64 changes: 44 additions & 20 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,51 @@
const exec = require('child_process').exec;
const path = require('path');
const readFileSync = require('fs').readFileSync;
const loaderUtils = require("loader-utils");

module.exports = function(source) {
const callback = this.async();
const cmd = 'sbt clean fastOptJS scalaVersion';

var self = this;
exec(cmd, { cwd: this.options.context }, function(error, stdout, _stderr) {
if (error) { return callback(error, null); }
const util = require("util");

const scalaVersion = stdout.toString().trim().split('\n').pop().replace(/\u001b\[0m/g, '').replace(/^\[info\] (\d+\.\d+)(\.\d+)?/, '$1').trim();
const outDir = path.join(self.options.context, 'target', `scala-${scalaVersion}`);

const modName = JSON.parse(readFileSync(path.join(outDir, 'classes', 'JS_DEPENDENCIES')).toString()).origin.moduleName;
const outFile = path.join(outDir, `${modName}-fastopt.js`);
module.exports = function(source) {
const options = Object.assign({},
{clean: true, dirSegment:"", jsStage: "fastOptJS",
removeSourceMapUrl: false, verbose: false},
loaderUtils.getOptions(this));
const verbose = options.verbose;
const dirSegment = options.dirSegment;
const clean = options.clean ? "clean": "";
const jsStage = options.jsStage;
const stageFileSegment = (jsStage === 'fastOptJS')?'fastopt':'opt';
const callback = this.async();
const cmd = `sbt ${clean} ${jsStage} scalaVersion`;
const context = this.options.context;
var self = this;
if(verbose) {
console.log("\nscalajs-loader options: " + util.inspect(options));
console.log("Running command: " + cmd);
}
exec(cmd, { cwd: context }, function(error, stdout, _stderr) {
if (error) { return callback(error, null); }
const scalaVersion = stdout.toString().trim().split('\n').pop().replace(/\u001b\[0m/g, '').replace(/^\[info\] (\d+\.\d+)(\.\d+)?/, '$1').trim();
const outDir = path.join(context, 'target', `scala-${scalaVersion}`);

callback(
null,
readFileSync(outFile).toString().replace(
new RegExp(`\\n\/\/# sourceMappingURL=${modName}-fastopt\.js\.map`),
`\n//# sourceMappingURL=${outFile}.map`
)
);
});
const modName = JSON.parse(readFileSync(path.join(outDir, 'classes', 'JS_DEPENDENCIES')).toString()).origin.moduleName;
const jsBasename = `${modName}-${stageFileSegment}.js`;
const outFile = path.join(outDir, dirSegment, jsBasename);
const sourceMapFile = path.join(outDir, dirSegment, `${modName}-${stageFileSegment}.js.map`);
if(verbose) { console.log("Reading source map file: " + sourceMapFile); }
const sourceMap = readFileSync(sourceMapFile).toString();
const replacement = options.removeSourceMapUrl? '': `\n//# sourceMappingURL=${outFile}.map`;
if(verbose) {
console.log("Processing scala file: " + outFile);
if(options.removeSourceMapUrl) { console.log("Removing sourceMappingURL."); }
else { console.log("Replacing source map url with: " + replacement); }
}
const regex = new RegExp(`\\n\/\/# sourceMappingURL=${modName}-${stageFileSegment}\\.js\\.map`);
const passAlongContent = readFileSync(outFile).toString().replace(regex, replacement);
callback(
null,
passAlongContent,
sourceMap
);
});
};
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
{
"name": "scalajs-loader",
"version": "0.0.1",
"author": "Matt Dziuban",
"name": "@aappddeevv/scalajs-loader",
"version": "0.0.2",
"author": "aappddeevv",
"description": "Scala.js loader module for webpack",
"dependencies": {
"loader-utils": "^1.1.0"
},
"repository": {
"type": "git",
"url": "[email protected]:mrdziuban/scalajs-loader"
"url": "[email protected]:aappddeevv/scalajs-loader"
},
"license": "MIT"
,"keywords": ["scalajs", "scala", "webpack"]
}