Many modern websites rely heavily on JavaScript. Each one has at least several home-cooked and 3rd party libraries. With the number of them growing, it becomes increasingly difficult to manage all of them, especially if you want to make sure to minimize traffic overhead by loading only what's absolutely necessary for the particular page.
That's where libraries like RequireJS come into play.
It helps reducing the initial load of the web page by implementing asynchronous loading of JavaScript files, as well as manages dependencies for you.
If you're not familiar with RequireJS, we suggest you go through their get started article first. If you're already up to speed, read on.
This tutorial focuses on how you can use RequireJS to load amCharts libraries.
Download RequireJS#
Before you can do anything with RequireJS, you will need to download it and install on your web server.
Alternatively, you can use one of the many CDN mirrors, to load RequireJS files.
Scaffolding#
We are using almost the same scaffolding as in their tutorial, so for that please create something like as below:
- project-directory/
- project.html
- scripts/
- main.js
- require.js
- amcharts/
- amcharts.js
- pie.js
- ...
Less HTML code#
There is not that much HTML code to write here - just ensure we have the require.js
API and our chart container in the project.html
file.
<!DOCTYPE html> <html> <head> <title>requireJS | amCharts.com</title> <script data-main="scripts/main" src="scripts/require.js"></script> </head> <body> <div id="chartdiv" style="width: 600px; height: 400px;"></div> </body> </html>
RequireJS reads its data-main
attribute and loads our main.js
file, which gets filled up in the next step.
Config#
RequireJS needs to know where amCharts is located. To do so, copy following code into main.js
// SETUP CONFIG requirejs.config( { // Define paths; relative from js folder "paths": { "amcharts": "//www.amcharts.com/lib/3/amcharts", "amcharts.funnel": "//www.amcharts.com/lib/3/funnel", "amcharts.gauge": "//www.amcharts.com/lib/3/gauge", "amcharts.pie": "//www.amcharts.com/lib/3/pie", "amcharts.radar": "//www.amcharts.com/lib/3/radar", "amcharts.serial": "//www.amcharts.com/lib/3/serial", "amcharts.xy": "//www.amcharts.com/lib/3/xy" }, // Define dependencies "shim": { "amcharts.funnel": { "deps": [ "amcharts" ], "exports": "AmCharts", "init": function() { AmCharts.isReady = true; } }, "amcharts.gauge": { "deps": [ "amcharts" ], "exports": "AmCharts", "init": function() { AmCharts.isReady = true; } }, "amcharts.pie": { "deps": [ "amcharts" ], "exports": "AmCharts", "init": function() { AmCharts.isReady = true; } }, "amcharts.radar": { "deps": [ "amcharts" ], "exports": "AmCharts", "init": function() { AmCharts.isReady = true; } }, "amcharts.serial": { "deps": [ "amcharts" ], "exports": "AmCharts", "init": function() { AmCharts.isReady = true; } }, "amcharts.xy": { "deps": [ "amcharts" ], "exports": "AmCharts", "init": function() { AmCharts.isReady = true; } } } } );
The paths
defines the module names with its source location, requireJS adds automatically the ".js" extension.
The shim
contains the requirements for the modules and exports the AmCharts variable to the RequireJS modules, since it's loaded we need to set AmCharts.isReady manually because the framework has been loaded asynchronously otherwise the framework will wait for the "onload" event.
The fun part#
So now RequireJS knows where the files are and what to do when they are ready. Now we can create the actual worker modules, simply copy following code after the config:
// LOAD DEPENDENCIES; CREATE CHART require( [ "amcharts.pie" ], function( amRef ) { var chart = amRef.makeChart( "chartdiv", { "type": "pie", "dataProvider": [ { "country": "Lithuania", "litres": 501.9 }, { "country": "Czech Republic", "litres": 301.9 }, { "country": "Ireland", "litres": 201.1 }, { "country": "Germany", "litres": 165.8 }, { "country": "Australia", "litres": 139.9 }, { "country": "Austria", "litres": 128.3 }, { "country": "UK", "litres": 99 }, { "country": "Belgium", "litres": 60 }, { "country": "The Netherlands", "litres": 50 } ], "valueField": "litres", "titleField": "country" } ); // ERROR HANDLER }, function( err ) { console.log( "Something went wront: ", err ); } );
Before RequireJS loads our pie.js
class, it will load its dependencies that we've defined in the config above within the shim
parameter. Since pie.js
is ready with all it's requirements it will call our passed callback with a reference of AmCharts to build the chart (we used our Simple Pie Chart from our demos).
Here's a working demo of the above:
What about plugins?#
Our plugins have the same dependency as the chart types, the core itself amcharts.js
. You just need to append the plugins to your paths, add the shim and your plugin is ready to get opt-in.
// SETUP CONFIG requirejs.config( { // Define paths; relative from js folder paths: { //... 'amcharts.plugins.responsive': '//www.amcharts.com/lib/3/plugins/responsive', 'amcharts.plugins.dataloader': '//www.amcharts.com/lib/3/plugins/dataloader' }, // Define dependencies shim: { // ... 'amcharts.plugins.responsive': { deps: [ 'amcharts' ] }, 'amcharts.plugins.dataloader': { deps: [ 'amcharts' ] } } );
Handling Export plugin#
Export plugin is a bit more complicated, because it relies on a number of external libraries, that it tries do load dynamically, which might seriously mess up your Require setup.
To fix that, you will need to add all those dependencies to the RequireJS setup. Furthermore, we need to ensure that correct hierarchy of dependencies is maintained. I.e. Export plugin relies on amcharts.js being loaded. pdfmake library needs to be loaded only when export.min.js was loaded. While pdfFonts.js needs pdfmake to be there when it loads.
This all leads to a rather more complicated path and dependency setup:
requirejs.config( { "paths": { "amcharts": "https://www.amcharts.com/lib/3/amcharts", "amcharts.serial": "https://www.amcharts.com/lib/3/serial", "amcharts.theme.light": "https://www.amcharts.com/lib/3/themes/light", "amcharts.export": "https://www.amcharts.com/lib/3/plugins/export/export.min", "amcharts.plugins.export.libs.blob": "https://www.amcharts.com/lib/3/plugins/export/libs/blob.js/blob", "amcharts.plugins.export.libs.fabric": "https://www.amcharts.com/lib/3/plugins/export/libs/fabric.js/fabric", "amcharts.plugins.export.libs.fileSaver": "https://www.amcharts.com/lib/3/plugins/export/libs/FileSaver.js/FileSaver", "amcharts.plugins.export.libs.jszip": "https://www.amcharts.com/lib/3/plugins/export/libs/jszip/jszip", "amcharts.plugins.export.libs.pdfmake": "https://www.amcharts.com/lib/3/plugins/export/libs/pdfmake/pdfmake", "amcharts.plugins.export.libs.pdfFonts": "https://www.amcharts.com/lib/3/plugins/export/libs/pdfmake/vfs_fonts", "amcharts.plugins.export.libs.xlsx": "https://www.amcharts.com/lib/3/plugins/export/libs/xlsx/xlsx" }, "shim": { "amcharts.serial": { "deps": [ "amcharts" ], "exports": "AmCharts", "init": function() { AmCharts.isReady = true; } }, "amcharts.theme.light": { "deps": [ "amcharts" ], "exports": "AmCharts", "init": function() { AmCharts.isReady = true; } }, "amcharts.plugins.export.libs.pdfFonts": { "deps": [ "amcharts.plugins.export.libs.pdfmake" ] }, "amcharts.export": { "deps": [ "amcharts", "amcharts.plugins.export.libs.blob", "amcharts.plugins.export.libs.fabric", "amcharts.plugins.export.libs.fileSaver", "amcharts.plugins.export.libs.jszip", "amcharts.plugins.export.libs.pdfmake", "amcharts.plugins.export.libs.pdfFonts", "amcharts.plugins.export.libs.xlsx" ], "exports": "AmCharts", "init": function() { AmCharts.isReady = true; // CSS exception; load once it's ready var link = document.createElement( "link" ); link.type = "text/css"; link.rel = "stylesheet"; link.href = "https://www.amcharts.com/lib/3/plugins/export/export.css"; document.getElementsByTagName( "head" )[ 0 ].appendChild( link ); } } } } );
IMPORTANT! You will also need to disable the automatic loading of libraries by the Export plugin:
"export": { "enabled": true, "libs": { "autoLoad": false } }
You may also need to separately require
the jszip library before creating the chart:
require(['amcharts.plugins.export.libs.jszip'], function(jszip) { window.JSZip = jszip; });
Here's a demo that shows all of this in action: