03 - How freedom.js works

Note - this section isn’t integral to building a simple app, but it is valuable to get a slightly deeper understanding of the stack you are building on. You can safely skip to the next section if you wish, and potentially revisit here for reference as needed.

Understanding the boilerplate

Regardless of how you chose to do your dev setup, you should now have a file hierarchy that looks something like this:

src/freedom-module.js
src/freedom-module.json
src/index.html
src/page.js
src/static/freedomjs-icon.png
src/static/style.css

These files are your freedom.js module - they specify layout/browser logic (index.html and page.js), freedom.js application logic (freedom-module.js), freedom.js API and dependencies/permissions (freedom-module.json), and styling or other static resources such as graphics (static/). In the above list they all live off of src/ to reflect that they are the source code view of your application - they will later be copied to build/ (and possibly linted and minified in the process).

index.html and page.js work much like simple static web pages you may be familiar with - the browser renders the page according to the HTML and runs JavaScript logic directly in the browser (i.e. it can interact with the DOM - the page itself). You can think of this as the “front end” of your application, though it is important to understand that the “back end” (the freedom module) also runs on the client. The main difference is that the freedom module runs in a web worker that cannot interact directly with the DOM, and instead uses message passing defined by its API to interact with and update the webpage.

Web workers are a standard intended to enable the concurrent execution of multiple JavaScript threads - a prototypical use would be to calculate something computationally expensive (e.g. large prime numbers) while not interfering with the user interface. freedom.js uses these workers as module containers, which combined with an enforced API leads to a clearer picture of the behavior of the overall application.

The demo application you have from your setup is “Counter”, a simple example of how freedom modules run and pass messages. You should definitely be able to run the demo locally (either with the runserver.sh script or with grunt demo if you chose to use npm), but you can also view Counter at freedomjs.org for convenience.

The functionality of the application is simple - click the button to increment the displayed count. The key insight is that the displayed count is part of the webpage and is updated through the DOM, but the incrementing itself occurs in the freedom.js module. Following is the program flow - see if you can find the lines of code corresponding to each step (answers are linked but see if you can first find the spots without peeking).

  1. The browser loads the page and freedom.js is loaded with a given manifest (answer)
  2. freedom.js running in the browser creates the initial freedom module object (answer)
  3. The freedom module itself is instantiated from the given starting value (answer)
  4. The browser listens for clicks on the incrementing button (answer)
  5. The browser sends a message to the freedom module on receiving incrementing clicks (answer)
  6. The freedom module receives the message and returns the incremented value (answer)
  7. The browser receives the value back and updates the page (answer)

The above flow may seem painstakingly detailed for such a simple example, but it is wise to make sure you understand every step as they will be larger and more obfuscated in more complex applications. Overall, while all the code is running in the browser, you need to be able to envision the divide between the code that interacts with the DOM (in this case page.js) and the code that runs in a web worker (in this case freedom-module.js). The former is responsible for both updating the visible page and handling user interaction with it, while the latter is responsible for running whatever freedom.js application logic you create, storing state, and communicating that state wtih the code running directly in the browser. In this specific case, page.js knows about the button clicks and is responsible for updating the displayed count, while freedom-module.js knows the actual count value and increments and returns it when requested.

The above addresses the starter code that is directly part of a freedom.js module. Depending on your choice of tooling, you may also have files like:

Gruntfile.js
node_modules/...
package.json
.gitignore

These are best understood by looking up their respective documentation, as described below.

Other resources

Any piece of computer technology is inevitably built on a deep stack eventually going down to sand and physics - this tutorial focuses on giving you enough knowledge and context to develop freedom.js modules, but should you find yourself wanting to dig deeper then here are some places to start:

It’s also valuable to learn about developing traditional (centralized) web applications. freedom.js requires thinking differently (especially about data storage and peer communication), but it’s useful to understand both perspectives. There is a fair amount of skill overlap (understanding templates, network requests, etc.), and for many “real-world” use cases a hybrid approach of centralized and decentralized may be best. We will see this in the design of Dorabella, which pragmatically depends on centralized social networks as how most users keep track of and communicate with their friends.

02 - Dev Environment Setup --- 04 - Designing Dorabella