In Niagara 4, the user interface is moving in a new direction with a heavy focus on HTML5 applications and open web technologies. Tridium provides a number of frameworks and utilities, intended to give developers the power to create their own web apps, from tiny field editors to powerful, full-featured full-screen views.
Developing in HTML5 and JavaScript is a different process from the familiar Java-based process for developing in the Niagara Framework. However, using the tools and techniques described in this document, you can create a JavaScript codebase that is robust, error-checked, and well-tested.
Before beginning HTML5 development in the Niagara Framework, you’ll want to take a few moments to familiarize yourself with a few of the different libraries and frameworks available to you. These frameworks include BajaScript, bajaux, and other open web technologies.
In order to most effectively develop Niagara web applications, you’ll need to install a few external utilities for building, code analysis, and testing.
The toolchain described in this document is the one used by Tridium to develop all of its HTML5 web applications for Niagara 4. The tools described are free and open-source. The toolchain is separate from the Niagara Framework itself, so if you find that it does not suit your purposes, you are free to use a different set of development tools, or create your own.
To use the standard Tridium toolchain, you’ll need to install the following utilities:
Node.js allows you to run JavaScript applications from the command line, without using a web browser. Tridium’s open-source tools for developing Niagara web applications are all based upon Node.js.
npm is a utility used to download and install Node.js modules. It is automatically installed alongside Node.js.
Grunt is a task runner for JavaScript. You will use it to find errors, run tests, and analyze your code. Install it like this:
npm install -g grunt-cli
After that, you’ll be able to run Grunt tasks for a web module by cd-ing into its directory and typing grunt.
Git is used to clone entire repositories of source code to your machine. This is mostly used internally by npm, but you might also need to clone some repositories manually.
These environment variables are necessary for doing Niagara web development. Some may already be set up for you - type set at your command line to see which are present.
niagara_home: your Niagara runtime home directory, typically c:\Niagara\Niagara-{versionNumber}, which contains the bin folder.niagara_user_home: directory containing your Niagara user files, notably the stations folder. Often, %USERPROFILE%\Niagara4.x\{companyName}.niagara_dev_home: directory containing all your Niagara development files (source code, etc.). Instead of an environment variable, this value can also be set via the niagara.dev.home system property. This is a requirement for using moduledev mode.In order to properly build and test JavaScript modules, there is some setup involved. npm libraries need to be downloaded and installed, configuration files need to be written, and code needs to be moved into the proper directories.
We have created a number of utilities to make this process as easy as possible. These are open-source Node.js modules, created and released by Tridium. They will facilitate a fully automated, test-driven approach to creating functional, reliable, well-tested Niagara web modules.
grunt-init is a tool that streamlines the creation of a new JavaScript project. The process is similar to Wizards you might use in Workbench: it asks you a number of setup questions and generates a brand-new web module for you to begin development.
grunt-init-niagara is Tridium’s own grunt-init template which is Niagara-specific; it generates you a brand-new Niagara web module that can be built and run using standard Niagara tools. The module will be pre-configured with source code and test directories, configuration files, and everything necessary to start developing.
All of the modules described in the rest of this section will be automatically included in your new module with no further configuration necessary. Simply type npm install to download everything, then begin development.
While it’s entirely possible to create a new web module without using grunt-init-niagara, we highly recommend that you use it for your first web module to learn about the recommended project structure and configuration.
This is less of a development tool and more of a collection of smart defaults. Including grunt-niagara in your project will include ESLint, Karma, Plato, and other development utilities, with configuration files pre-configured with settings Tridium has found to be optimal when developing web modules. The settings can be added to or changed in your own configuration files.
When creating a new module using grunt-init-niagara, you’ll automatically have grunt-niagara installed and configured. For information about migrating an existing module to use grunt-niagara, see Migrating to grunt-niagara.
This is a library that allows you to start and stop Niagara 4 stations using Node.js. It is most commonly used during the test process to start a station with BajaScript installed, so that the web module’s unit tests can use a live BajaScript session to verify real-world behavior.
It also has some basic port configuration abilities. For example, if you are running tests on a machine that has port 80 already in use, niagara-station can reconfigure the station to run HTTP on port 8080 instead.
When using grunt-init-niagara, your web module will automatically receive a test station and a default niagara-station configuration.
This module simply includes some utilities for logging into a running test station using JavaScript and triggering the browser to run tests. Again, it’s automatically included by grunt-init-niagara.
Since JavaScript is an interpreted, not compiled, language, there is no compilation step to catch syntax errors before the code is run in the browser. This makes a static analysis tool like ESLint a necessity. It will find syntax errors (and some semantic errors as well) in your JavaScript code before it is run.
ESLint runs as a Grunt task as part of the standard development process.
Jasmine is Tridium’s unit testing framework of choice. All of our JavaScript libraries, like BajaScript and bajaux, are fully unit tested using Jasmine.
The Jasmine framework will be automatically configured when using grunt-niagara. It is possible to use other testing frameworks, but you will need to configure these manually.
Karma actually runs your tests and generates the results. By default, it will start up an instance of ChromeHeadless - a headless Chromium instance - and run your full test suite. You can also connect any other browser to it, such as Firefox, Edge, or an iPhone, and run your tests in all of those browsers as well.
Note that if Chrome cannot be found for running tests, follow this link for additional information on this topic.
When building your web module, the build process can use the r.js optimizer to compact all of your JavaScript code into a single file. Since network calls are the biggest factor affecting the loading time of your application, this is a crucial step in ensuring your app loads as quickly as possible.
This plugin also generates documentation for your app using JSDoc.
For more information, see the Deploying Help section.
moduledev modeWhen developing a web module, it’s a severe slowdown to have to rebuild your module and restart your station every time you want to test out a new change in your browser. It’s much faster to simply change a file and refresh the browser to pick up the latest changes.
To facilitate this, Niagara 4 includes a moduledev mode that allows files from certain modules to be read directly from your hard drive instead of from a module JAR file. In order to enable this mode, you’ll need to perform the following steps.
First, you’ll need to ensure this feature is enabled in your Tridium license. You’ll need the developer feature included in your license with the moduleDev property set to true. If your license does not include this feature, please contact your Tridium sales representative.
Next, add an entry to system.properties: niagara.module.dev=true. This is for the browser only; for Workbench, there is another setting: niagara.module.dev.wb=true.
Not every file type can be resolved in this way: by default, only JS, CSS, HTML, image files, and some other web-related file types are supported. If you wish to resolve some different file types, you can configure this list using this system property: niagara.module.dev.supportedExtensions=js,css,vm,htm(...)
Next, create a file niagara_home/etc/moduledev.properties. Each entry in this file maps a module name to the directory on your hard drive in which that module’s source code lives. For instance, myModule=d:/niagara/dev/myModule. (Note that the runtime profile is not included! myModule-ux=d:/niagara/dev/myModule/myModule-ux will not work. moduledev mode will resolve files from any of your runtime profile directories.)
Now, whenever a request is made for a file, with a supported extension, from your web module, it will be resolved from your hard drive instead of from the JAR. This way, hitting refresh in the browser will always load your up-to-date changes. Note that this mode should never be enabled in production - only in development.
Now that you’ve set up your environment and gotten a brief introduction to the various JavaScript libraries and frameworks available to you, it’s time to start developing! This section will contain a full tutorial, from creating your first module using grunt-init-niagara, to writing your first test, to viewing the result in the browser.
Begin by installing grunt-init-niagara to your machine, following the instructions from the Grunt website. This process may vary from machine to machine, but will probably look similar to:
npm install -g grunt-init
mkdir %USERPROFILE%/.grunt-init
cd %USERPROFILE%/.grunt-init
git clone https://github.com/tridium/grunt-init-niagara
Once installed, navigate in a console to your dev directory containing the source for your Niagara modules. If you have not set up a build environment using the New Module Wizard, do so using the steps here first.
The steps below assume you are working with a typical multi-module Gradle setup rooted at %niagara_user_home%. As usual, any Gradle commands should only be run from the root of your build (the same folder containing build.gradle and settings.gradle).
Begin the process like so:
mkdir myWebModule
cd myWebModule/
grunt-init grunt-init-niagara
Note that if you are adding a -ux part to an existing module, or if you specified -ux as a module part when running the New Module Wizard, you will need to run grunt-init with the --force option. grunt-init will not run by default if there are existing files in your directory - it doesn’t want to overwrite them!
You’ll be asked a series of questions. Leaving the answer to any question blank will accept the default (shown in parentheses). For this tutorial, we’ll ask it to create a bajaux Widget for us to study and modify.
Please answer the following:
[?] Niagara module name (myWebModule)
[?] What Niagara version will you build your module against? (4.10)
[?] Shortened preferred symbol for your Niagara module (myWbMdl)
[?] Description of your Niagara module My First Web Module
[?] Author name (myCompany)
[?] Would you like to create a bajaux Widget? (y/N) y
After completing all the questions (you can select default values for all additional questions not shown above), it will generate a myWebModule-ux directory, containing the generated sources for your web module. It should build and install using the normal build process:
gradlew :myWebModule-ux:jar :myWebModule-ux:moduleTestJar
(To facilitate rapid development, ensure that you have enabled moduledev mode and added an entry for myWebModule to moduledev.properties at this time.)
Just to make sure everything is functional, let’s install and run tests for our module.
cd myWebModule-ux/
grunt ci
Don’t worry, I’ll describe what’s happening in just a moment. gradlew jar should download and install all the necessary dependencies to run tests for your module, then grunt ci should actually run those tests. Hopefully, you’ll see SUCCESS at the end of this process. Now let’s take a look at a few of the individual steps in this process, and the relevant configuration files.
This file is used by Node.js and npm. Most of it won’t be relevant to you unless you decide to publish your module to the npm repository. The important part is the devDependencies section, which describes which additional modules your module depends on. It will be pre-populated with those modules that are necessary to run unit tests for your Niagara web module.
Typing npm install will download these dependencies from npm and install them for you. But gradlew jar will do this for you as part of the build process you completed in the last step, so you shouldn’t need to do it a second time.
This file is used by Grunt. It describes all the automated tasks that are available for your module, and sets up configuration settings for each.
You will see at the bottom of the file that it loads tasks for the grunt-niagara module. This is a utility module that includes tasks that we at Tridium have found to be very useful when developing web applications. It sets up a default configuration for each one that we find to work well. You are free to override these configurations as you wish, but just leaving this file alone and working with the provided config is a great way to get started. (Later on, if you decide that grunt-niagara isn’t right for you, you can leave it out completely and build your own toolchain as you see fit.)
To see the tasks that are available to you right out of the box, just type grunt.
Another feature that grunt-niagara provides for you is the ability to pass in config flags on the command line when running tests. To see a list of all available flags, type grunt flags. A few flags you may find particularly useful are:
--testOnly: if your test suite grows large, you may find it taking longer and longer to run all of your specs. You can use testOnly to limit which specs are run.--station-http-port: if your test station runs a different HTTP port, you can specify which port your tests should use to attempt to log into the station. There are also corresponding flags for HTTPS, FOX, and FOXS.--override-station-ports: used in conjunction with the previous flags, actually will inject the port number into the config.bog before starting the station to force it to run on a particular port. This is helpful if one of the default ports is already in use on your machine.--station-log-level: configure how much detail from the station log is output to the console when running tests. It defaults to NONE because usually you’ll only want to see the actual test output instead of a lot of noise from the station. But dialing it up to INFO, FINE, or all the way to ALL can help with debugging.Many of these flags’ default values are set using the niagara_home and niagara_user_home environment variables.
Let’s start developing straight away by typing grunt watch. Your test station will be copied into your stations/ directory and started up (note that the default credentials for the test station are user: admin, password: asdf1234), and an instance of Karma will be started as well. By default, a single instance of ChromeHeadless - a command-line, headless web browser - will start and get ready to run tests. (If you wish to run tests in other browsers, like Firefox or Edge, it will print out instructions on how to connect those as well.)
What happens now is that every time you save a change to a file, the grunt watch task will immediately spring into action, running ESLint to detect syntax errors and other bugs, and then running your suite of tests in Karma to verify behavior. This allows for a very rapid TDD, red-green-refactor workflow.
Let’s demonstrate the process. grunt-init-niagara should have generated you a file called MyWebModuleWidget.js. Out of the box, the code should pass all linting and tests, so we’ll have to introduce some new errors to see how they are handled. Take a look at the doLoad (or the spandrel function if you generated JSX) function, and you should see a line that looks like this:
that.$buildButtons(value);
Change it so that it looks like this:
that.$buildButtons(schmalue)
Now save the file. Grunt should detect your change and immediately go to work. After running tests, the next step in the watch process is to run ESLint on your code. Ignoring test failures for now: our change introduced two errors in our code, and ESLint should have caught them both:
>> File "src\rc\MyWebModuleWidget.js" changed.
Running "eslint:src" (eslint) task
src\rc\MyWebModuleWidget.js
118 | that.$buildButtons(schmalue)
^ Missing semicolon.
118 | that.$buildButtons(schmalue)
^ 'schmalue' is not defined.
If you generated JSX, you can try the same thing in the spandrel function: Find the line that looks like this:
{ comp.getDisplayName(slot) }
Change it so that it looks like this:
{ komp.getDisplayName(slot) }
You will see a similar ‘komp is not defined’ ESLint error.
As you can see, whenever you introduce an error that ESLint can detect, you will be alerted. Note that ESLint is a static code analysis tool; it is separate from actually running your code during the test phase. ESLint looks for syntax errors, misspellings, code style problems, and similar categories of errors. It will not find logical errors in the execution of your code. That happens in the testing phase.
Back out the change we just made so that it looks like it did before:
that.$buildButtons(value);
Now, we’ll take a closer look at the unit testing capabilities of Karma. We’re going to follow the traditional TDD method of red-green-refactor:
Take a look at the example page at http://localhost/module/myWebModule/rc/myWebModule.htm that grunt-init-niagara generated for us (remember that the default credentials for the test station are user: admin, password: asdf1234). You’ll see that it creates a clickable button for every slot on a Component, and whenever we click one of the buttons, it updates to show the name of the slot we selected. For this next example, we want to change the widget’s behavior slightly. Instead of just displaying the slot name, we’ll add an exclamation mark just to properly convey our excitement.
The first step is to change the test. (If we were adding new behavior to the widget we’d add another test, but since we’re changing existing behavior, we can just change the test.) Take a look at srcTest/rc/MyWebModuleWidgetSpec.js. This suite of unit tests is written using the Jasmine framework, which is Tridium’s test framework of choice and the one automatically configured by grunt-niagara.
Look at the spec named arms a handler to display selected slot name. Since we’re changing the way the slot name is displayed, this is also the spec that we will change. Towards the bottom of the spec, you will see the verification test that looks something like this:
waitForTrue(() => slotDom.text() === 'larry');
Change it so that it’s expecting an exclamation point:
waitForTrue(() => slotDom.text() === 'larry!');
Save the file. Since grunt watch is running, the change will be immediately detected and your test suite will be run. You should see the spec fail:
nmodule/myWebModule/rc/MyWebModuleWidget #doInitialize() arms a handler to display selected slot name FAILED
Expected { message : 'timed out after 5000 msec waiting for something to happen', stack :
'Error: timed out after 5000 msec waiting for slot name to match the expected name.
Executed 8 of 8 (1 FAILED) (0.562 secs / 0.567 secs)
This is the “red” phase of development: we have a failing unit test. By first having a failing test, we get visual proof that the behavior we’re writing has correct test coverage behind it. To get back to green, we go into src/rc/MyWebModuleWidget.js and update the $updateSlotText function to add the exclamation point we need:
that.jq().find('.MyWebModuleWidget-selected-slot').text(slotName + '!');
Save the file and the test will automatically be run. This time, everything should pass.
Using these frameworks and techniques, you have the ability to implement a fully test-driven development process from beginning to end. It may seem like a large upfront time investment (isn’t it twice as much code for the same functionality?) but a comprehensive suite of automated tests for your code is invaluable: short-term, it helps to ensure that the code you write actually does what you think it does; and long-term, it allows you to make changes, improvements, and refactorings to your code without worrying about breaking existing functionality.
Unit tests, as configured by grunt-niagara, will export their results in a JUnit-compatible XML format. This means that if your organization uses a Continuous Integration solution, like Bamboo or Jenkins, it can consume these XML files. Your JavaScript code can then be included in your CI process.
When invoking the Grunt process, use grunt ci to run CI-related tasks and generate these XML files. If needed, you can use the --junit-reports-dir flag to specify where the XML results go.
Implementing your JavaScript-based widgets is only one part of the development process. They must also be built into your Niagara module so that they can be deployed to Niagara stations and supervisors.
By default, the Niagara build environment will run any Grunt tasks you have configured (the default is just the requirejs task) prior to building the module jar. You can change this by editing the “gruntBuild” section of your module’s Gradle build file:
gruntBuild { tasks 'requirejs' }
You may add additional tasks by specifying the task name(s) as such:
gruntBuild { tasks 'less', 'babel', 'requirejs' }
You can then build your module as normal:
gradlew :myWebModule-ux:jar
One of the tasks available for the gruntBuild config is requirejs. This Grunt task will optimize your JavaScript using r.js. All JavaScript modules will have all of their dependencies resolved and included in a single file: myWebModule.built.min.js. This allows you to download every JavaScript file in your Niagara module using a single network call. This is crucial on embedded devices where negotiating network connections can be slow.
Often, your HTML5 web app will have an instance of some BajaScript value: a Facets, for instance, or a DynamicEnum, that you wish to present to the user in an editor. You could manually go and fetch the code for FacetsEditor or DynamicEnumEditor, then instantiate, initialize, and load it into your page. It would be much easier, though, to simply ask the framework for an editor that’s appropriate to edit that value. Then, you’ll be certain that you’ll be provided the correct, most up-to-date version of that editor.
Also, consider the Property Sheet. If you have a custom Baja value and a custom field editor to edit that value, you’ll need to create an association between the two so the Property Sheet knows how to show the correct editor for your custom value.
The way to do this is to create a simple Java class in your module. Its only job is to provide answers to these questions:
To let the Niagara framework know about the JavaScript file containing your editor, create a Java class that extends BSingleton and implements javax.baja.web.js.BIJavaScript. This simply creates a mapping between a Niagara Type and a JavaScript file.
@NiagaraType
@NiagaraSingleton
public final class BMyWebModuleWidget
extends BSingleton
implements BIJavaScript, BIFormFactorMini, BIOffline
{
private BMyWebModuleWidget() {}
public JsInfo getJsInfo(Context cx) { return JS_INFO; }
private static final JsInfo JS_INFO = JsInfo.make(
BOrd.make("module://myWebModule/rc/MyWebModuleWidget.js"),
BMyWebModuleJsBuild.TYPE
);
}
As you can see, there is very little to a BIJavaScript class. It has only one method to implement, getJsInfo(), which lets the Niagara Framework know where the JavaScript implementation of your widget is located.
Also notice the implemented interface BIFormFactorMini - see the bajaux documentation for details on what this does.
(Beginning in Niagara 4.2, BajaScript supports offline editing of .bog files. If you are implementing a field editor that you wish to be available offline, also implement the marker interface BIOffline. Note that a number of operations are unavailable while BajaScript is in offline mode, such as resolving station-specific ORDs and making XMLHttpRequests, so ensure that your field editor will not attempt to perform unsupported operations before implementing BIOffline.)
You can also see as part of the JsInfo.make() method, you can pass in an instance of BJsBuild. This performs a very similar function to BIJavaScript, but instead of providing the location of a single JavaScript module, it provides the location of an optimized JavaScript built file: e.g., myWebModule.built.min.js produced by the Gradle RequireJS plugin as described above.
The implementation of a BJsBuild class is also very simple:
public class BMyWebModuleJsBuild extends BJsBuild
{
public static final BMyWebModuleJsBuild INSTANCE = new BMyWebModuleJsBuild(
"myWebModule", //webdev ID
new BOrd[] {
BOrd.make("module://myWebModule/rc/myWebModule.built.min.js")
}
);
//TYPE and private constructor
}
While optimizing your JavaScript and creating BJsBuild classes are strictly optional, they are highly recommended.
Don’t forget that your BIJavaScript and BJsBuild classes are standard Niagara Types and should be included in module-include.xml.
Now that you’ve implemented a JavaScript editor and registered its existence with the framework, you can also declare it to be compatible with certain Types. For instance, MyWebModuleWidget might be able to load values of type myWebModule:MyWebModuleComponent. To declare this relationship, simply register your BIJavaScript as an agent on a Type. You can do this the usual way, in module-include.xml:
<type name="MyWebModuleWidget" class="com.tridium.mywebmodule.BMyWebModuleWidget">
<agent><on type="myWebModule:MyWebModuleComponent" /></agent>
</type>
Or (recommended) the new annotation-based method available in Niagara 4:
@NiagaraType(agent = @AgentOn(types = { "myWebModule:MyWebModuleComponent" }))
public final class BMyWebModuleWidget
One last thing to consider. At this point you have two files containing your editor’s code: the one you’ve just created, with the human-readable JavaScript code (MyWebModuleWidget.js), and the built and minified version for conserving network traffic (myWebModule.built.min.js).
During normal usage, your station will only serve up the minified file. This is absolutely the correct behavior: on an embedded device, conservation of network traffic is key. But take a look at the minified file: it’s completely incomprehensible. When developing and debugging, you really want to be able to see the original, human-readable code.
By enabling webdev mode for your module, the station will kick into debug mode: it will switch over to serving up the original file, so that you can open up the console in Chrome or Internet Explorer and trace through your actual code.
To enable webdev mode, simply go into the spy page for the station and visit the webDevSetup page. (You’ll need to actually visit the web interface first - so the station serves up some files - for it to appear.) Enable webdev mode for the ID of your BJsBuild, and from then on, the unminified files from your module will be served to the browser. This is invaluable when debugging your code live in the browser. (To learn more about browser debugging, search the web for “{your browser name} console tutorial.”)
You can also configure webdev by hand by editing %niagara_user_home%/etc/webdev.properties.
Let’s do a quick recap of what you’ve accomplished so far.
MyWebModuleWidget.js)BMyWebModuleWidget implements BIJavaScript)requirejs configuration creates myWebModule.built.min.js)BMyWebModuleJsBuild extends BJsBuild) and let the framework know that your widget’s code is packaged within it (BMyWebModuleWidget references BMyWebModuleJsBuild)MyWebModuleWidget when it tries to load an editor for a compatible Type (BMyWebModuleWidget is an Agent on BMyWebModuleComponent).At this point, you have everything you need to go full-speed into developing HTML5 widgets and editors. Continue using the linting and testing tools provided by grunt-init-niagara to iterate over your widget until it is well tested, error-checked, and fully functional. (If you are developing a field editor intended for use in the HTML5 Property Sheet, definitely check out the webEditors tutorial for notes on this use case.)
Feel free to stop by the Niagara Central Forums to discuss any questions or problems.
Happy coding!
niagara-rjs to grunt-niagaraWhen using grunt-init-niagara to create a new Niagara module targeting 4.6 or later, grunt-niagara will automatically be used in place of niagara-rjs. When migrating an existing module to the latest version of Niagara, the niagara-rjs config should be removed and migrated to use grunt-niagara instead. This section will describe that migration process.
One option is to run grunt-init-niagara in an empty directory, which will generate a Gruntfile and package.json for you. Or, for an existing module, you can manually create them as shown below. Both of these files go in the root of your module part, that is, yourModuleName/yourModuleName-ux.
//package.json
{
"name": "yourModuleName-ux",
"version": "0.1.0",
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-plugin-istanbul": "^4.1.3",
"grunt": "~1.0.1",
"grunt-niagara": "^2.1.0"
}
}
//Gruntfile.js
const SRC_FILES = [
'src/rc/**/*.js',
'!src/rc/**/*.min.js'
];
const TEST_FILES = [
'srcTest/rc/**/*.js'
];
const ALL_FILES = SRC_FILES.concat(TEST_FILES);
module.exports = function runGrunt(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
jsdoc: { src: SRC_FILES },
eslint: { src: ALL_FILES },
watch: { src: ALL_FILES },
karma: {},
babel: {},
requirejs: {},
niagara: {
station: {
forceCopy: true,
sourceStationFolder: './srcTest/stations/bajauxUnitTest'
}
}
});
grunt.loadNpmTasks('grunt-niagara');
};
Let’s look at an example niagaraRjs config block from a legacy Gradle file.
//in myModule-ux.gradle:
niagaraRjs {
builds = [
'myDefaultBuild': [
rootDir: 'src/rc',
include: [
'nmodule/myModule/rc/fe/MyWidget',
'nmodule/myModule/rc/fe/YourWidget',
// ... every file in my module
]
]
]
options = [
disablePlugins: [ 'baja', 'lex', 'css' ],
exclude: [ 'Handlebars', 'underscore', 'hbs' ],
hbs: [
disableHelpers: true,
disableI18n: true
],
paths: [
'nmodule': 'empty:',
'bajaScript': 'empty:',
'jquery': 'empty:',
'bajaux': 'empty:',
'dialogs': 'empty:',
'profileInfo': 'empty:',
'bajauxContainer': 'empty:',
'jqueryContextMenu': 'empty:',
'hx': 'empty:',
'Promise': 'empty:',
'ace': 'empty:',
'nmodule/myModule': 'src',
'nmodule/myModuleTest': 'srcTest',
'Handlebars': projectResource('js-ux', 'rc/handlebars/handlebars-v2.0.0'),
'hbs': projectResource('js-ux', 'rc/require-handlebars-plugin/hbs'),
'i18nprecompile': projectResource('js-ux', 'rc/require-handlebars-plugin/hbs/i18nprecompile'),
'json2': projectResource('js-ux', 'rc/require-handlebars-plugin/hbs/json2'),
'underscore': projectResource('js-ux', 'rc/underscore/underscore')
],
rhinoJvmArgs: [ '-Xss4m' ]
]
}
The grunt-niagara equivalent of this configuration is:
// in myModule-ux.gradle:
apply plugin: "com.tridium.niagara-grunt"
gruntBuild { tasks 'requirejs' }
// in Gruntfile.js:
requirejs: {}
That’s it! By including an empty requirejs block, RequireJS optimization will be turned on, using the default behavior. The default behavior of grunt-niagara matches the existing behavior of niagara-rjs and is described below:
.js file in src/rc into the builtfilebuild/src/rc/yourModuleName.built.min.js, where it will be packaged into the .jarbaja! plugin to start up a BajaScript session while optimizing)require-handlebars-plugin to package Handlebars templates into the builtfileMost of the customization for the requirejs task in grunt-niagara is identical to the customization for niagara-rjs, just converted from Groovy to JavaScript. Any customization you provide will be merged in with the defaults, so you do not need to customize every single rule, only the ones that differ from the default. All configuration options supported by grunt-contrib-requirejs are supported in grunt-niagara.
One thing that differs is that projectResource is no longer available because grunt-niagara runs outside the scope of any Gradle project. Instead, use moduleResources as shown:
// moduleResources allows resources from other Niagara modules to be
// included in your builtfile. usually, you would want them to be
// excluded using an 'empty:' path to avoid code duplication. but if
// you want to avoid the dependency on the other module, you can build
// it in to avoid the additional download.
// note that this requires moduledev.properties to be configured to see
// the source directory of the source module. see above for more info on
// moduledev mode.
requirejs: {
options: {
moduleResources: {
'underscore': 'nmodule/js/rc/underscore/underscore.min'
}
}
}