summaryrefslogtreecommitdiff
path: root/book
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-10-29 22:19:12 -0700
committerLi Haoyi <haoyi@dropbox.com>2014-10-29 22:19:12 -0700
commit42394b5fa4bc0a76585d77f587a79b11c1b7c32f (patch)
tree5b288d3b955accd452f5f2ccfb460035b4e554d6 /book
parent43ac26ba9800a8fd15a94e59c8ba262691949226 (diff)
downloadhands-on-scala-js-42394b5fa4bc0a76585d77f587a79b11c1b7c32f.tar.gz
hands-on-scala-js-42394b5fa4bc0a76585d77f587a79b11c1b7c32f.tar.bz2
hands-on-scala-js-42394b5fa4bc0a76585d77f587a79b11c1b7c32f.zip
wip
Diffstat (limited to 'book')
-rw-r--r--book/index.tw11
-rw-r--r--book/intro.tw96
-rwxr-xr-xbook/src/main/resources/js/ui.js1
-rw-r--r--book/src/main/scala/book/Book.scala22
-rw-r--r--book/src/main/scala/book/Utils.scala8
5 files changed, 109 insertions, 29 deletions
diff --git a/book/index.tw b/book/index.tw
index db27d24..4dcea2d 100644
--- a/book/index.tw
+++ b/book/index.tw
@@ -2,22 +2,21 @@
@sect("Hands-on Scala.js")
@div(cls:="pure-g")
@div(cls:="pure-u-1 pure-u-md-13-24")
- @hl.ref("examples/src/main/scala/Example.scala", "/*example*/", false)
+ @hl.ref("examples/src/main/scala/Example.scala", "/*example*/", indented=false)
@div(cls:="pure-u-1 pure-u-md-11-24")
- @canvas(id:="example-canvas", display:="block")
- @script(src:="example-fastopt.js")
- @script("Example().main('example-canvas')")
+ @canvas(id:="canvas1", display:="block")
+ @script("Example().main(document.getElementById('canvas1'))")
@p
@a("Scala.js", href:="http://www.scala-js.org/") is a compiler that compiles Scala source code to equivalent Javascript code. That lets you write Scala code that you can run in a web browser, or other environments (Chrome plugins, Node.js, etc.) where Javascript is supported.
@p
- This book contains something for all levels of experience with Scala.js: beginners can get started with the Introduction and Hands-on tutorial, people who have used it before can skip ahead to the later parts of the tutorial, and even experienced users will find the In-depth Documention useful.
+ This book contains something for all levels of experience with Scala.js: absolute beginners can get started with the Introduction and Hands-on tutorial, people who have used it before can skip ahead to the later parts of the tutorial, building a canvas app or dynamic HTML page. Intermediate users will find the chapters on cross-publishing a Scala.js library interesting, and even experienced users will find the In-depth Documention useful.
@Book.intro
@Book.gettingStarted
-
+ @Book.canvasApp
diff --git a/book/intro.tw b/book/intro.tw
index ac40291..7c31fbc 100644
--- a/book/intro.tw
+++ b/book/intro.tw
@@ -1,3 +1,26 @@
+@p
+ Scala.js compiles Scala code to equivalent, executable Javascript. Here's the compilation of a trivial hello-world example:
+
+@div(cls:="pure-g")
+ @div(cls:="pure-u-1 pure-u-md-1-2")
+ @hl.scala
+ object Example extends js.JSApp{
+ def main() = {
+ var x = 0
+ while(x < 10) x += 3
+ println(x)
+ }
+ }
+
+ @div(cls:="pure-u-1 pure-u-md-1-2")
+ @hl.javascript
+ ScalaJS.c.LExample$.prototype.main__V = (function() {
+ var x = 0;
+ while ((x < 10)) {
+ x = ((x + 3) | 0)
+ };
+ ScalaJS.m.s_Predef().println__O__V(x)
+ });
@p
Traditionally, Scala has been a language which runs on the JVM. This eliminates it from consideration in many cases, e.g. when you need to build interactive web apps, you need to fall back to Javascript to run your client-side code, at a great loss in terms of toolability and maintainability. Scala.js lets you to develop web applications with the safety and toolability that comes with a statically typed language:
@@ -15,14 +38,7 @@
@p
The value proposition is that due to the superior language and tooling, writing a web application in Scala.js will result in a codebase that is more flexible and robust than an equivalent application written in Javascript.
-@sect{Who this book is for}
- @p
- This book is targeted at people who have some experience in both Scala and Javascript, as well as web development in general. You do not need to be an expert, but I will skim over basic concepts in to cut to the Scala.js specific points, though I will leave links whenever I introduce a new concept so you can read up if necssary.
-
- @p
- Furthermore, this book aims to only give an overview of the main steps you need to perform (and ideas you need to understand) to get started using Scala.js. It isn't a comprehensive guide, so if you want to know something this book doesn't cover, feel free to ask on the @a("mailing list", href:="https://groups.google.com/forum/#!forum/scala-js").
-
-@sect{Why Scala.js}
+@sect{About Javascript}
@p
Javascript is the language supported by web browsers, and is the only language available if you wish to write interactive web applications. As more and more activity moves online, the importance of web apps will only increase over time.
@@ -52,7 +68,12 @@
@hr
@p
- This is where Scala.js comes in. As developers we want Javascript-the-platform, with its ease-of-distribution, hyperlinks and security characteristics. We do not want Javascript-the-language, with its propensity for bugs, verbosity, and fragility. With Scala.js, you can cross compile your Scala code to a Javascript executable that can run on all major web browsers, thus saving you from the endless stream of gotcha's like the one below:
+ This is where Scala.js comes in. As developers we want Javascript-the-platform, with its ease-of-distribution, hyperlinks and security characteristics. We do not want Javascript-the-language, with its propensity for bugs, verbosity, and fragility.
+
+@sect{The Promise}
+
+ @p
+ Scala.js promises to save us from this mess: with Scala.js, you can cross compile your Scala code to a Javascript executable that can run on all major web browsers, thus saving you from the endless stream of gotcha's like the one below:
@hl.javascript
javascript> ["10", "10", "10", "10"].map(parseInt)
@@ -62,8 +83,61 @@
scala> List("10", "10", "10", "10").map(parseInt)
List(10, 10, 10, 10) // Yay!
- @p
- Scala.js allows you to take advantage of the Javascript platform while still enjoying all the benefits of a concise, safe, modern language. The benefits of Scala are well documented, and I will not make a case here for Scala vs. some other language. Suffice to say, I believe it's a considerable improvement over programming in Javascript, and with Scala.js we can bring this improvement in development speed and happiness from the backend systems (where Scala has traditionally been used) to the front-end web application.
+ @sect{The Language}
+ @p
+ At a first approximation, Scala.js provides you a sane language to do development in the web browser. Not only do you have an expressive language with static types, you also have great tooling with IDEs like IntelliJ and Eclipse, a rich library of standard collections, and many other modern conveniences that we take for granted but are curiously missing when working in the wild west of web development: the browser!
+
+ @p
+ While not useful for small applications, where most of the logic is gluing together external APIs, this comes in very useful in large applications where a lot of the complexity and room-for-error is entirely internal. With larger apps, you can no longer blame browser vendors for confusing APIs that make your code terrible: these confusing APIs only lurk in the peripherals around a larger, complex application. One thing you learn working in large-ish web client-side code-bases is that the bulk of the confusion and complexity is no-one's fault but your own, as a team.
+
+ @p
+ At this point, all of Google, Facebook, and Microsoft have all announced work on a typed variant of Javascript. These are not academic exercises: Dart/AtScript/Flow/Typescript are all problems that solve a real need, that these large companies have all faced once they've grown beyond a certain size. Clearly, Javascript isn't cutting it anymore, and the convenience and "native-ness" of the language is more than made up for in the constant barrage of self-inflicted problems. Scala.js takes this idea and runs with it!
+
+ @sect{Shared Code}
+ @p
+ Scala.js does not just stop at writing code on the client, though! Scala itself is a very successful, capable language for writing all sorts of systems, from web servers to backend infrastructure. With Scala.js, you can utilize the same libraries you use writing your Scala servers when writing your Scala web clients! On one end, you are sharing your templating language with @a("Scalatags", href:="https://github.com/lihaoyi/scalatags") or sharing your serialization logic with @a("uPickle", href:="https://github.com/lihaoyi/upickle"). At the other, you are sharing large, abstract libraries like @a("Scalaz", href:="https://github.com/japgolly/scalaz") or @a("Shapeless", href:="https://groups.google.com/forum/#!searchin/scala-js/shapeless/scala-js/5Sf2up0z3PU/9F9SYB0qHEcJ").
+
+ @p
+ Sharing code means several things:
+
+ @ul
+ @li
+ Not having to find two libraries to do a particular common task
+ @li
+ Not having to re-learn two different ways of doing the exact same thing
+ @li
+ Not needing to implement the same algorithms twice, for the times you can't find a good library to do what you want
+ @li
+ Not having to debug problems caused by subtle differences in the two implementations
+ @li
+ Not having to resort to awkward Ajax-calls or pre-computation to avoid duplicating logic between the client and server
+
+ @p
+ Shared code doesn't just mean sharing pre-made libraries between the client and server. You can easily publish your own libraries that can be used on both Scala-JVM and Scala.js. This means that as a library author, you can at once target two completely different platforms, and (with some work) take advantage of the intricacies of each platform to optimize your library for each one. Take Scalatags as an example: as the first client-server Scala.js-ScalaJVM shared libraries, it enjoys a roughly event split of downloads from people using it on both platforms:
+
+ @img(src:="images/Scalatags Downloads.png", width:="100%")
+
+ @p
+ Shared code means that if you, as an application writer, want some logic to be available on both the client and server, you simply put it in a "shared" folder, and that's the end of the discussion. No architectural patterns to follow, no clever techniques need to be involved. Shared logic, whether that means constants, functions, data structures, all the way to algorithms and entire libraries, can simply be placed in "shared" and be instantly accessible from both your client-side web code and your server.
+
+ @p
+ Shared code has long been the holy-grail of web development. Even now, people speak of shared code as if it were a myth. With Scala.js, shared code is the simple, boring reality. And there's a lot to like in that!
+
+ @sect{Client-Server Integration}
+ @p
+ There is an endless supply of new platforms which have promised to change-the-way-we-do-web-development-forever. From old-timers like @a("Ur-Web", href:="http://www.impredicative.com/ur/"), to @a("GWT", href:="http://www.gwtproject.org/"), to Asana's @a("LunaScript", href:="https://asana.com/luna"), to more recently things like @a("Meteor.js", href:="https://www.meteor.com/").
+ @p
+ One common theme in all these platforms is that their main selling point is their tight, seamless client-server integration, to the point where you can just make method calls across the client-server boundary and the platform/language/compiler figures out what to do.
+ @p
+ With Scala.js and Scala-JVM, such conveniences like making method calls across the client-server boundary is the boring reality. Not only are the calls transparent, they are also statically checked, so any mistake in the route name or the parameters it expects, or the result type it returns to you, will be caught by the compiler long before even manual testing.
+
+ @hr
+
+ @p
+ In many ways, Scala.js all-at-once provides many of the traditional holy-grails of web development: People have always dreamed about doing web development in a sane, best-of-breed language that compiles to both client and server. Of not having to worry too hard about whether code goes on the client or on the server, and being able to move or share it if necessary. Of having a compiler that will verify and check that your entire system is correct.
+
+ @p
+ Scala.js provides all these things, and much more.
@sect{The Agenda}
diff --git a/book/src/main/resources/js/ui.js b/book/src/main/resources/js/ui.js
index 5f144bb..ba79579 100755
--- a/book/src/main/resources/js/ui.js
+++ b/book/src/main/resources/js/ui.js
@@ -36,7 +36,6 @@ document.addEventListener("DOMContentLoaded", function(){
var snippets = document.getElementsByClassName("highlight-me");
for(var i = 0; i < snippets.length; i++){
- console.log("highlighting", snippets[i])
hljs.highlightBlock(snippets[i])
}
diff --git a/book/src/main/scala/book/Book.scala b/book/src/main/scala/book/Book.scala
index 31364cc..909c46e 100644
--- a/book/src/main/scala/book/Book.scala
+++ b/book/src/main/scala/book/Book.scala
@@ -14,6 +14,7 @@ object Book {
lazy val intro = sect("Intro to Scala.js")(twf("book/intro.tw"))
lazy val gettingStarted = sect("Getting Started")(twf("book/getting-started.tw"))
+ lazy val canvasApp = sect("Canvas App")(twf("book/canvas-app.tw"))
val txt = twf("book/index.tw")
val contentBar = {
def rec(current: Node, depth: Int): Seq[Frag] = {
@@ -66,6 +67,7 @@ object Book {
)
)
).render
+
object hli{
def javascript(code: String*) = hl.highlight(code, "javascript", inline=true)
def scala(code: String*) = hl.highlight(code, "scala", inline=true)
@@ -73,6 +75,7 @@ object Book {
def diff(code: String*) = hl.highlight(code, "diff", inline=true)
def html(code: String*) = hl.highlight(code, "xml", inline=true)
}
+
object hl{
def highlight(snippet: Seq[String], lang: String, inline: Boolean) = {
val string = snippet.mkString
@@ -120,7 +123,7 @@ object Book {
* }
*/
- def ref(filepath: String, identifier: String = "", indented: Boolean = true) = {
+ def ref(filepath: String, identifier: String = "", end: String = "", indented: Boolean = true) = {
val lang = filepath.split('.').last match{
case "js" => "javascript"
@@ -132,7 +135,9 @@ object Book {
println("??? " + x)
???
}
+
val lines = io.Source.fromFile(filepath).getLines().toVector
+
val blob = if (identifier == ""){
lines.mkString("\n")
}else {
@@ -140,10 +145,14 @@ object Book {
val whitespace = lines(firstLine).indexWhere(!_.isWhitespace)
val things =
lines.drop(firstLine + 1)
- .takeWhile{ x =>
- val firstCharIndex = x.indexWhere(!_.isWhitespace)
- firstCharIndex == -1 || firstCharIndex >= whitespace + (if (indented) 1 else 0)
- }
+ .takeWhile{ x =>
+ if (end == "") {
+ val firstCharIndex = x.indexWhere(!_.isWhitespace)
+ firstCharIndex == -1 || firstCharIndex >= whitespace + (if (indented) 1 else 0)
+ }else{
+ !x.contains(end)
+ }
+ }
val stuff =
if (!indented) {
@@ -158,10 +167,7 @@ object Book {
}
stuff.map(_.drop(whitespace)).mkString("\n")
}
-
pre(code(cls:=lang + " highlight-me", blob))
}
}
-
-
}
diff --git a/book/src/main/scala/book/Utils.scala b/book/src/main/scala/book/Utils.scala
index fbef8e8..54c9231 100644
--- a/book/src/main/scala/book/Utils.scala
+++ b/book/src/main/scala/book/Utils.scala
@@ -17,7 +17,8 @@ object Utils{
"css/pure-min.css",
"css/grids-responsive-min.css",
"css/layouts/side-menu.css",
- "js/ui.js"
+ "js/ui.js",
+ "example-fastopt.js"
)
val manualResources = Seq(
@@ -26,7 +27,8 @@ object Utils{
"images/Hello World White.png",
"images/Hello World Console.png",
"images/IntelliJ Hello.png",
- "example-fastopt.js"
+ "images/Dropdown.png",
+ "images/Scalatags Downloads.png"
)
val includes = for(res <- Utils.autoResources) yield {
@@ -80,4 +82,4 @@ object Utils{
def munge(name: String) = {
name.replace(" ", "")
}
-} \ No newline at end of file
+}