$ gnpm install external
External is a dual purpose library. It ships with a client-side framework renders third party or external pages in the most optimal way as possible. This is done using various of techniques:
But we also ship with a server-side framework implementation for BigPipe which makes it possible to serve the client and automatically format all the output in the expected HTML structure.
The client-side component is composed from various of tiny modules and can be
build using Browserify. It can be build-in to other browserify components by
simply requiring the external
module in your client-code.
The server side part of this framework can be installed through npm:
npm install external
In addition to providing a browserify-able client-side script there is also a
compiled version of this code which lives in the dist
folder called
extern.js
. This pre-compiled library exposes it self using the Extern
global
and therefor does not introduced require
statement as globals. In all the code
examples in documentation we assume that you have an Extern
global. If you use
the dist
build you can skip the following example:
var Extern = require('extern');
If you want to generate new stand alone bundles of the Extern library you can
run our prepublish
and dev
scripts using the npm run
command. These
commands do assume that you've installed the devDependencies
of this project.
To generate a new production build, dist/extern.min.js
run:
npm run prepublish
As this is a prepublish
script, it means that every release to npm will have
the dist/extern.js
included. So if browserify isn't your think, you can just
include the extern/dist/extern.min.js
instead.
To generate an un-minified build for development purposes you can run:
npm run dev
This will generate a new dist/extern.dev.js
file.
Now that you know how to install it and what type of bundles there are you can decide how to serve the library. When this module is used as plugin in BigPipe it will automatically serve the browserify and plugin combined bundle from:
http(s)://domain.com/extern.js
We also mount our dist
folder on the server so the static assets in this
folder can also be served:
http(s)://domain.com/extern.min.js
Now that you've picked your build, and know how the files are served you can simply put the script tag in your page and your ready to display external pages/apps.
<script src="https//yourdomain.com/extern.min.js"></script>
<script>
var extern = new Extern(document.body, 'http://whateverurlyouwantousehere.com/path/name');
</script>
The easiest way to have Extern
load your remote pages is by using the
Extern.listen
method in combination with the rel="extern"
attributes on
<a>
elements:
<a href="http://my-remote-server.com/optional/path" rel="extern">Remote</a>
The Extern.listen
method will gather all <a>
elements and search for a rel
that is set to extern
and uses the set href
of the element as URL that needs
to be remotely loaded.
Extern.listen(document.body, {});
The following options are supported:
timeout
Timeout for dependency loading. If assets take longer we should
render and error template instead. The timeout is in milliseconds.document
Reference to the document
global can be useful if assets need
to be loaded in iframes instead of the global document.className
If a link has this className we will automatically load it in
the placeholder. This className will also automatically be add and removed
once the link is clicked. Defaults to extern-loads
.var extern = new Extern('http://my.example.com/page', document.body, {
timeout: 10000
});
The returned extern
instance is actually an EventEmitter3
instance so you
can listen to the various of events that we're emitting:
error
as argument.name
part in the event should be name of the fragment you
want to listen for.The client code for each fragments are loaded through an XHR connection. This
way we can safely executed third party code by wrapping the execution in a
try/catch
statement. But not only does this allow us to wrap code, it also
allows us to introduce variables in the function. The following variables are
introduced as "globals":
React
, This is the react/addons
reference.require
, Reference to our require
statement so you can re-use all the
bundled things.The following properties and methods are exposed on the Extern instance.
Exposed on the constructor
Scan the current document for all <a rel="extern">
elements and attach click
listeners to it so we can automatically update the supplied placeholder with the
contents of the set URL. This method accepts one argument and that is the
placeholder
DOM element where all pages should loaded in
Extern.listen(document.body);
Exposed on the constructor
Merge the object of the second argument in to the first argument. It returns the fully merged first argument.
var x = Extern.merge({ foo: 'foo' }, { bar: 'bar' });
Exposed on the constructor
A reference to the requests
module that we're using for our XHR requests.
var requests = Extern.requests.
See unshiftio/requests for more information.
This library ships with a custom Fittings framework implementation for
BigPipe which allows us to control how everything is processed inside of
BigPipe. Adding it to your BigPipe instance is just as simple as passing a
custom framework
option while creating a new instance:
'use strict';
var BigPipe = require('bigpipe')
, Extern = require('external');
var app = BigPipe.createServer({
framework: Extern,
port: 8080
});
But the framework can also be set after the construction using the framework
method:
app.framework(Extern);
Please do note that the current Fittings implentation is in the BigPipe master branch but will out in the release that follows 0.9
Once the fittings are installed on the application, it will start spitting out responses based on the specified Wire Format below. The processing instructions can be found in the instructions folder in the root of this repository. But before fiddling with these files I would suggest giving the README.md of Fittings a read so you know how the data formatting works.
In order to have the broadest support within this framework we came up with a dedicated wire-format in order to have the server-side and client-side components interact with each other. While this wire-format is mostly catered to the needs of an application that is build using the BigPipe framework it should be relatively easy to produce exactly the same output in different frameworks and programming languages. This wire format is also required in order to make streaming data as simple as possible as we can trigger buffer flushes based on this.
The format that we're using is \u1337
separated JSON
. Every time we
encounter the \u1337
character on the client-side we assume it's the end of
chunk that requires processing. The JSON payload that is send should contain the
following properties:
_id
A unique id for the payload that is flushed.name
Name of the payload that is flushed. This is used to track
potential child->parent references throughout the flushed payload.details
An object that contains:
js
Array with path names for the JavaScript files that need to be
loaded on the page. We will automatically prepend the server address to
these assets.css
Array with path names for the CSS files that need to be
loaded on the page. We will automatically prepend the server address to
these assets.state
Additional state that will be spread on the component when we
render it.template
An initial HTML template that should be rendered in the given
placeholder.In order to be able to load CSS assets fully async in every browser we need to
know when the styles are applied. This is done by Extern client by adding a DOM
element to the page that has an id
attribute which contains _
and the filename of
the asset that is being downloaded (#_yourfilename
). We therefor require
that the CSS file contains CSS selector and sets the height
property to
42px
. This allows us to poll the element for height changes to know when the
CSS is fully loaded. So if we have a file called 1aFafa801jz09.css
it should
have the following selector in the source:
#_1aFafa801jz09 { height: 42px }
This project has been released under the MIT license, see [LICENSE].
Copyright 2013 - present © cnpmjs.org | Home |