F is a client-side JavaScript architecture, which provides a base structure for Single-Page-Applications. It promotes modular development by providing an implementation of the proven principles of Scalable JavaScript Application Architecture outlined by legendary Nicholas Zakas in his talks on the subject.
Note
This begun as just an exercise of trying to take the concepts outlined in the talk and build something I could use on my apps.
It has not been tested in the wild, thus it should not be considered production-ready. If you're looking for something like this, that is more mature and production-ready, then you should definitely check out the T3 implementation made by Box in collaboration with Nicholas himself, linked in the Similar Projects section bellow.
- Decoupled application architecture
- Divide & conquer : each module implements only a functionality or a small set of functionalities
- Modules are independent : change/removal/failure of one does not affect the others
- Reusability : modules can be reused across a number of different applications
- Testing : modules can be tested individually both inside and outside of the application
The Core
contains the main application object that is the heart of
the application architecture.
Responsibilities:
- Manages the lifecycle of modules (registers, starts, renders and stops modules)
- Manages communication between modules using the PubSub/Mediator Pattern
- Manages the application state using Anchor Interface Pattern
- Manages application wide features/interfaces such as URL anchor (hash fragment), feature containers, cookies
- Manages Errors - Detects, traps, reports and handles errors in the system.
- Startup, Eventing, lifecycle, Placement
- Be extensible
Services
(referred as Extensions
in the talk) augment the
capabilities of the core to keep it relevant and useful.
Services
are loaded in your application when it starts. They allow
you to add features to the application, and are available to the Modules
through their Sandbox
or directly via Dependency Injection.
Services
have access to the base library and / or it's plugins,
like jQuery and jQuery plugins.
Services
are intended to be reusable pieces of code such as cookie
parsing, Ajax communication, string utilities, and so on.
The Sandbox
is an abstraction of the core that's an API for common
tasks, used by modules.
The Sandbox
uses the facade pattern
so that you can hide the features provided by the Core
and only show
a well defined custom static long-term API to your Modules
. This is
actually one of the most important concept for creating maintainable
apps -- change plugins, implementations, etc. but keep your API stable
for your Modules
.
For each Module
a separate Sandbox
instance will be created,
so that the Module
can interact with the Core
.
Responsibilities:
- Permissions manager - acts as a security guard for the modules, securing what modules can/can't access meaning it knows what a module can access and what cannot. It determines which parts of the framework the modules can access
- provide a dependable interface for modules
- translate module requests into core actions
- ensures a consistent interface for the modules - modules can rely on the methods to always be there
As defined by Nicholas Zakas,
a web application Module
is:
an independent unit of functionality that is part of the total structure of a web application, which consists of HTML + CSS + JavaScript and which should be able to live on it's own. It's each module's job to create a meaningful user experience.
A Module
is a completely independent part of your application which
has absolutely no reference to any another piece of the app, but the
Sandbox
, which it uses to communicate with the other parts of the
application.
Modules
can be easily started, stopped or restarted by the Core
.
They subscribe to notifications of interest and rapidly react to changes,
whilst also notifying the app when something interesting happens through
the Sandbox
.
Modules
manage Data
and Views
, though may not have actual objects
representing either. Views
are in turn formed by Widgets
, which are
reusable pieces of UI that contain no business logic or data, and can be
shared among many Views
.
The ideas around Modules
, Views
and Widgets
are pretty close to
rising ideas of Web components,
where our Modules
would play the role of the Parent/Controller-Views
.
Thus, we can implement them or just the child views using any of the
various libraries we desire like Riot, React, Polymer or BackBoneViews.
F's API only requires that the module provides the start
and
stop
methods so the Core
can manage the Modules
lifecycle, but
other than that its opened to the user the option to implement them
using whatever he likes.
Responsibilities:
- Provides a well-scoped capability to the application.
- Creates and manages its own content (typically HTML and SVG) in a
container provided by the
Sandbox
- Provides a consistent API to the
Core
/Sandbox
for configuration, initialization, and use. - Is kept isolated from other features by using unique and coordinated
JavaScript and CSS namespaces, and by not allowing any external calls
except to shared utilities (
Extensions
).
A good Module
implementation should abide by these rules:
- only call your own methods or those in the
Sandbox
- don't access DOM elements outside of your box
- don't access non-native global objects
- anything else you need ask the
Sandbox
- don't create global objects
- don't directly reference other
Modules
Module
s only know theSandbox
, the rest of the architecture doesn't exist to them- Manage data and views
One thing that must be beared in mind, is that Modules can and are comprised of other smaller components/widgets. The key thing that will turn a component into a module is it's significance and the features it provides to the user under a given context. For instance, if we look at a text message component, when considering if it's a module or not the questions we have to ask are:
- can it live on it's own?
- does it provide a significant feature or meaning on it's own.
So, a Module
will be a set of components that provide a functionality
as a whole and which can live on it's own on the page as a whole.
F requires the dependencies listed bellow. As long as you have them, just download the recent-most release from the releases page and include it in your page.
Also check out the examples listed in bellow, they provide a good hint on how to use the framework.
no dependencies ;D
Note
Although the example uses Riot for the views and Navigo for routing, they're not dependencies of the framework, it's just an example using them, but it could be anything else.
- Todos - An implementation the famous TODOs app by
TODO MVC.
- Start a simple HTTP Server (like
python -m SimpleHTTPServer
for example) from the root of the project and browse it. - Navigate to the
examples/todos
folder and it should show up.
- Start a simple HTTP Server (like
Code and documentation are available according to the MIT License.
See the LICENSE file for details.