当前位置: 首页 > news >正文

(cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)

前言

 书接上一回,在了解cljs基本语法后并在clojurescript.net的奇特错误提示后,我们必须痛定思痛地搭建一个本地的开发环境,以便后续深入地学习cljs。

现有的构建工具

 由于浏览器仅能运行JS,而无法直接运行cljs,因此我们需要搭建一个预编译环境将cljs编译成JS后再在浏览器中运行。预编译无非就是JVM和Nodejs两个环境,但具体使用时有如下几种构建工具。

  1. 直接JVM编译
  2. Lein方案
  3. Boot方案
  4. Lumo方案
  5. Shadow-cljs方案
  6. cljs/tool方案
     其中Lein和Boot都是基于JVM编译环境,只是上层的构建方式有所不同,而Lein除了用于构建cljs外还用于构建clj;而Boot则专注于构建cljs。
     Lumo则是基于Nodejs编译环境。
     Shadow-cljs则是node-jre,就是用node模块管理的jvm。
    由于我们只需搭建一个刚好可用的开发环境即可,因此下面只介绍方案1。

搭建一个最基础的——直接JVM编译

下载依赖

  1. Jdk8.0+
  2. ClojureScript 独立JAR

    创建工程

# 在家目录下创建工程目录
$ mkdir -p ~/hello_world/src/hello_world/

# 复制cljs.jar文件到工程目录下
$ cp ~/cljs.jar ~/hello_world/

# 创建项目配置文件
$ touch ~/hello_world/build.clj

# 创建源码文件
$ touch ~/hello_world/src/hello_world/core.cljs

# 创建HTML文件
$ touch ~/hello_world/index.html

build.clj文件中输入

(require '[cljs.build.api :refer [build]])
(build "src"
       {:main 'hello-world.core   ; 指定程序入口命名空间
        :output-to "main.js"}) ; 指定目标代码入口所在文件
;; 注意:其余依赖模块的目标代码默认会生成在out/下

src/hello_world/core.cljs文件中输入

(ns hello-world.core)

; 标准输出重定向到js/console.log
(enable-console-print!)

(println "Hello world!")

index.html文件中输入

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <!--必须放在body中,否则搭建Browser REPL时会报
        Uncaught TypeError: Cannot read property 'appendChild' of null
        at goog.net.xpc.CrossPageChannel.<anonymous> (crosspagechannel.js:482)
    -->
    <script src="main.js"></script>
</body>
</html>

现在到了最激动人心的一刻了!编译君!在shell中执行

$ java -cp cljs.jar:src clojure.main project.clj

然后打开浏览器访问index.html就可以在console中看到那句熟悉的Hello world!了。
 现在每次修改代码后均要编译一下,要知道启动Clojure是那么的漫长,所以我新增watch.clj的配置,让它监控src文件的变化来实现自动编译吧!

(require '[cljs.build.api :refer [watch]])
(watch "src"
       {:main 'hello-world.core   ; 指定程序入口命名空间
        :output-to "main.js"}) ; 指定目标代码所在文件

然后运行

$ java -cp cljs.jar:src clojure.main watch.clj

就会自动编译了,是不是舒心多了!等等,还不够。对于快速开发而言,我们还需要一个REPL!

搭建Browser REPL

首先安装个rlwrap,后面会用到!

新增repl.clj文件

(require '[cljs.build.api :refer [build]]
         '[cljs.repl :refer [repl]]
         '[cljs.repl.browser :refer [repl-env]])
(build "src"
       {:main 'hello-world.core
        :output-to "main.js"})

;; 配置REPL
(repl (repl-env)
      :watch "src"       ; REPL自动监控src目录下的cljs文件
      :output-dir "out") ; REPL重用build函数已编译的文件

修改src/hello_world/core.cljs文件

(ns hello-world.core
 (:require [clojure.browser.repl :as repl]))

;; 启动Browser REPL
(defonce conn
 (repl/connect "http://localhost:9000/repl"))

(enable-console-print!)

(println "Hello world!")

然后运行

$ rlwrap java -cp cljs.jar:src clojure.main repl.clj

然后打开浏览器访问http://localhost:9000/,这时浏览器访问的是index.html页面,然后我们按F12打开浏览器的console,那么shell中就会有我们心仪已久的REPL了!
这时我们在core.cljs中追加下面代码

(defn add [& more]
  (reduce + 0 more))

然后在REPL中加载这个命名空间

(require '[hello-word.core :refer [add]])
(add 1 2 3) ; -> 6

然后再将add改成multi

(defn multi [& more]
  (reduce * 0 more))

然后在REPL中重新加载这个命名空间

(require '[hello-word.core :refer [multi]] :reload)
(multi 2 2 3) ; -> 12

 现在我们可以继续深入cljs的学习咯!!!

总结

 开发环境搭建好了,那接下来要从哪里入手呢?大家是不是对(require '[cljs.repl :refer [repl]])(require '[cljs.repl :as repl])等有些疑惑呢?后面我们就从命名空间开始吧!(cljs/run-at (JSVM. :browser) "命名空间就这么简单")
尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/7087902.html ^_^肥仔John

相关文章:

  • IPv4 forwarding is disabled. Networking will not work.
  • 技术架构组工作职责
  • 第7章 高级分组
  • MySQL数据库的高可用方案总结
  • 一个扎心的错——Consider defining a bean of type 'java.lang.String' in your configuration.
  • Buffer源码深入分析
  • 以太坊共识机制
  • 浅析NSTimer CADisplayLink内存泄露
  • hdu 2227
  • ViewPager+RadioGroup实现标题栏切换,Fragment切换
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • PyTorch快速入门教程五(rnn)
  • 故障排查
  • 腾讯云服务器 安装监控组件
  • CRM系统客户形成需求和认知的五大因素
  • [nginx文档翻译系列] 控制nginx
  • es6
  • es6(二):字符串的扩展
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • Fastjson的基本使用方法大全
  • mysql 数据库四种事务隔离级别
  • unity如何实现一个固定宽度的orthagraphic相机
  • vue:响应原理
  • Wamp集成环境 添加PHP的新版本
  • 翻译--Thinking in React
  • 突破自己的技术思维
  • 小程序button引导用户授权
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 【干货分享】dos命令大全
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • (floyd+补集) poj 3275
  • (区间dp) (经典例题) 石子合并
  • (转)菜鸟学数据库(三)——存储过程
  • (转载)OpenStack Hacker养成指南
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • .net CHARTING图表控件下载地址
  • .NET Core引入性能分析引导优化
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • :如何用SQL脚本保存存储过程返回的结果集
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • @RequestBody与@ResponseBody的使用
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(白虎组)
  • [20181219]script使用小技巧.txt
  • [AIGC 大数据基础]hive浅谈
  • [BZOJ1089][SCOI2003]严格n元树(递推+高精度)
  • [c#基础]值类型和引用类型的Equals,==的区别
  • [C#基础知识]专题十三:全面解析对象集合初始化器、匿名类型和隐式类型
  • [C++] Boost智能指针——boost::scoped_ptr(使用及原理分析)
  • [CareerCup] 6.1 Find Heavy Bottle 寻找重瓶子
  • [cb]UIGrid+UIStretch的自适应
  • [CUDA手搓]从零开始用C++ CUDA搭建一个卷积神经网络(LeNet),了解神经网络各个层背后算法原理
  • [C语言]——内存函数
  • [Django 0-1] Core.Handlers 模块