Home >Web Front-end >JS Tutorial >Using RequireJS in AngularJS Applications
Core points
One of the easiest ways to write large JavaScript applications is to split the code base into multiple files. Doing so can improve the maintainability of your code, but can increase the possibility of missing or misplaced script tags in the main HTML document. As the number of files increases, tracking dependencies becomes difficult. This problem also exists in large AngularJS applications. We already have many tools to handle the loading of dependencies in our application. In this article, we will learn how to use RequireJS with AngularJS to simplify the work of loading dependencies. We will also look at how to use Grunt to generate a combo file containing the RequireJS module.
Introduction to RequireJS
RequireJS is a JavaScript library that helps to delay loading JavaScript dependencies. The module just contains some JavaScript files that require JS syntax sugar. RequireJS implements the asynchronous module specified by CommonJS. RequireJS provides a simple API to create and reference modules. RequireJS requires a main file that contains basic configuration data, such as the paths to modules and shims. The following code snippet shows the framework of the main.js file:
<code class="language-javascript">require.config({ map: { //映射 }, paths: { //模块的别名和路径 }, shim: { //模块及其依赖模块 } });</code>
All modules in the application do not need to be specified in the paths section. Other modules can be loaded using their relative paths. To define a module, we need to use the define() block.
<code class="language-javascript">define([ //依赖项 ], function ( //依赖项对象 ) { function myModule() { //可以使用上面接收到的依赖项对象 } return myModule; });</code>
Modules may have some dependent modules. Usually, an object is returned at the end of the module, but this is not a mandatory requirement.
Angular's dependency injection and RequireJS dependency management
A common question I've heard from Angular developers is about the difference between Angular's dependency management and RequireJS's dependency management. It is important to remember that the purpose of these two libraries is completely different. The built-in dependency injection in AngularJS requires the Object required in the system processing component; while the dependency management processing module or JavaScript file in RequireJS. When RequireJS tries to load modules, it checks all dependent modules and loads them first. The objects of the loaded module are cached and are provided when the same module is requested again. AngularJS, on the other hand, maintains an injector containing a list of names and corresponding objects. When a component is created, the entry is added to the injector and is provided whenever an object is referenced with the registered name.
The combination of RequireJS and AngularJS
The downloadable code that comes with this article is a simple application with two pages. It has the following external dependencies:
These files should be loaded directly into the page in the order listed here. We have five custom script files that contain the code for the required AngularJS component. Let's see how these files are defined.
Define AngularJS component as RequireJS module
Any AngularJS component contains:
In the above three tasks, we will execute the first two tasks within each module, and the third task will be performed in a separate module responsible for creating the AngularJS module. First, let's define a config block. The config block does not depend on any other blocks and returns the config function at the end. However, before we load the config module inside another module, we need to load everything we need to config blocks. config.js contains the following code:
<code class="language-javascript">require.config({ map: { //映射 }, paths: { //模块的别名和路径 }, shim: { //模块及其依赖模块 } });</code>
Please note the way dependency injection is in the above code snippet. I use $inject
to inject the dependency because the config function defined above is a normal JavaScript function. Before closing the module, we return the config function so that it can be sent to the dependent module for further use. We also take the same approach to defining any other type of Angular components, because there is no component-specific code in these files. The following code snippet shows the definition of the controller:
<code class="language-javascript">define([ //依赖项 ], function ( //依赖项对象 ) { function myModule() { //可以使用上面接收到的依赖项对象 } return myModule; });</code>
The Angular module of the application depends on each module defined so far. This file takes objects from all other files and hooks them to the AngularJS module. This file may or may not return anything, as the Angular module of this file can be referenced from anywhere using angular.module()
. The following code block defines an Angular module:
<code class="language-javascript">require.config({ map: { //映射 }, paths: { //模块的别名和路径 }, shim: { //模块及其依赖模块 } });</code>
Because the required script file is loaded asynchronously, it is impossible to boot the Angular application using the ng-app directive. The correct way here is to use manual boot. This must be done in a special file called main.js. This requires first loading of the file that defines the Angular module. The code for this file is shown below.
<code class="language-javascript">define([ //依赖项 ], function ( //依赖项对象 ) { function myModule() { //可以使用上面接收到的依赖项对象 } return myModule; });</code>
Configure Grunt to combine RequireJS modules
When deploying JavaScript-heavy applications, script files should be combined and compressed to optimize the download speed of script files. Tools like Grunt can easily automate these tasks. It defines many tasks, making any front-end deployment process easier. It has a task, grunt-contrib-requirejs
, for combining the RequireJS file module in the correct order, and then compressing the result file. Like any other grunt task, it can be configured to behave differently for each stage of the deployment. The following configuration can be used for demonstration applications:
<code class="language-javascript">define([], function () { function config($routeProvider) { $routeProvider.when('/home', {templateUrl: 'templates/home.html', controller: 'ideasHomeController'}) .when('/details/:id', {templateUrl: 'templates/ideaDetails.html', controller: 'ideaDetailsController'}) .otherwise({redirectTo: '/home'}); } config.$inject = ['$routeProvider']; return config; });</code>
This configuration will generate uncompressed files when running Grunt with the dev option and generate compressed files when running grunt with the release option.
Conclusion
Managing dependencies can become challenging when the application size exceeds a certain number of files. Libraries like RequireJS make it easier to define dependencies without worrying about file loading order. Dependency management is becoming an integral part of JavaScript applications. AngularJS 2.0 will support AMD in built-in.
(The FAQs part has been omitted because it is too long and does not match the pseudo-original goal. The FAQs part can be regenerated as needed.)
The above is the detailed content of Using RequireJS in AngularJS Applications. For more information, please follow other related articles on the PHP Chinese website!