Angular Modules vs ES6 Modules
Aren't Angular modules and ES6 modules the same? No? In this quick tutorial, you'll find out how they differ, and when to use each.
Join the DZone community and get the full member experience.
Join For FreeI often see people being confused when it comes to understanding Angular Modules vs. ES6 Modules. This happens especially for newcomers in the JavaScript and front-end development ecosystem and immediately get confronted with both of them. Here’s a short article that hopefully sheds some light on the matter.
Contents are based on Angular version 2+.
To start straight away: Angular Modules are different from ES6 Modules!
JavaScript Modules Primer
I don’t like to repeat the same content, so if you want to get an exhaustive introduction of what JavaScript modules are about, I highly recommend reading the article on “A 10-minute primer to JavaScript modules, module formats, module loaders and module bundlers” by my friend Jurgen Van de Moere.
In short, we need JavaScript modules to:
- Avoid leaking code to the global namespace and thus to avoid naming collisions.
- Encapsulate code to hide implementation details and control what gets exposed to the “outside.”
- Structure our applications (we cannot use a single file).
- Manage dependencies.
- Reuse code.
Prior to ES2015 (ES6), there was no module system in the standard of the ECMAScript language. What we had (and still have) instead, are different implementation patterns for “simulating” a module system: there are the simple IIFEs (Immediately Invoked Function Expressions), UMD (Universal Module Definition), AMD (Asynchronous Module Definition) and CommonJS. ES6 finally introduced a standard way of defining modules. This example illustrates a simple ES6 module, importing a dependency math-utils
, specifically the sqrt
function of that math-utils
library. It then defines a couple of math operations and exports the addition
and multiplication
:
import { sqrt } from 'math-utils';
const addition = (val1, val2) => val1 + val2;
const subtraction = (val1, val2) => val1 - val2;
const multiplication = (val1, val2) => val1 * val2;
const calculateSquareRoot = (val) => sqrt(val);
export { addition, multiplication }
In short, an ES6 module is represented by a single file, having different imports and exports.
What are Angular Modules?
Angular modules represent a core concept and play a fundamental role in structuring Angular applications.
An Angular Module groups together a set of Angular artifacts, namely components, directives, pipes, and services that are part of that very same module. That said, it represents a logical grouping into what can be called a feature area of our application (i.e. contacts module, admin module, etc.). Moreover, an Angular Module also defines dependencies to other modules, that is, what other modules it needs to import and in turn which components, directives or pipes get exported.
@NgModule({
imports: [ BrowserModule, HttpModule, FormsModule ],
declarations: [ PersonComponent, ContactComponent, ContactListComponent ],
providers: [ PersonService, ContactService ],
exports: [ ContactListComponent, ContactComponent ]
})
export class ContactModule {}
In this example, we see imports such as the FormsModule
whose exports can now be used within our ContactModule
. Moreover, the module declares what components it uses in the declarations
property and the services in the according providers
property. As you can see from the exports
property, we only export certain components which are then available to other consumers of our ContactModule
.
Angular modules are a logical grouping of multiplesymbols (components, services, etc.).
Also, reusing components, services, etc. is done at the module level. We don’t directly import a single component from another module such as the people.component
in the following example.
Rather, we have another module, say the PeopleModule
, which already imports its own PersonComponent
, declares it, and also exports it so that it can then be used by other modules. Consequently, in our ContactsModule
we simply import the PersonModule
and can then use the exported PersonComponent
within the components of our ContactsModule
.
The following shows an example of a modular application with a “shared” and “contacts” module. Internally, the Contacts Module contains other artifacts such as person components.
As such, Angular Modules can be seen as the “unit of reusability” within our application. As we have seen, they define their members, what gets imported, and what gets exported. It is also best practice to encapsulate the module specific application routes within the module itself. Hence, ideally, when we want to get rid of a feature of our application, say the contacts feature, we could simply delete the according Angular Module, with a minimum impact on the other areas of the application.
"Angular Modules are the unit of reusability"
We usually tend to structure our application into feature modules (contacts module, orders module, admin module) and “transversal” modules containing shared components and services that are used by other feature modules throughout our application.
Could I simply have one single application module?
Technically you can, but it’s definitely not recommended, as this most probably results in a poor application structure, is bad for the modularity of your application, and you also end up with some features, such as lazy loading, that are performed at the Angular module level. All in all, don’t do it, it completely messes up your application architecture.
To summarize, Angular modules are a means to logically group a set of symbols (components, services, etc.). An Angular module usually comprises an entire folder.
Want to learn more about NgModule? Check out the FAQ page on the official Angular documentation.
Conclusion
To conclude:
- ES6 modules represent a single file.
- The ES6 module syntax is a standardized construct of the ECMAScript language specification.
On the other side:
- Angular Modules are an Angular-specific construct.
- Angular Modules logically group different Angular artifacts such as components, pipes, directives, etc.
- Angular Modules in the form of the
@NgModule
decorator provide metadata to the Angular compiler which in turn can better “reason about our application” structure and thus introduce optimizations. - Important features such as lazy loading are done at the Angular Module level.
Thanks a lot to Wassim Chegham (@manekinekko) for reviewing this article!
If you enjoyed this post you might want to follow me on Twitter for more news around JavaScript and Angular.
Published at DZone with permission of Juri Strumpflohner. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments