Haskell Stack单仓库多包项目:为前端包指定GHCJS编译器方案
解决Haskell多包项目中GHC与GHCJS共存的方案
嘿,你的这个多包Haskell Web项目的困扰我太懂了——其实方案二(单仓库+单个Stack配置的思路)完全可行,Stack早就支持为不同包指定不同的编译工具链,或者通过轻量的多配置文件来分离构建任务。下面给你几个具体的落地方法:
方法一:在单个stack.yaml中为前端包指定GHCJS
Stack的packages字段支持为每个包单独配置编译器,你只需要调整stack.yaml如下:
resolver: lts-20.25 # 选一个兼容的resolver,确保GHC和GHCJS版本匹配 packages: - path: ./shared - path: ./backend - path: ./frontend compiler: ghcjs-9.2.0.1 # 替换成和你的resolver兼容的GHCJS版本 extra-deps: # 这里按需添加GHCJS专属的额外依赖(如果resolver里没有的话)
注意:要保证GHCJS版本和resolver对应的GHC版本匹配,比如lts-20对应的GHC是9.2.8,对应的GHCJS用9.2.0.1就没问题。你可以先跑stack setup ghcjs-<version>提前装好对应的工具链。
构建的时候也很灵活:
- 编译后端和共享包:
stack build backend shared - 编译前端包:
stack build frontend
Stack会自动为前端包切换到GHCJS编译器,完全不用手动切换环境。
方法二:用多Stack配置文件分离构建任务
如果觉得单个配置文件里混着两种编译器的配置有点乱,你可以搞两个配置文件:
stack.yaml(用来编译后端和共享包,用GHC):
resolver: lts-20.25 packages: - ./shared - ./backend
stack-ghcjs.yaml(专门编译前端包,用GHCJS):
resolver: lts-20.25 compiler: ghcjs-9.2.0.1 packages: - ./shared - ./frontend extra-deps: # 前端依赖的GHCJS版本包(如果需要的话)
构建时:
- 后端/共享包直接跑:
stack build - 前端包跑:
stack --stack-yaml stack-ghcjs.yaml build
这种方式更清晰,避免不同工具链的配置冲突,同时所有包还是在同一个仓库里,方便统一管理版本和代码。
对方案一的小改进(如果你还是倾向多仓库)
要是你还是想保留多仓库的方案,其实不用每次改完共享包都推GitHub——Stack支持引用本地路径的依赖,把extra-deps改成这样就行:
extra-deps: - ./../shared # 假设共享包在当前项目的同级目录下
改完共享包之后,直接在后端或者前端项目里跑stack build就能用上本地的修改,完全不用推送,测试效率会高很多。
额外小建议
- 共享包里定义数据类型的时候,记得用
DeriveGeneric、Generic配合aeson做JSON序列化,这样前后端对接的时候完全不会有类型不兼容的问题。 - 前端用
reflex-dom的话,配合ghcjs-dom处理DOM操作会更顺手,Stack会自动处理GHCJS环境下的依赖替换。
内容的提问来源于stack exchange,提问作者rtytgat
相关产品推荐
相关产品推荐

