Git Product home page Git Product logo

brisket's Introduction

Brisket

Build Status Code Climate

For changes see the Changelog. You can also find older versions at 0.x

About Brisket

Brisket is a framework for building single page web apps using isomorphic JavaScript. A Brisket app is both a traditional web site AND a single page web application at the same time. Brisket provides the tools that you need to spend your time focusing on your application's logic rather than on "what environment is my code running in?".

Getting Started

Using generator-brisket is the fastest way to get started.

Install Yeoman:

npm install -g yo

To install generator-brisket from npm, run:

npm install -g generator-brisket

Create a directory for your app:

mkdir projectname
cd projectname

Finally, initiate the generator and run your app:

yo brisket && npm start

Your first brisket app will be available at http://localhost:8080

Getting More Started

Now that you have a working app, check out our Recipes for common use cases.

Documentation

Brisket Concepts And High Level Systems

Brisket's Parts

  • Brisket.App: Initialize your application with Brisket.App.
  • Brisket.createServer: A function that returns an express engine that you can use in your application to run the server.
  • Brisket.Router: An implementation of Backbone.Router that routes on client and server.
  • Brisket.Events: A proxy to Backbone.Events that exposes a noop on the server to avoid server-side memory leaks.
  • Brisket.View: Our version of a Backbone.View that allows support for some of the core features - reattaching views, child view management, memory management, etc.
  • Brisket.Layout: A specialized View that handles meta tags, page title, etc.
  • Brisket.Templating.TemplateAdapter: Inherit from this to tell Brisket how to render templates.
  • Brisket.Templating.StringTemplateAdapter: The default template adapter. Set a View's template key to be a string template to get started.
  • Brisket.version: The version of Brisket. On the client, the version can be accessed by window.Brisket.version.
  • Brisket.onError: Registers error callback.

Using Brisket in your project

Install the Brisket into your project:

npm install brisket --save

Bundling your Brisket application

Check the Bundling With Browserify Recipe!

Compatibility and Requirements

Please refer to package.json for Brisket's dependencies

Node.js Support

Brisket officially supports Node.js >=4.0.0 i.e. it is tested in the latest versions of Node. However Brisket likely works with Node 0.10.0, 0.11.0, 0.12.0, and io.js >=3.0.0.

Browser Support

Chrome, Firefox, Safari, iOS 6+, Android 4+, Internet Explorer 9+

For support in older versions of IE you can include your favorite shim libraries in the head of your layout. For example to support IE8 include the following in your head tag:

<!--[if lt IE 9]>
    <script type='text/javascript' src='//cdnjs.cloudflare.com/ajax/libs/es5-shim/2.3.0/es5-shim.min.js'></script>
    <script type='text/javascript' src='//cdnjs.cloudflare.com/ajax/libs/es5-shim/2.3.0/es5-sham.min.js'></script>
<![endif]-->

To support IE7, include the snippet above AND the following:

<!--[if lt IE 8]>
    <script type='text/javascript' src='http://cdnjs.cloudflare.com/ajax/libs/json3/3.3.1/json3.min.js'></script>
<![endif]-->

Note: In IEs < 10, the single page app functionality that Brisket provides will not work since pushState is not available. Brisket does not support hash tag SPA's. When the SPA functionality is disabled, Brisket will operate like a standard website i.e. clicking application links will cause a page reload.

Development

Install dependencies:

$ npm install

To run the test suite:

$ npm test

To run benchmarks:

$ npm run benchmarks

Troubleshoot

jsdom error with Legacy Node.js and io.js

For Node.js 0.10.x, 0.11.x and 0.12.x, specify the version of jsdom to be v3.x,

rm -rf ./node_modules/brisket/node_modules/jsdom
npm install jsdom@3 --save

For io.js, specify the version of jsdom to be v6.x,

rm -rf ./node_modules/brisket/node_modules/jsdom
npm install jsdom@6 --save

License

Apache License (Version 2). See license text in LICENSE.

Copyrights and Names

Brisket originated at Bloomberg Finance LP. The name 'Brisket' is a service mark of Bloomberg LP.

brisket's People

Contributors

ankurp avatar claquesous avatar davydog187 avatar ericherdzik-zz avatar ggentzke avatar joezimjs avatar kpfleming avatar leochen1216 avatar prayagverma avatar rosslitscher avatar stephenbaldwin avatar sylnp0201 avatar wawjr3d avatar zanesterling avatar zomaish avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

brisket's Issues

Brisket.random

As a developer,
I want to execute code randomly, but still have view reattaching working correctly,
So that I can satisfy use cases that require random execution

Acceptance

  • Bison makes a method available that returns a random value
  • The random value is memoized so that, for the current server/client request, when code runs on the client, it executers exactly the same as it did on the server

Ability to get value from cookies

As a developer,
I would like to be able to get a value for a cookie on the server,
I would like to be able to get a value for a cookie on the browser,
So that I can provide functionality based on the value of a cookie

Acceptance Criteria:

  • identical interface for both server and client

Better error handling for route delegation

As a Brisket user, I would like Brisket to tell me nicely not to abuse routers, rather than crashing randomly.

>> [2015-10-19T15:41:20.694Z|39734] TypeError: Cannot read property 'host' of undefined
>>     at Object.ServerRequest.from (/Users/dlucia/Development/business/node_modules/brisket/lib/server/ServerRequest.js:14:41)
(/Users/dlucia/Development/business/node_modules/brisket/lib/server/ServerRenderingWorkflow.js:17:47)

My use case was experimenting with default values in a route. I set up two routes in my router.

routes: {
   routeOne: "routeWithDefault",
   routeTwo: "routeWithoutDefault"
},

routeWithDefault: function() {
   this.routeWithoutDefault("defaultValue");
},

routeWithoutDefault function(value) {
   MyController.doSomething(value);
}

While one could argue that the Controller is the correct place for the defaulting logic, I still think Brisket should provide a more meaningful error message in this case.

Remove need to shim jquery-mockjax

As a user, it is inconvenient for me to have to shim jquery-mockjax in my Brisket application for bootstrapped data to work.

Acceptance Criteria Bootstrapped data functions correctly without the consumer having the shim any libraries.

Brisket response object

As a developer,
I would like a way to manage the response for a request from a route handler,
So that the user's response correctly reflects the user's request and application state

Acceptance criteria

  • Expose a response object to route handlers
  • response object api should be normalized across client/server
  • behavior of functionality provided by response object should work "as expected" in the environment it is used (i.e. a redirect on the server should respond with 302 and show another route's content, while on the client, the redirect should just show another route's content)
  • eventual desired functionality includes redirecting, setting cookies, setting status code
  • ideally developer does NOT have direct access to express response object (don't want them to destroy their own response by setting response to another object)

Separate Components

I was wondering if using the approach that Ampersand uses would be wise. Ampersand separates each of their components into separate packages so each component can be loaded individually and be updated independently.

Custom page transitions

As a developer,
I would like to specify how to transition from one route to another,
So that I can delight my users

Background
Currently, you can use onRouteStart and onRouteComplete in your Routers to make some transitions. Assume the main View for first route is A and main View for second route is B.

What you can do now - using onRouteStart and onRouteComplete, you can make any transition where only A is visible and then only B is visible e.g. "fade out the entire content well, then fade it back in when B is ready"

What you cannot do now - any transition where A and B are visible at the same time. The Renderers replace views by closing one, then rendering the other i.e. close A, then render B in it's place. There are currently no hooks to manage how replacement happens.

Ability to use a framework on top of Brisket

As a developer,
I would like to be able to use a framework on top of Brisket's base libraries,
So that I can use a framework that I'm familiar with,
So that I can still get the Brisket goodness

Acceptance
I can use frameworks like Marionette on top of Brisket

Note
The goal of this issue is to make libraries "Brisketable". For example if I have a framework that includes a View called ExampleView, which inherits from Backbone.View, there should be a way to set it up to inherit from and operate as a Brisket.View without clobbering any of its functionality

Expose environment config to route handlers

Currently, only the Layout has access to the environment config. It is definitely possible that a user could want access to the environment config at any point during the handling of a route, so we should make it available there.

Bootstrap data with the same key is re-fetched

When there are two (or more) requests on the page to the same data url, the later request overwrites the bootstrap data of the first one. Then the front end application tries to re-fetch the data with an unnecessary ajax call.

Better place to put initializers that happen on client AND server

If you need to initialize something only in the browser, that can go in the ClientApp. If you need to initialize something only in the browser, that can go in the ServerApp. If something needs to be initialized in both places, right now, the code needs to go in ClientApp AND ServerApp. There should be another way to initialize code for client and server without having to write it twice

Choose layout data at the Routing/Controlling layer

As a developer,
I would like to choose the data for the layout from my routers,
So that different routes can provide the layout with different data

Acceptance

  • At the Router level, there should be a way to specify how to fetch data for the layout (e.g. if you have a preview router, there should be a way to provide preview data to the layout)
  • At the RouterBrewery level, there should be a way to specify how to fetch data for the layout so you can set defaults

Upgrade to Backbone >= 1.2

Make the necessary changes in Brisket to upgrade to backbone >= 1.2 (http://backbonejs.org/#changelog). The biggest changes will be to decouple from jQuery by default, provide hooks to continue to use jQuery if user wants to, have a new solution for server side rendering.

Support Canonical Tag Element

Similar to the other metatags, Brisket should support the canonical link tag with the format of

<link rel="canonical" href="http://www.blabla.com/example-path" />

Install Issues....

You guys really need to work simpler installation..

What if I dont want to use yeoman, grunt, bower? This project assumes
that all of these sys-admin dependancies are available. They may not be.

Kudo's on choosing BackBonejs, but cant install everything cleanly. I dont
want to corrupted the global NPM namespace with all the pre-install
dependancies.

Fast clicking on initial load breaks the page

If you go to a brisket app and click on a link fast enough (i.e. after brisket app has started but before the initial page load completes), the page breaks. In this case "breaks" means that the url updates but a new page is never rendered.

Based on my early analysis, the root cause is a flaw in the ClientRenderingWorkflow logic that causes the layout not to be initialized correctly.

Brisket Version in the Console

As a developer, I want a quick way to check the version of the Brisket serving the application. One option is to allow the application to output the version of Brisket in the console output.

closeChildViews should happen automagically

As a developer, I want all child views to be closed when their parent view is to be close. Currently, it's required to put the following code in the parent view:

onClose: function() {
    this.closeChildViews();
}

This is almost always the case whenever the view has child views. Making it happen automagically not only cut the coding burden, but also reduce the risk of memory leak when it's missed.

Performance Benchmark

Since brisket is being advertised as being super fast there should be a benchmark against other popular frameworks so that as a user I can better compare if it's worth using for my next app. At the moment I have no view as to whether its more performant than say the original Backbone.js, Angular.js or React.js

Also it's stated in your readme that brisket depends on:

jQuery ~1.11.1
jsdom ~0.11.1
Underscore ~1.6.0
Backbone ~1.1.2
bluebird ~2.2.1
jquery-mockjax ~1.5.3
express ~4.0.0
qs 1.2.2

This does not sound performant to begin with - with so many key external dependencies. Instead these could be broken down to only use specific modules e.g. only jQuery ajax, and particular _ functions that are required, rather than loading the entire library.

I'm sure you'll do performance sprints in the future so this could be food for thought.

Bootstrap data does not correctly support requests with query params

If you do an ajax call with query parameters on the server, the params are not reflected in the bootstrapped data at the bottom of the page on initial load. this could clobber two requests with different params e.g.:

/data/request?param1=value1

AND

/data/request?param2=value2

may both be in the bootstrapped data hash like this:

{
"/data/request": { some: "data" },
"/data/request": { "someOther": "data" }
}

This could lead to the initial bootstrapping working incorrectly

Update meta content on route

It would be good to update the meta content of a page on route update so that JS reading such meta content at runtime will have the meta content of the current view.

Running "exec:nodemon" fails under Windows 8.1 x64

Hi,

I'd like to share my findings about the problem I encountered while playing around with Brisket 0.29.0.


After setting up a simple project by following the README the Grunt task exec:nodemon refused to work:

'node_modules' is not recognized as an internal or external command,
operable program or batch file.
Exited with code: 1.
Warning: Task "exec:nodemon" failed. Use --force to continue.

Well, node_modules is never a command, if I'm not mistaken. ๐Ÿ˜ธ

So, I checked the Gruntfile.js and my first assumption was that the the problem was in the path of nodemon server.js (line 49).

Therefore I changed it from

cmd: 'node_modules/.bin/nodemon server.js'

to

cmd: './node_modules/.bin/nodemon server.js'

But, no luck. ๐Ÿ˜ญ

My "solution" was to uninstall the preinstalled nodemon package from my project's node_modules/.bin and install it again, globally.

npm i -g nodemon

Now, grunt works.

Running "concurrent:server" (concurrent) task
Running "exec:nodemon" (exec) task
Running "watch" task
Waiting...
22 Feb 01:10:18 - [nodemon] v1.3.7
22 Feb 01:10:18 - [nodemon] to restart at any time, enter rs
22 Feb 01:10:18 - [nodemon] watching: .
22 Feb 01:10:18 - [nodemon] starting node server.js
My favorite town is Brisket Town
My favorite server is a plate
ServerApp has started
Brisket app is listening on port: 8080

Expose functionality to trigger a route

As a developer,
I would like to be able to trigger a route,
So that I can refresh the current route

Currently, Brisket will not execute the route for a link if the user is already on that route.

Acceptance Criteria:
I can call a function and pass a route and the route is fully executed.

Annotate server code as "noop" on the client

Consumers of Brisket will want to use modularization tools such as Browserify to bundle their application. Brisket needs to provide metadata to these tools to make server side code a noop in the browser.

callback for when request is visible

As a developer,
I want to now when my request is visible,
So that I can avoid doing work that the user will never see

Some of the use cases:

  • Tracking
  • Detecting user activity
  • Fetching additional data for lazy loading

Add applicationPath

Need the ability to add an application path to handle environmental path differences. For example, in one environment the path might be /foo/ while in another environment the path is /bar/foo/. We should be able to account for that without needing to use a regex in a router.

Separate Express adapter into plugin

As a developer,
I would like to have the Express adapter available as a Brisket plugin,
So that I can easily startup an app with Express,
So that I can use another routing framework if I wanted to

A.C.

  • Express not shipped with Brisket
  • Express plugin as easy to integrate as Hogan adapter

Local event bus for a view

As a developer, I would like to create a Brisket View with the option of using an event bus local to it and its children
so that I can design my application knowing that if a child view triggers an event, only its siblings and parent are able to listen to that event.

Background
A lot of the applications right now, implement a global event bus to manage event handling. Developers may not fully understand the implications of using a global event bus. Consider the following use case -

I have multiple instances of a view (type X) on the page. X has a child view of type Y. Y triggers an event and X listens to that event and handles it. The event uses a class selector as part of the definition.
With a global event bus implementation, if the event is triggered by one instance of Y, the event handler of each instance of X is invoked.

A workaround to this of course, is to set an ID for the view, and pass this on to child views as well. All event names will be namespaced with the view ID dynamically. This works, but is error prone and not very DRY. Hence the idea for the option to create a view with a local event bus.

Layout is regular View

As a front end engineer,
I would like to be able to use different layouts for different routes in the browser,
So that I can separate responsibilities between layouts

Views in my templates

As a developer,
I want to place my child views in my template,
So it's easier to see how all the pieces fit together

view.closeChildViews should also remove html

  • view.closeChildViews doesn't remove html code.
  • It should remove root element first and loop through its children to optimize client rendering performance. (need to make sure no memory leak)

Rendering a View with an iframe in it causes a memory leak on server

If a View's template includes an iframe, rendering it on the server causes a memory leak. Here's an example of a View that can create a server-side memory leak:

var LeakingView = Brisket.View.extend({
  template: '<iframe src="about:blank"></iframe>'
});

To test i used a simple Brisket app with a route "/has-leaking-view", the following scripts, and my Mac's activity monitor:

hit.js

var Promise = require('bluebird');
var request = Promise.promisify(require('request'));

var count = 0;

function ping() {
  return request("http://localhost:8080/has-leaking-view")
    .then(function(response) {
        console.log("");
        console.log("");
        console.log(count++);
        return ping();
  });
}

ping();

hitters.sh

echo "Spawning 60 processes"
for i in {1..60}
do
    ( node hit.js & )
done

I put hit.js and hitters.sh in the same directory and run ./hitters.sh. If you look at the activity monitor, you can see that the memory usage increases very quickly and never goes down.

Compress bootstrap data json

As a developer,
I want bootstrap data to be as small as possible,
So that my users get all the benefits while not feeling the impact of additional content sent down the wire

Acceptance

  • Bootstrap data is compressed on the server, then unpacked losslessly on the client

Add ability to easily add page-level customizations

We have recently looked to have the ability to add other page-level changes (e.g. link tags, body classes, etc) triggered by a view similar to how meta tags and page title are handled.

It would be great to be able to have something similar to renderMetaTags/renderPageTitle and how that whole workflow works, but have it for anything we want to be page-level (e.g. renderPageElement, withPageAttributes, etc).

It would also be helpful if setExtraRenderInstructions/executeRenderInstructions would be passed in the view which would allow us to achieve similar, if not same results.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.