如何从多个Scala.js项目创建前端并适配跨构建配置
实现方案
方案一(最低成本):无需拆分项目,直接创建多独立Websocket连接
http4s-dom提供的connectHighLevel没有全局单例限制,完全没必要为了拆分WS连接新建独立Scala.js项目。你可以直接在现有前端代码里,给聊天、游戏大厅、核心游戏逻辑分别调用一次connectHighLevel创建独立连接实例,每个实例单独绑定消息处理器、重连规则、生命周期钩子即可,互相完全不干扰,零构建改造成本。
方案二(适合代码解耦需求):拆分独立前端模块
如果要按业务域拆分独立前端模块,按下面的配置调整即可:
1. 调整sbt跨构建配置,复用共享代码
Scala.js跨构建原生支持多JS模块依赖公共共享层,直接修改build.sbt:
// 原有跨构建项目保留,所有JVM/JS共享的代码、公共模型、工具逻辑都放在这里 lazy val diceGame = crossProject(JSPlatform, JVMPlatform) .in(file(".")) // 保留你原有的所有依赖、编译配置 .jvmSettings(/* 服务端原有配置不动 */) .jsSettings(/* 核心前端公共配置不动 */) // 新增聊天业务JS模块 lazy val chatJS = project.in(file("modules/chat-js")) .enablePlugins(ScalaJSPlugin) .dependsOn(diceGame.js) // 直接依赖原有跨构建的JS侧,所有公共代码直接复用 .settings( // 聊天模块单独的依赖、配置,比如WS相关的自定义逻辑 ) // 新增游戏大厅业务JS模块 lazy val lobbyJS = project.in(file("modules/lobby-js")) .enablePlugins(ScalaJSPlugin) .dependsOn(diceGame.js) // 同样复用公共共享代码 .settings( // 大厅模块单独的配置 ) // 根项目聚合所有模块,编译的时候会一次性处理所有子模块 lazy val root = project.in(file(".")) .aggregate(diceGame.jvm, diceGame.js, chatJS, lobbyJS)
配置完成后,原有共享层的所有代码都可以在chatJS、lobbyJS里直接引用,不需要重复编写。
2. 单JS文件引入的实现
不要手动合并编译输出的JS文件,Scala.js编译产物有严格的初始化顺序,手动拼接很容易出现类找不到、初始化时序错误。推荐用单入口聚合的方案:
- 把原有
diceGame.js作为前端唯一入口,让它依赖chatJS、lobbyJS两个业务模块:
lazy val diceGameJS = diceGame.js .dependsOn(chatJS, lobbyJS) .settings( // 主入口的启动逻辑里,分别调用聊天模块、大厅模块的WS初始化方法即可 )
sbt编译的时候会自动把所有依赖模块的代码打包到diceGame.js的输出产物里,HTML里只需要引入这一个JS文件就行,不需要额外处理合并逻辑。
- 如果后续要做代码分割按需加载,再考虑用Scala.js的模块拆分配置配合ES module加载即可,初期单入口打包是成本最低、最稳定的方案。
内容的提问来源于stack exchange,提问作者Onajk
相关产品推荐
相关产品推荐

