sbt new vmunier/play-scalajs.g8 #(新建play scalajs 工程)
参照https://github.com/paulb79/play-scalajs-skeleton-project link 更改项目配置。
另一个有价值的参考项目为:https://github.com/beikern/foulkon-ui/blob/master/build.sbt link
build.sbt 和 plugins.sbt配置
a. 必须将整个项目分割为3个子Project,每个Project的依赖插件单独配置,以保证 jvm, js互不干扰,并保留share的子project,跨平台项目作为 js jvm平台复用部分,涉及js平台的scala代码有特殊的要求,参考scalajs项目文档。
关键插件scalajs-bundler
a. 依赖npm和 webpack,但仅需要安装npm, 相关依赖也不用显式添加webpack
b. npm 获取 js依赖, webpack将js依赖及 scalajs编译生成的文件 compress到同一js文件中
c. js依赖只有在 相关库有被显式使用的时候才会真正被添加(从现象来看是 用户个人的编码里有使用的 js依赖才会被添加, 第三方库中使用的js依赖不会,但如果用户使用了第三方scalajs库,则相关的js依赖也会添加),这一步与scalajs三方库 是否使用facade有关。可详细阅读 scalajs的document。
d. 针对c项,部分三方scalajs库需要 原js库被export到js global空间中,这个需要使用webpack的 配置文件将相关的模块输出到global空间,可以参考:
https://scalacenter.github.io/scalajs-bundler/cookbook.html#global-namespacelink
f. 关于d项中 webpack.config.js配置项:
var webpack = require('webpack');
// Load the config generated by scalajs-bundler
var config = require('./scalajs.webpack.config');
// Exported modules
var globalModules = {
"plotly.js-dist-min": "Plotly",
};
//const importRule = {
// // Force require global modules
// test: /.*-(fast|full)opt\.js$/,
// loader:
// "imports-loader?" +
// Object.keys(globalModules)
// .map(function(modName) {
// return modName + "=" + globalModules[modName];
// })
// .join(",")
//};
const exposeRules = Object.keys(globalModules).map(function(modName) {
// Expose global modules
return {
test: require.resolve(modName),
loader: "expose-loader?" + globalModules[modName]
};
});
//const allRules =
const allRules = exposeRules.concat(config.module.rules);
config.module.rules =allRules
module.exports = config;
关于globalModules 的设定说明,key为子module的名,对应js中的依赖路径, value为输出到gloable中的辩识符
var globalModules = {
"plotly.js-dist-min": "Plotly",
};
// 对于 expose来说,等效于 javascript中的var Plotly = require(plotly.js-dist-min)
//类似的其它例子:
// Exported modules
var globalModules = {
"material-ui": "mui",
"material-ui/styles" : "mui.Styles",
"material-ui/svg-icons/index" : "mui.SvgIcons",
"react": "React",
"react-infinite": "Infinite",
"react-paginate": "ReactPaginate",
};
e. 关于d项中的配置,build.stb的client的setting需要添加
//添加 js 依赖
npmDependencies in Compile ++= Seq( // js dep
"react" -> "16.13.1",
"react-dom" -> "16.13.1",
"plotly.js-dist-min" -> "1.52.2"
),
// 添加 expose-loader
npmDevDependencies in Compile ++= Seq( // for compile
"expose-loader" -> "0.7.5", // expose lib js global accord scalajs-bundler
// "imports-loader" -> "0.8.0",
// "webpack-merge" -> "4.1.2",
),
// 设定配置文件
webpackConfigFile := Some(baseDirectory.value / "webpack.config.js"), // 指明配置文件地址
lazy val server = (project in file("server")) // server side set noly jvm
.settings(commonSettingsJs)
.settings(
scalaJSProjects := Seq(client),
pipelineStages in Assets := Seq(scalaJSPipeline),
pipelineStages := Seq(digest, gzip),
// triggers scalaJSPipeline when using compile or continuous compilation
compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value,
libraryDependencies ++= {
val log4jversion = "2.13.0"
Seq(
"com.vmunier" %% "scalajs-scripts" % "1.1.4",
// ws, // play http ws client libary
"com.typesafe.play" %% "play-ahc-ws" % "2.8.7",
// ehcache, //cache for play ws
guice,
specs2 % Test,
// scala parallel
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.1",
"org.apache.kafka" % "kafka-clients" % "0.11.0.3" exclude("org.slf4j", "slf4j-log4j12"),
"com.baidu.adu" % "st-interface" % "1.2.0-SNAPSHOT",
"org.apache.logging.log4j" % "log4j-slf4j-impl" % log4jversion,
"org.apache.logging.log4j" % "log4j-core" % log4jversion,
"org.apache.logging.log4j" % "log4j-api" % log4jversion,
)
},
// add dependency asser accord scalajs-bundler
npmAssets ++= NpmAssets.ofProject(client) { modules => (modules / "font-awesome").allPaths }.value,
)
.enablePlugins(PlayScala) // for play framwork
.disablePlugins(PlayLogback)
.enablePlugins(WebScalaJSBundlerPlugin) // accord scalajs-bundler
.dependsOn(sharedJvm)
lazy val client = (project in file("client")) // client side only scala js
.enablePlugins(ScalaJSPlugin)
// .enablePlugins(ScalaJSWeb) // must not enable conflict with WEBJSBundler
.enablePlugins(ScalaJSBundlerPlugin) // accord scalajs-bundler
.enablePlugins(JSDependenciesPlugin)
// .enablePlugins()
.settings(commonSettingsJs)
.settings(
// scalaJSUseMainModuleInitializer := true,
webpackBundlingMode := BundlingMode.LibraryAndApplication(),
libraryDependencies ++= Seq( // scala dep
"org.scala-js" %%% "scalajs-dom" % "1.1.0",
// plotly face
"org.openmole" %%% "scala-js-plotlyjs" % "1.5.1",
//binding
"com.thoughtworks.binding" %%% "binding" % "12.0.1",
"org.lrng.binding" %%% "html" % "1.0.3",
"org.querki" %%% "jquery-facade" % "2.0",
),
npmDependencies in Compile ++= Seq( // js dep
"plotly.js-dist-min" -> "1.52.2",
// jquery for semantic
"jquery" -> "3.5.1"
),
npmDevDependencies in Compile ++= Seq( // for compile
"expose-loader" -> "0.7.5", // expose lib js global accord scalajs-bundler
"imports-loader" -> "0.8.0",
"webpack-merge" -> "4.2.2",
),
webpackConfigFile := Some(baseDirectory.value / "webpack.config.js"),
requireJsDomEnv in Test := true
)
.dependsOn(sharedJs)
lazy val shared = crossProject(JSPlatform, JVMPlatform)
.crossType(CrossType.Pure)
.in(file("shared"))
.settings(commonSettings)
.jsConfigure(_.enablePlugins(ScalaJSWeb))
.settings(
libraryDependencies ++= Seq(
"com.typesafe.play" %%% "play-json" % "2.9.2",
)
)
lazy val sharedJvm = shared.jvm
lazy val sharedJs = shared.js
lazy val commonSettingsJs = Seq(
scalaVersion := "2.13.1",
organization := "idg.itsqa",
// binding-scala
scalacOptions ++= {
import Ordering.Implicits._
if (VersionNumber(scalaVersion.value).numbers >= Seq(2L, 13L)) {
Seq("-Ymacro-annotations")
} else {
Nil
}
},
// Enable macro annotations by adding compiler plugins for Scala 2.12
libraryDependencies ++= {
import Ordering.Implicits._
if (VersionNumber(scalaVersion.value).numbers >= Seq(2L, 13L)) {
Nil
} else {
Seq(compilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full))
}
}
)
lazy val commonSettings = commonSettingsJs
// Seq(
// scalaVersion := "2.13.1",
// organization := "xx.xx"
//)
scalaVersion := "2.13.1"
organization := "xx.xx"
onLoad in Global := (Command
.process("project server", _: State)) compose (onLoad in Global).value
// Comment to get more information during initialization
logLevel := Level.Info
// Resolvers
resolvers += "Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/"
addSbtPlugin("org.scala-js" % "sbt-jsdependencies" % "1.0.2")
// Use Scala.js v1.x
//addSbtPlugin("com.vmunier" % "sbt-web-scalajs" % "1.1.0") // must disable because conflict with ScalaJSBundlerPlugin's webpack-based source mapping
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.3.0") // 1.2.0
// If you prefer using Scala.js v0.6.x, uncomment the following plugins instead:
// addSbtPlugin("com.vmunier" % "sbt-web-scalajs" % "1.1.0-0.6")
// addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.33")
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.6")
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-gzip" % "1.0.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.4")
addSbtPlugin("ch.epfl.scala" % "sbt-web-scalajs-bundler" % "0.20.0") // 0.18.0 for server web
//addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.8.2")
var Webpack = require('webpack');
const Merge = require("webpack-merge");
// Load the config generated by scalajs-bundler
var config = require('./scalajs.webpack.config');
// Exported modules
var globalModules = {
"plotly.js-dist-min": "Plotly",
"jquery": "jQuery"
// "react":"React",
// "react-dom": "ReactDom",
// "@material-ui/core": "MaterialCore",
// "@material-ui/icons": "MaterialIcons",
// "@material-ui/lab": "MaterialLab",
};
const importRule = {
// Force require global modules
test: /.*-(fast|full)opt\.js$/,
loader:
"imports-loader?" +
Object.keys(globalModules)
.map(function(modName) {
return modName + "=" + globalModules[modName];
})
.join(",")
};
const exposeRules = Object.keys(globalModules).map(function(modName) {
// Expose global modules
return {
test: require.resolve(modName),
loader: "expose-loader?" + globalModules[modName]
};
});
//const allRules = exposeRules.concat(importRule).concat(config.module.rules);
const allRules = exposeRules.concat(importRule).concat(config.module.rules);
config.module.rules =allRules
Object.keys(config.entry).forEach(function(key) {
// Prepend each entry with the globally exposed JS dependencies
config.entry[key] = Object.keys(globalModules).concat(config.entry[key]);
});
// Globally expose the JS dependencies
//config.module.loaders = Object.keys(globalModules).map(function (pkg) {
// return {
// test: require.resolve(pkg),
// loader: "expose-loader?" + globalModules[pkg]
// }
//});
module.exports = config
示例使用的npm版本
npm -v = 6.14.10
node -v = 14.15.4
转载请注明本文出处:[查看原文][1]
*[1]https://editor.csdn.net/md/?articleId=113756406