What are Modules in JavaScript? 🤔
The Module Pattern is one of the important patterns in JavaScript. It is a commonly used Design Pattern which is used to wrap a set of variables and functions together in a single scope. It is essentially a piece of code written in a file that exposes a public API for other files to call and use. Just like regular Web APIs, modules enable developers to share an executable piece of code that accepts and returns values.
A module is just a file. One script is one module.
Modules can load each other and use special directives export and import to interchange functionality, call functions of one module from another one:
👉 export
keyword labels variables and functions that should be accessible from outside the current module.
👉 import
allows the import of functionality from other modules.
For instance, if we have a file sayHi.js exporting a function:
// 📁 👋sayHello.js
export function sayHello(user) {
alert(`Hello, ${user}!`);
}
// 📁 main.js
import {sayHi} from './sayHello.js';
alert(sayHi); // function...
sayHi('Irene'); // Hello, Irene!
👉 It is used to define objects and specify the variables and the functions that can be accessed from outside the scope of the function. We expose certain properties and function as public and can also restrict the scope of properties and functions within the object itself, making them private. This means that those variables cannot be accessed outside the scope of the function. We can achieve data hiding an abstraction using this pattern in the JavaScript.
The benefits of using modules
A modular approach will give your project the following features:
Organization: Allows you to organize your code into small file chunks, with each file responsible for one job.
Abstraction: Hides the implementation detail so you don’t need to understand how the code runs.
Encapsulation: Just like you can expose a piece of code from a file, you can also hide / protect another piece of code from public access.
Reusability: By exposing a piece of code that has accepts input and returns output, your code becomes a processing machine that can be reused by other pieces of code again and again.
Understanding import & export
The import and export statements are one of the most crucial features of JavaScript ES6. It allows you to import and export JavaScript classes, functions, components, constants, any other variables between one JavaScript file and another.
This feature allows you to organize your JavaScript code into small, bite-size files. Making it easier to share, improve, manage, and debug your code as the development phase requires.
How JavaScript export works 🤔 ?
You can use a JavaScript export statement to export any JavaScript variable, function, or class. There is no limit to how many times you can export modules in one JavaScript file:
// example.js
export const user = 'Irene'
export let days = ['Monday', 'Tuesday', 'Wednesday']
export var countries = ['Bulgaria', 'Germany']
export function sayHi() {
console.log('Hello World!')
}
export const greet = name => {
console.log('Hello ' + name + '!')
}
export class User {
constructor(username){
this.username = username
}
}
All of these exports are valid.
Multiple exports in a separate line
The example above can be used to export multiple modules, but you can also export modules in a separate line by using the export { .., .., .. }
syntax:
const user = 'Irene'
let days = ['Monday', 'Tuesday', 'Wednesday']
var countries = ['Bulgaria', 'Germany']
function sayHi() {
console.log('Hello World!')
}
const greet = name => {
console.log('Hello ' + name + '!')
}
class User {
constructor(username){
this.username = username
}
}
export {user, days, countries, sayHi, greet, User}
🛑 Notice how user
and User
could be used in one file without any error. JavaScript is case-sensitive, so it treats them as separate variables.
How JavaScript import works
There are multiple ways to import a module in JavaScript. First, you can import specific modules by using the import { .. } from ..
syntax:
import { user, days, countries } from './example'
The from
keyword will tell JavaScript which file to look for the modules. Alternatively, you can import code and run it immediately by omitting the variable name and directly importing the file:
import './example'
sayHi();
Since the entire example.js code is executed with the import statement, you can call the sayHi()
function immediately after that.
Named export and import variables
You can rename exported variables with the as keyword:
export { greet as greetings, user as myUser }
// you need to import with the new names
import { greetings, myUser } from './example'
And the same can be done with imports:
export { greet, user }
import { greet as greetings, user as myUser } from './example'
Default export and import
When you have only one module to export, you can use the export default statement:
export default class User {
constructor(username){
this.username = username
}
}
// or
class User {
constructor(username){
this.username = username
}
}
export default User
Unlike regular imports, a default import doesn’t use curly braces {} to wrap its modules:
import User from './example'
Instead of using the default keyword, default import simply write a variable name followed by from statement. Also, the variable name you declared for default import doesn’t need to match the export default variable name:
class User {
constructor(username){
this.username = username
}
}
export default User
// can be imported like this
import usr from './example'
The example above will be understood as import User as usr by JavaScript.
@ symbol in JavaScript import statements
As you code and collaborate with others through GitHub and any other medium, you might find some open source code using @ symbol in their import .. from .. syntax like this:
import Button from '@/components/Button'
// or
import Button from '~/components/Button'
The @ and ~ symbols are custom module loaders that are not part of JavaScript standard specification. Most likely, your project has a configuration file that can understand the symbols when you compile your code (usually through Babel or Webpack).
For example, babel-plugin-root-import treats the symbol as the root path, so you can write @/components
instead of ../../components
.
Note that this is different from NPM scoped packages, which also use @
before the package name
RECAP
👉 In JavaScript, you can export modules in three different ways:
by placing the export statement before the module: export const ..
syntax
Or in a separate line: export { a, b, c}
You can also specify a default export with export default ..
And named export with export {xyz as abc}
👉 Then you can also import these modules as:
An import all with import * as x from ..
syntax
A default import with import x from ..
Multiple import with import {x, y, z} from ..
Named import with import { x as c } from ..
Run import code immediately with import 'x'
JavaScript is case-sensitive, so you might have x
is not defined error if you have a mismatch between your import and export statement.
🌴