Skip to content

How to load amber

herby edited this page Oct 15, 2014 · 27 revisions

Amber is available both through the node and the bower package managers.

Note: This page is not obsolete in the sense that every piece described here still happens to exist in version 0.13 but has been moved to different files (devel.js, deploy.js, *.amd.json). So this page needs to be rewritten to show things for 0.13 version and return the link back to Home page.

To load Amber, you should add these <script> tags into your page (placement to head or at the end of body at your own discretion; if you want/need to load amber.js or both the first two scripts asynchronously, see Note 2):

    <!-- 1 -->
    <script src="path_to_amber/support/requirejs/require.min.js"></script>
    <!-- 2 -->
    <script src="path_to_amber/support/amber.js"></script>
    <!-- 3 -->
    <script>
        require.config({paths:{
            // ---- up to version 0.12.3 use this ----
            // -- 4 --
            'biz_corp_clientlib': 'path_to_corp_clientlib/js',
            'gh_author_foolib': 'path_to_foolib/js',
            'biz_corp_app': 'code/js',
            // -- 5 --
            'biz_corp_app/_source': 'code/st'
            // ---- since version 0.12.4 use this ----
            // -- 4 --
            'biz_corp_clientlib': 'path_to_corp_clientlib/src',
            'gh_author_foolib': 'path_to_foolib/src',
            'biz_corp_app': 'code/src',
            // ---- end of version specific parts ----
        }});
        require([
            // -- 6 --
            "amber/devel",
            // -- 7 --
            "gh_author_foolib/FooLib-Backend",
            "gh_author_foolib/FooLib-Frontend",
            "biz_corp_clientlib/CorpClient-Bar",
            "biz_corp_clientlib/CorpClient-Baz",
            "biz_corp_app/CorpApp-Model",
            "biz_corp_app/CorpApp-Client"
        ], function (amber) {
            // ---- up to version 0.12.2 use this ----
            // -- 9 --
            amber.defaultAmdNamespace = 'biz_corp_app';
            // -- 8 --
            amber.initialize();
            // ---- since version 0.12.3 use this ----
            // -- 8 --
            amber.initialize({
                // -- 9 --
                'transport.defaultAmdNamespace': 'biz_corp_app'
            });
            // ---- end of version specific parts ----

            // -- 10 --
            amber.globals.Browser._open(); // for legacy IDE, or
            amber.popupHelios(); // for Helios IDE
            amber.AppLogic._start();
        });
    </script>

Notes:

  1. Loading AMD loader
  • path_to_amber can be anything - relative path, absolute path or full URL.
  • You don't need to load require.js AMD loader from amber location, you can load it from any other place you want.
  • Not tested, but amber should play just fine with any conforming AMD loader.
  1. Loading amber.js script that configures AMD loader
  • path_to_amber can be anything - relative path, absolute path or full URL, it depends how you deploy / decide to load amber from.
  • amber.js is built so that it can appear after require.js but also before it - it the former case it properly configures require.js, it the latter case it prepares the configuration into require global, using the feature of require.js that uses contents of require global, if it exists, as the configuration upon loading itself.
  • If you want to load and execute this script asynchronously, you must give it id='amber-path-mapper', otherwise it cannot find its parameters (path and attributes).
  1. Hand-written script that actually loads Amber including your packages
  • it is only required that things described later happen, in that order, sometimes after (1) and (2), but you can structure them as you wish; using <script> tag with presented structure is just a convention.
  1. Configuring namespace-to-path mappings for loading packages
  • Each package in amber must have a namespace, the part before '/'. There should be no dot in namespace.
  • Each namespace represents one physical location to load from, and optionally, to save to; IOW, it represent one URL path; again, it can be relative path (relative to page being loaded), absolute path or full URL path.
  • You should point 'namespace' to the location of compiled amber files, which have .js extension. The convention in lot of projects is to put source (Smalltalk) files into .../st and compiled files into .../js where ... is same path. This is why in this example, all three namespaces are mappped into paths that end with /js. This convention has changed inside amber itself and for new projects in version 0.12.4: there should be only one folder src which holds both .js and .st files.
  • Namespaces are selected for the library / app (a group of amber packages at the same location) by its developer and are hardcoded into it. For this reason, care must be taken when selecting namespace, so it does not clash with other namespaces. One technique, used in this example as well, is to take the 'path' where the project resides ('corp.biz/clientlib', 'github.com/author/foolib' etc.), revert the domain name ('biz.corp/clientlib', 'com.github/author/foolib' etc.) and replace all separators ('.', '/') with underscores ('biz_corp_clientlib', 'com_github_author_foolib'). One can do some simplifyings if they seem to be safe enough; like shortening github_com_ into gh_.
  • Changing namespace is hard, or even impossible if your code is already reused (is a library) and is a breaking change. The namespace is world-wide global name for a group of files of your project. Every file of your project needs unique name, to be able to use it in list of dependencies in AMD. That is the role of namespace - to give your files a unique prefix (thus "name space"). Other, more technical, side to namespaces is that they group files that are held together, thus forming a high-level module. You can deploy this module anywhere you wish, since you map the namespace into the physical location for the loader.
  • This example represents complex application that resides at corp.biz domain. This page loads the app, which has its own code (namespace biz_corp_app), uses some internal library (namespace biz_corp_clientlib) and also uses (contrived) third-party library foolib created by author and developed in github (namespace gh_author_foolib).
  • As in previous cases, path_to_corp_clientlib and path_to_foolib can be any URL paths - relative to page being loaded, absolure or full URL paths with protocal, machine etc.
  • You can see the namespace biz_corp_app is mapped to relative path code/ja, that is, if this page is http://foo/bar/index.html, the mapped path of biz_corp_app would be http://foo/bar/code/js.
  1. Configuring namespace-to-path mappings for saving package sources
  • If you map 'namespace/_source' (the special ending /_source), you are mapping the URL path into which the page will try to save sources (file with .st extension) of amber packages in namespace 'namespace'.
  • When saving, compiled .js files are saved as well; these are saved into the same path which is used for loading them.
  • Since version 0.12.4, it is recommended not to map .../_source at all. In that case, .st files will be saved to the location of .js files.
  • In this example, if you save any package from namespace corp_biz_app, its .st file is tried to save into code/st/PackageName.st and the compiled file is saved into code/js/PackageName.js.
  1. Specifying proper amber subset to load
  • The first element of an array of modules to load in the require call should be one of the preconfigured amber sets. There are three sets available: amber/devel which loads all amber packages including IDE and SUnit support, amber/helios which loads all that amber/devel does but also adds the new work-in-progress IDE named Helios, and amber/deploy which includes only core amber itself and Canvas package for working with web page, but no IDEs, no compiler and no testing support is included.
  • If you wish to select your own subset, either make your own set by cloning and modifying some of the amber ones, or put amber_vm/smalltalk as the first element of the array and then include all amber packages you want to load by hand after it. There is no need to do this, though for 99.9% of the projects ;-)
  1. Listing other packages to load
  • Besides the amber subset from (6), you also want to load your / third-party packages as well, so that you app actually loads. You just list them here. Of course, to load them, namespaces must be correctly mapped to paths in (4).
  • If you happen to create new package and successfully save it, you must add it into this list in your .html page by hand. Amber does not touch your .html in any way - you write the loading scripts, you manage them; Amber only saves .st file with source and``.js` file with compiled JavaScript into designated locations.
  1. Initializing smalltalk
  • Sets up all the loaded packages and the amber runtime.
  • Required before running any amber code.
  1. Specifying default namespace
  • Amber itself does not have the concept of package namespace in the language itself. Namespace is the matter of external structure of the project (where are groups of packages located / loaded from / saved to). An existing package knows its namespace and uses it when saving. Newly created packages have no explicit namespace set, as they are created as a side effect of adding a class to a package name.
  • This sets the 'default namespace'. Its sole purpose is to be added as a namespace to all newly created packages.
  • If you are sure no new packages will ever be created (you are only using the packages to run some page, used amber/deploy subset to load amber; IOW you are not developing), you can omit this line altogether.
  • If you want to have a new package in different namespace than the default, just issue (Package named: 'NewPackageName') transport namespace: 'new_namespace' in Workspace after the package is created but before it is saved.
  1. Launching some startup code
  • You should start your app / etc. by issuing some code here.
  • In this example, you see the equivalent of Browser open and AppLogic start. The first just opens the legacy IDE - while you are developing the app, it is convenient to have IDE opened automatically (the alternative code in the second line opens the new Helios IDE instead). The third line is just the stereotypical 'start the app' line, expecting you have AppLogic class somewhere in the code (probably in CorpApp-Client package).
  • Alternatively, you can open legacy Browser by slightly longer smalltalk.Browaer._openOn_(smalltalk.AppLogic) which is compiled version of Browser openOn: AppLogic. As it suggests, it opens the Browser on the specific class (as opposed to empty one from the example).

Start page

Clone this wiki locally