Getting Started with Requirejs and AEM
Setup
Create project using maven archetype
Instructions for doing this can be found at the docs.adobe.com
Simplified approach
Using Eclipse (Luna)
Artifact Id myartifact
artifactName artifact
packageGroup package
appsFolderName apps
contentFolderName content
cssId cssId
componentGroupName componentGroup
siteName site
Using Eclipse (Luna)
- Click New -> Maven Project
- Ensure Create a simple project (skip archetype selection) is not checked then click Next
- Click Configure -> Add Remote Catalog. Enter http://repo.adobe.com/nexus/content/groups/public/ in the Catalog File Textbox. Put any name for Description (i.e. Adobe). Click OK
- Select the newly created Catalog Item in the dropdown. In the main box you should now see a few options. If you do not see aem-project-archetype under Artifact Id, then an error has occurred.
- Select aem-project-archetype (I'm using version 10) -> Click Next
- Here we need to specify some properties, remember kiss...
Artifact Id myartifact
artifactName artifact
packageGroup package
appsFolderName apps
contentFolderName content
cssId cssId
componentGroupName componentGroup
siteName site
- Click Finish
Getting Requirejs
Download Requirejs here
Download Requirejs here
Setup Requirejs
- Copy folder clientlib-all (located at: /ui.apps/target/classes/etc/designs/apps/clientlib-all)
- Paste to /ui.apps/target/classes/etc/designs/apps and Rename to clientlib-vendor
- Create folder "js" under clientlib-vendor
- Create folder "vendor" under js
- Modify .content.xml file
categories="[cssId.vendor]" dependencies="[jquery]"
Put the requirejs file into clientlib-vendor/js/vendor (mine is named require.js) I am using version 2.1.17
Put the requirejs file into clientlib-vendor/js/vendor (mine is named require.js) I am using version 2.1.17
Setup jQuery
Create a file named require-configuration.js under clientlib-vendor/js
In AEM, jQuery ($) is defined globally, but requirejs tries to minimize things in the global namespace. We will need to make jQuery a module to be used inside of requirejs modules.
Create a file named require-configuration.js under clientlib-vendor/js
In AEM, jQuery ($) is defined globally, but requirejs tries to minimize things in the global namespace. We will need to make jQuery a module to be used inside of requirejs modules.
(function (){
'use strict';
define(
'jquery',
[],
function() {
return jQuery;
});
}());
For more information about this go here
Wire Up Clientlibs
Create a js.txt file under clientlib-vendor
Add
Create a js.txt file under clientlib-vendor
Add
#base=js
vendor/require.js
require-configuration.js
At this point your vendor client lib structure should look like this:
Ignore the ember.js files, they are not needed for this tutorial
Simple Test
Ignore the ember.js files, they are not needed for this tutorial
Setup AEM
In headlibs.html under /apps/apps/components/structure/page/partials
Add
In headlibs.html under /apps/apps/components/structure/page/partials
Add
<sly data-sly-use.clientLib="/libs/granite/sightly/templates/clientlib.html"
data-sly-call="${clientLib.js @ categories='cssId.vendor'}" data-sly-unwrap/>
- Create a component under /apps/components/content (I named it testcomponent)
- Create a clientlib folder and a js.txt file inside the newly created component
#base=js
test.js
- Create a test.js file under the clientlib folder
- Create/Modify .context.xml file under the clientlib folder
categories="[cssId.test]"
- Create/Modify testcomponent.html
<h3 id="test-me">test component</h3>
This is what your file structure should look like:
This is what your file structure should look like:
- Modify .content.xml under /ui.content/src/main/content/jcr_root/content/content/en (This is under the ui.content project)
<testcomponent
jcr:primaryType="nt:unstructured"
sling:resourceType="apps/components/content/testcomponent"/>
I put this in between servicecomponent and title_1 but it doesn't really matter where you put it.
Putting it all together
We created a project using a maven archetype. This created a sightly ready aem project.
When setting up Require js, we created a client lib to hold the require js files inside /etc... We defined jQuery as a Require js module in the require-configuration.js file which gets loaded immediately after the initial Require js file. This does not eliminate jQuery or $ from the global namespace, as would cause problems within AEM. We then "sightly included" theses files into the headlibs.html. Typically, js is loaded at the bottom but this is a simplified approach. It is possible to put the Require js files at the bottom but then any Require js modules would need deferred until the page is completely rendered or until Require js is loaded.
For the Simple Test, we created a test component and added the clientLibs folder and test.js file. Inside this file, we added the testing criteria. In this test, all of the Require modules are in the same file. Usually, each Require module has its own file. This is where AEM client libs show its usefulness: by adding all the Require js module files into the js.txt and by using embed we can add all the client libraries, that are inside the component, to the main clientlib (cssId.all in this case which is loaded at the bottom of the page). So if we have many components, and they all have the category of cssId.test, they all will be appended to the main client file. No build tool required.
Taking a closer look at the Simple Test, there are a few things visible: a module name Spaceship is defined; the Spaceship module is required; require.config is used to set attributes for the Spaceship. Require.config can be useful if dealing with only one javascript object. In this case, using it for multiple objects may not be a best practice, but it can be seen as how it acts as a global namespace for modules.
If you don't want to go through this whole process. I put my working copy on github at https://github.com/kuckmc01/aem-6-base. There is no guarantee that this working project will work by the time you see it.
- Modify .content.xml file under /ui.apps/src/main/content/jcr_root/etc/designs/ (This is in the ui.apps project)
embed="[cssId.site,cssId.page,cssId.topnav,cssId.colctrl,cssId.textimage,cssId.test]"
- Modify the test.js file under /apps/components/content/testcomponent/clientlib/js
require(['jquery'], function( $ ) {
console.log( $('#test-me').html() ); // prints test component
});
- This will ensure we have jquery working with requirejs.
define('Spaceship', ['jquery', 'module'], function($, module) {
var Spaceship = function() {
//constructor
var me = this;
var equipment = {};
equipment.weapon = (require.config.Spaceship != undefined) ? require.config.Spaceship.defaults.weapon : 'none';
this.getEquipment = function() {
return equipment;
};
};
Spaceship.prototype.shoot = function() {
var me = this;
var equipment = this.getEquipment();
if (equipment.weapon === 'none') {
console.log('Retreat!');
} else {
console.log(equipment.weapon + ' fires');
}
};
return Spaceship;
});
require(['Spaceship'], function(Spaceship) {
require.config = {
'Spaceship': {
defaults: {
weapon: 'Laser Cannon'
}
}
};
var warship = new Spaceship();
warship.shoot();
require.config = {
'Spaceship': {
defaults: {
weapon: 'none'
}
}
};
var cargoship = new Spaceship();
cargoship.shoot();
});
- Now wrap everything inside test.js with
(function() {
//8. & 9. goes here
})();
- Fire up your AEM 6 instance (I am using AEM 6 sp2)
- Build the project using mvn clean intall -PautoInstallPackage
- Open http://localhost:4502/editor.html/content/content/en.html and view console. Should see something like this:
We created a project using a maven archetype. This created a sightly ready aem project.
When setting up Require js, we created a client lib to hold the require js files inside /etc... We defined jQuery as a Require js module in the require-configuration.js file which gets loaded immediately after the initial Require js file. This does not eliminate jQuery or $ from the global namespace, as would cause problems within AEM. We then "sightly included" theses files into the headlibs.html. Typically, js is loaded at the bottom but this is a simplified approach. It is possible to put the Require js files at the bottom but then any Require js modules would need deferred until the page is completely rendered or until Require js is loaded.
For the Simple Test, we created a test component and added the clientLibs folder and test.js file. Inside this file, we added the testing criteria. In this test, all of the Require modules are in the same file. Usually, each Require module has its own file. This is where AEM client libs show its usefulness: by adding all the Require js module files into the js.txt and by using embed we can add all the client libraries, that are inside the component, to the main clientlib (cssId.all in this case which is loaded at the bottom of the page). So if we have many components, and they all have the category of cssId.test, they all will be appended to the main client file. No build tool required.
Taking a closer look at the Simple Test, there are a few things visible: a module name Spaceship is defined; the Spaceship module is required; require.config is used to set attributes for the Spaceship. Require.config can be useful if dealing with only one javascript object. In this case, using it for multiple objects may not be a best practice, but it can be seen as how it acts as a global namespace for modules.
If you don't want to go through this whole process. I put my working copy on github at https://github.com/kuckmc01/aem-6-base. There is no guarantee that this working project will work by the time you see it.
No comments:
Post a Comment
If you have any doubts or questions, please let us know.