You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: doc/internals/compile-opt-pipeline.md
+49-54Lines changed: 49 additions & 54 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,22 +7,21 @@ title: Compilation and optimization pipeline
7
7
From Scala source files to optimized JavaScript code, there are a few steps
8
8
which are described in this document.
9
9
10
-
**compiling*: compile .scala files to 1 .js file per class using the scalac
10
+
**compiling*: compile .scala files to 1 .sjsir file per class using the scalac
11
11
compiler with the Scala.js compiler plugin.
12
12
13
-
For libraries, it stops here. The compiled .js files, their source maps and
14
-
the .sjsinfo files are put together with .class files in the binary jars that
13
+
For libraries, it stops here. The compiled .sjsir files are put together with .class files in the binary jars that
15
14
can be published to an Ivy or Maven repository.
16
15
17
16
For the application project, one more mandatory step creates 1 or 3 .js files
18
17
consumable by browsers. Then an optional step can be used to optimize the
19
18
result.
20
19
21
-
**linking* all the .js files together, including those in transitive
20
+
**linking* all the .sjsir files together, including those in transitive
22
21
dependencies. This is either one of:
23
-
**packaging*: concatenate blindly all compiled .js files in 3 big .js files.
24
-
**preoptimizing*: apply a type-aware inter-method global dead code
22
+
**fastoptimizing*: apply a type-aware inter-method global dead code
25
23
elimination that results in 1 preoptimized .js file.
24
+
**packaging*: concatenate blindly all compiled .sjsir files in 3 big .js files. This used to be the default in earlier versions of Scala.js. Packaging is discouraged and might fall away in future versions since the fast optimization is now faster.
@@ -33,29 +32,51 @@ Compilation is similar to using the Scala compiler daily. .scala source files
33
32
are compiled with incremental compilation by the Scala compiler. They can
34
33
depend on external libraries or other projects in the build, as usual.
35
34
36
-
The Scala.js compiler plugin produces .js files in addition to the .class files
37
-
generated by scalac. Roughly one .js file is produced for each .class file.
38
-
(Sometimes, fewer .js files are necessary when the compiler can optimize
35
+
The Scala.js compiler plugin produces .sjsir files in addition to the .class files
36
+
generated by scalac. Roughly one .sjsir file is produced for each .class file.
37
+
(Sometimes, fewer .sjsir files are necessary when the compiler can optimize
39
38
anonymous function classes as JavaScript functions.)
40
39
41
-
For each class, three files are emitted:
40
+
An .sjsir file contains a Scala.js specific intermediate representation. You may use `scalajsp` from the Scala.js [CLI]({{ BASE_PATH }}/downloads.html) to display it in a human readable form.
42
41
43
-
*`TheClass.js`: the JavaScript code for the class, its methods, its runtime
44
-
class data, and, for module classes, the module accessor.
45
-
*`TheClass.js.map`: the source map linked to `TheClass.js`.
46
-
*`TheClass.sjsinfo`: additional information used by the linkers (packaging or
47
-
preoptimizing).
48
-
49
-
These files are bundled together with .class files in jars published on Ivy or
42
+
The .sjsir files are bundled together with .class files in jars published on Ivy or
50
43
Maven repositories.
51
44
52
45
This step completely supports separate compilation and incremental compilation,
53
46
just like the regular Scala compiler.
54
47
48
+
## Fast Optimzing
49
+
50
+
The size of the JavaScript files produced by blindly concatenating .sjsir files are huge.
51
+
They are always bigger than 20 MB because they include the full Scala standard
52
+
library.
53
+
But typically, only a small fraction of the libraries you depend on are
54
+
actually used.
55
+
56
+
Fast optimizing is a task that identifies all the classes and methods reachable
57
+
from a given set of entry points, and removes everything else.
58
+
Entry points are classes and methods that are
59
+
[exported to JavaScript]({{ BASE_PATH }}/doc/export-to-javascript.html).
60
+
61
+
The fast optimizer uses information stored by the compilation step in .sjsir
62
+
to derive a reachability graph from the entry points.
63
+
Then it produces a single .js file containing all the code that is actually
64
+
useful (or, since in theory the algorithm computes an over-approximation, all
65
+
the code that could not be proved to be useless).
66
+
67
+
In sbt, the fast optimizing task is called `fastOptJS`. The result of
68
+
fast optimization is typically between 1.5 MB and 2.5 MB.
69
+
70
+
The fast optimizer can also be called programmatically using the class
Packaging is the simplest form of linking. Conceptually, it simply takes the
58
-
.js files generated by the compilation step for all the transitive dependencies
76
+
**Packaging is discouraged, since fast optimizing has become faster. This section is for information only, as packaging can be useful for very specific use-cases.**
77
+
78
+
Packaging is the simplest form of linking. Conceptually, it simply takes the JavaScript code in the
79
+
.sjsir files generated by the compilation step for all the transitive dependencies
59
80
of the project and concatenates them.
60
81
There are however 2 subtleties: a decomposition in 3 files for performance,
61
82
and an ordering for correctness.
@@ -75,13 +96,13 @@ code that changes on every single dev cycle are in the project itself, which
75
96
are the *exported products* of the project.
76
97
77
98
The packaging takes advantage of this obversation by producing 3 .js files
78
-
instead of just 1: `app-extdeps.js` contains the external dependencies,
79
-
`app-intdeps.js` contains the internal dependencies, and `app.js` contains the
99
+
instead of just 1: `app-pack-extdeps.js` contains the external dependencies,
100
+
`app-pack-intdeps.js` contains the internal dependencies, and `app-pack-app.js` contains the
80
101
exported products.
81
-
`app-extdeps.js` is typically very large (the Scala standard library itself
102
+
`app-pack-extdeps.js` is typically very large (the Scala standard library itself
82
103
accounts for more than 20 MB of JavaScript code), but need not be repackaged
83
104
often.
84
-
`app.js` has to be repackaged on every single dev cycle, but contains
105
+
`app-pack-app.js` has to be repackaged on every single dev cycle, but contains
85
106
relatively much fewer code, and so this is fast.
86
107
87
108
### Ordering
@@ -90,48 +111,22 @@ The internal structure of the produced .js files imposes a constraint on the
90
111
order in which they are packaged. A class must always be packaged after its
91
112
superclass (and hence, transitively, all its superclasses).
92
113
93
-
To do so, the .sjsinfo file contains (among other things), the number of class
114
+
To do so, the .sjsir file contains (among other things), the number of class
94
115
ancestors of each class. Since a subclass *A* of a superclass *B* has at least
95
116
one more ancestor than *B* (namely, *B*), it is sufficient, to guarantee the
96
117
required ordering, that classes with more ancestors are ordered after classes
97
118
with less ancestors.
98
119
99
-
## Preoptimizing
100
-
101
-
The size of the JavaScript files produced by packaging are huge.
102
-
They are always bigger than 20 MB because they include the full Scala standard
103
-
library.
104
-
But typically, only a small fraction of the libraries you depend on are
105
-
actually used.
106
-
107
-
Preoptimizing is a task that identifies all the classes and methods reachable
108
-
from a given set of entry points, and removes everything else.
109
-
Entry points are classes and methods that are
110
-
[exported to JavaScript]({{ BASE_PATH }}/doc/export-to-javascript.html).
111
-
112
-
The preoptimizer uses information stored by the compilation step in .sjsinfo
113
-
to derive a reachability graph from the entry points.
114
-
Then it produces a single .js file containing all the code that is actually
115
-
useful (or, since in theory the algorithm computes an over-approximation, all
116
-
the code that could not be proved to be useless).
117
-
118
-
In sbt, the preoptimizing task is called `preoptimizeJS`. The result of
119
-
preoptimization is typically between 1.5 MB and 2.5 MB.
120
-
121
-
The preoptimizer can also be called programmatically using the class
0 commit comments