SproutCore

SproutCore Guides

These guides are designed to help you write and perfect your code.

SproutCore's Build Tools

After reading this guide, you will be able to:

  • Create a new SproutCore project skeletons using sproutcore init.
  • Add additional apps to a SproutCore project and additional views, controllers, models and unit tests to a SproutCore app using sproutcore gen.
  • Configure your apps using Buildfiles.
  • Use SproutCore's server and proxy, sproutcore server, for development and testing.
  • Build a SproutCore app for production deployment using sproutcore build.

1 - Introduction

One of the least understood and, because of this, occasionally maligned components of SproutCore are the accompanying build tools. Let's be clear, build tools are absolutely necessary for even the smallest project and to attempt to write an application without them from the start, simply means being forced to cobble together less effective processes later on.

The reason for this is it quickly becomes too difficult and time consuming to manage multiple source files and assets; there are several important optimizations required for deploying top-of-class web experiences that are best left to automated scripts.

For example, SproutCore's build tools do the following and more:

  • Automatically scans your source code and builds a manifest of how your code should be built into a final project. This ensures that your JavaScript and CSS always load in the proper order.
  • Run stylesheets through the Compass CSS Authoring Framework for simple and clean CSS.
  • Proxies XHR requests to avoid same-origin policy restrictions while developing.
  • Applies localization rules to automatically build different language variations of your project.
  • Inserts cache-friendly URLs on build for any assets (such as images) that you may want to load.
  • Builds your JavaScript files and stylesheets into a single JavaScript and a single CSS file and minifies the contents of each. This makes your deployed app load much faster since multiple smaller requests are slower for the clients.
  • Automatically slices and sprites your images; a typically very time-consuming and error prone task.

For a list of the available commands, type sproutcore on the command line after installing the SproutCore gem:

$ sproutcore SproutCore 1.9.2 Usage ====================== Tasks: sproutcore build [TARGET..] # Builds one or more targets sproutcore build-number TARGET # Computes a build number for the target sproutcore docs [TARGET..] # Generates JSDoc's for specified targets. sproutcore gen generator Namespace[.ClassName] [--target=TARGET_NAME] [--filename=FILE_NAME] # Generates SproutCore components sproutcore help # How to use the sproutcore command sproutcore help [TASK] # Describe available tasks or one specific task sproutcore init PROJECT [APP] # Generates a SproutCore project with an initial appl... sproutcore manifest [TARGET..] # Generates a manifest for the specified targets sproutcore server # Starts the development server sproutcore version # Show the SproutCore version number Options: [--project=PROJECT] [--mode=MODE] [--logfile=LOGFILE] -b, [--build=BUILD] [--build-targets=BUILD-TARGETS] # Targets to build (excluding their dependencies) [--dont-minify] # Disables minification for the build. -v, [--verbose] -V, [--very-verbose] [--help]

2 - Generating a New SproutCore Project: sproutcore init

To create a new basic SproutCore project simply use sproutcore init or its short form equivalent, sc-init, and supply a project name and optional initial app name. If you don't supply the AppName parameter, an app with the same name as the project will be created. For example, to create a project "MediaTools" with the default app "VideoEditor" use the following:

$ sproutcore init MediaTools VideoEditor ~ Created directory at media_tools ~ Created file at media_tools/Buildfile ~ Created file at media_tools/README ~ Created directory at apps ~ Created directory at apps/video_editor ~ Created file at apps/video_editor/Buildfile ~ Created file at apps/video_editor/core.js ~ Created file at apps/video_editor/main.js ~ Created directory at apps/video_editor/resources ~ Created file at apps/video_editor/resources/_theme.css ~ Created file at apps/video_editor/resources/loading.rhtml ~ Created file at apps/video_editor/resources/main_page.js ~ Created file at apps/video_editor/theme.js Your new SproutCore project is ready! To get started, you can find your initial application in the "apps" directory.

To create a project "Calculator" with an app of the same name, simply use:

$ sproutcore init Calculator ~ Created directory at calculator ~ Created file at calculator/Buildfile ...

To create a project "BusyBee" with an app of the same name with a base statechart, simply use:

$ sproutcore init BusyBee --statechart ~ Created directory at busy_bee ~ Created file at busy_bee/Buildfile ...

Passing a camelcase app name to sproutcore init, such as VideoEditor — notice the uppercase 'E' — creates a namespace VideoEditor and the directories are named using underscores (i.e. apps/video_editor).

3 - Generating Additional SproutCore Files: sproutcore gen

The command sproutcore init creates a few default files for you that form a typical starting point for a new project, but you will soon need other files and this is where the command sproutcore gen or sc-gen, for short, can come in. The following are the most commonly used commands with a brief description of each.

3.1 - sc-gen project ProjectName

Creates an empty SproutCore project. You may use this instead of sproutcore init, if you don't want a default app to be created.

3.2 - sc-gen app AppName

When called from within a project, adds an app to the project with the namespace AppName.

3.3 - sc-gen statechart_app AppName

When called from within a project, adds an app with a basic SC.Statechart setup.

Similar to generating basic statechart files with sproutcore init --statechart you can achieve the same result with sproutcore gen app --statechart.

3.4 - sc-gen model AppName.ModelName

Adds a SC.Record subclass, 'AppName.ModelName', in the file model_name_model.js along with stub fixture and unit test files.

3.5 - sc-gen controller AppName.ControllerName

Adds a SC.ObjectController subclass instance, 'AppName.controllerName', in the file controller_name_controller.js and a stub unit test file.

3.6 - sc-gen view AppName.ViewName

Adds a SC.View subclass, 'AppName.ViewName', in the file view_name_view.js and a stub unit test file.

3.7 - sc-gen data-source AppName.DataSourceName

Adds a SC.DataSource subclass, 'AppName.DataSourceName', in the file data_source_name.js.

3.8 - sc-gen language AppName.Language

Adds a language file for 'Language', in the file language.lproj. Here are some examples:

$ sc-gen language MediaTools French ~ Created directory at french.lproj ~ Created file at french.lproj/strings.js $ sc-gen language MediaTools en-ca ~ Created directory at en_ca.lproj ~ Created file at en_ca.lproj/strings.js $ sc-gen language MediaTools Latin ~ Created directory at Latin.lproj ~ Created file at Latin.lproj/strings.js

Generally the provided 'Language' will result in the same named directory, 'Language.lproj', but as can be seen by the French example above, the build tools have a bit of an odd behavior of recognizing English, French, German, Italian, Spanish and Japanese as parameters and making the directory name the lowercase version.

3.9 - sc-gen framework FrameworkName

Creates a framework with namespace FrameworkName in the project's frameworks directory. Read further to learn about including frameworks in your SproutCore apps.

4 - Configuring SproutCore Applications: Buildfile

The operations of the build tools are configured via the project, framework and app Buildfiles. If you used the previous commands, you will find a Buildfile within your root project directory and a Buildfile in each of your app directories. As it states in the default app Buildfiles, the settings in the app Buildfile will override the project Buildfile.

Therefore, a recommended setup would configure properties shared between all your apps within a project in the project's Buildfile and to configure any properties specific to an app, in the app's Buildfile. For simplicity state, the following examples will just use a single Buildfile in most cases.

Before looking at each config setting in detail, there is one important statement, mode, that is valuable to understand. Any configurations within a mode #{name} block will only apply to the named environment. By default, sproutcore build uses the mode production and sproutcore server uses the mode debug, but you may provide any custom mode by passing --mode=my_mode to the command.

The following list describes the most common Buildfile config properties.

4.1 - :build_number => {String}

By default, the build project assets will get cache friendly paths containing a unique build number. This is necessary to ensure that the files are properly cached, but you can specify a custom build number with this setting.

Using a fixed build_number will cause cached assets to not be invalidated. Use this setting with caution.

4.2 - :combine_javascript => {Boolean}

By default, the built project combines all the JavaScript files into a single file. Setting :combine_javascript to false will prevent this from happening, which may be useful for debugging purposes.

4.3 - :combine_stylesheets => {Boolean}

By default, the built project combines all the CSS files into a single file. Setting :combine_stylesheets to false will prevent this from happening, which may be useful for debugging purposes.

4.4 - :javascript_libs => {Array}

An array of JavaScript file URLs that will be inserted as the src attributes of <script> tags in the <head> element.

Ex. Including the Google Maps API:

my_project/apps/my_app/Buildfile
config :my_app, :javascript_libs => [ 'https://maps.googleapis.com/maps/api/js?v=3&sensor=false' ]

4.5 - :layout => {String}

By default, SproutCore apps use the index.html template in the SproutCore framework at lib/index.rhtml. You may copy the default index.rhtml file into your app and specify the path in your Buildfile.

Failing to update your copy of index.rhtml when SproutCore is updated, may cause conflicts with the build tools. Therefore it is recommended to use the config parameters to modify the generated index.html, rather than modifying the template directly.

4.6 - :load_debug => {Boolean}

By default, directories named debug are not included in the built project. Set :load_debug to true to have them included.

4.7 - :load_fixtures => {Boolean}

By default, fixtures are excluded in the built project. Set :load_fixtures to true to have them included.

4.8 - :load_protocols => {Boolean}

By default, files in directories named protocols are excluded in the built project. Set :load_protocols to true to have them included.

4.9 - :minify => {Boolean}

By default, the HTML, JavaScript and CSS is minified when built. Set this to false to prevent minification, which may be useful for debugging. You can also be more specific by using either :minify_javascript,

:minify_css or :minify_html.

If minify is false, sc-build will throw a security exception unless --allow-commented-js is set, because all comments will be visible in the built product.

4.10 - :required => {Array}

This defines the frameworks in the order that the app requires them and is initially set by default to :sproutcore. Since frameworks can be nested and can define their own requirements, the :sproutcore framework is actually just a wrapper framework that includes several of its sub-frameworks each of which have their own requirements as well. New developers should not generally concern themselves with stripping away

Ex. The most basic Buildfile:

my_project/Buildfile
config :all, :required => :sproutcore

Ex. Including a framework, DataHelpers, from the project's frameworks directory for all apps within the project:

my_project/Buildfile
config :all, :required => [:sproutcore, :data_helpers]

Ex. Including different frameworks for different apps:

my_project/Buildfile
config :all, :required => [:sproutcore] config :my_app, :required => [:client_views] config :my_admin_app, :required => [:admin_tools]

Ex. Including different frameworks for different apps using app specific Buildfiles:

my_project/Buildfile
config :all, :required => [:sproutcore]
my_project/apps/my_app/Buildfile
config :my_app, :required => [:client_views]
my_project/apps/my_admin_app/Buildfile
config :my_admin_app, :required => [:admin_tools]

For advanced manipulation of the included SproutCore frameworks, refer to the SproutCore Buildfile.

4.11 - :theme => {String}

The framework or theme that contains the app's theme. See the guide on Theming Your App for more information.

4.12 - :theme-name => {String}

A class name to set on the <body> element. If not specified, the body will have a class sc-theme.

4.13 - :title => {String}

The value of the HTML <title> element.

Ex. Separate titles for different apps:

my_project/Buildfile
config :all, :required => [:sproutcore] config :my_app, :title => 'My App' config :my_admin_app, :title => 'My App (Administration)'

For advanced Buildfile configuration, refer to the build tool's Buildfile.

5 - Developing with SproutCore: sproutcore server

So that you can view and test your code in action immediately, the build tools also provide a local server and proxy. As was mentioned in Getting Started, you run the server by changing to your project's directory and running either sproutcore server or sc-server for short. The server will monitor your files for changes and re-build them when they do change. To keep the process fast and to allow you to debug your code while developing, the individual files aren't packed or minified in debug mode. When your server is running, you can access your apps at http://localhost:4020 or a specific app at http://localhost:4020/app_name.

The server also includes a proxy that is configurable within the project's Buildfile. Without a proxy, XHR requests will fail since the origin of your test page, http://localhost:4020 will not match the origin of your backend server (ex. https://my-private-api.com:8080) and the browser will consequently reject the request. Therefore, if you want to load data from your backend from a URL like https://my-private-api.com:8080/users/3, your XHR request must be to /users/3 and you will use the SproutCore server to proxy the request across.

Here are some examples configuring the SproutCore server proxy:

my_project/Buildfile
# Proxy all requests for '/news' to 'http://news.com/news'. proxy "/news", :to => "news-server.com" # Proxy all requests for '/session' to 'https://session-server.net/session'. proxy "/session", :to => "session-server.com", :secure => true # Proxy all requests for '/users' to 'https://our-app.com/people'. # ex. /users/23 => https://our-app.com/people/23 proxy "/users", :to => "our-app.com", :secure => true, :url => "/people" # Proxy to a local server with a longer timeout to support long-polling requests. # ex. /socket.io => http://localhost:3443/socket.io proxy '/socket.io', :to => 'localhost:3443', :timeout => 25 # An alternate configuration of the above. proxy '/socket.io', :to => 'localhost:3443', :connect_timeout => 5, :inactivity_timeout => 30 # Disallow redirects proxy '/originals', :to => 'some-api.org', :redirect => false

When changing proxy settings, the server may need to be restarted to reflect the changes.

6 - Building a SproutCore Application: sproutcore build

Finally, when your application is ready to be deployed to a real server, you will do a production build and move the files across to be hosted. Depending on the options you set in your Buildfile, this will generate some variant of static deployable and cache-able content.

Ex. Building all apps and required frameworks within a project.

$ sproutcore build

Ex. Building a specific app within a project, including it's required frameworks.

$ sproutcore build my_app

The following are some options that you may want to pass to sproutcore build or sc-build.

6.1 - --allow-commented-js

You must set this if you have set minify: false in your Buildfile and you do want to build an un-minified product which includes all your comments.

6.2 - --build

Specify the build number manually to use. This results in paths that won't cache properly, but may be useful for testing or embedding a SproutCore app.

$ sproutcore build my_app --build=test_build

6.3 - --buildroot

Specify the path to the built product.

$ sproutcore build my_app --buildroot=../builds

6.4 - --languages

Specify which languages to build. By default, the build tool will build all languages in the project.

$ sproutcore build my_app --languages=en,en-ca,zh

6.5 - --dont-minify

Disables minification for the build without throwing a Security exception as setting minify: false within the Buildfile would do.

Be sure to remove any debugger statements from your code, as they will cause the build to fail.

6.6 - --stageroot

Specify the path to the staging products.

$ sproutcore build my_app --stageroot=../tmp/staging

6.7 - --verbose or -v

Verbose output.

7 - Changelog

  • February 27, 2012: initial version by Tyler Keating
  • February 28, 2012: added some documentation on sc-server & sc-build by Tyler Keating
  • December 17, 2012: added note about changing proxy settings by Mike Atkins
  • July 14, 2013: converted to Markdown format for DocPad guides by Topher Fangio