Module
Questions 🤔
- What Happens When a Module Is Imported Twice?
- What is the benefit of building tools?
- Is it possible to export const function?
- What is the purpose of modules?
- What are the best practices of modules?
JS modules (also known as “ES modules” or “ECMAScript modules”) are a major new feature, or rather a collection of new features. As our application grows bigger, we want to split it into multiple files, so-called modules
. A module may contain a class or a library of functions for a specific purpose.
Within a module, you can use the export keyword to export just about anything. You can export a const, a function, or any other variable binding or declaration. Just prefix the variable statement or declaration with export.
Core module features
A module is just a file. One script is one module. As simple as that.
🔸 export
keyword labels variables and functions that should be accessible from outside the current module.
🔸 import
allows the import of functionality from other modules.
The import
directive loads the module by path ./message.js
relative to the current file, and assigns exported function conveyMessage
to the corresponding variable.
use strict
🔸 Always Modules always use strict
, by default
🔸 Module-level scope
Each module has its own top-level scope. In other words, top-level variables and functions from a module are not accessible from an outside script
In order to use we need to export from one script and import it in another.
🔸 A module code is evaluated only the first time when imported
If the same module is imported into multiple other places or in the same script, its code is executed only the first time
, then exports are given to all importers.
🔸 HTML-style comment syntax is not supported in modules, although it works in classic scripts
Let's see with another example
Changes made in ironman.js
file are visible in infinityWar.js
So let's summarize, the module is executed only once. Exports are generated, and then they are shared between importers, so if something changes from one module will reflect in another imported module
🔸 import.meta
The object import.meta
contains information about the current module.
Its content depends on the environment. In the browser, it contains the URL of the script, or a current webpage URL if inside HTML
this
is undefined
🔸 In a module, The this
within modules does not refer to the global this
, and instead is undefined
. (Use globalThis
if you need access to the global this.)
Compare it to non-module scripts, where this is a global object
bare
modules allowed
🔸 No In the browser, the import must get either a relative
or absolute
URL. Modules without any path are called bare modules
. Such modules are not allowed in import
.
Certain environments, like Node.js or bundle tools, allow bare modules, without any path, as they have their own ways for finding modules and hooks to fine-tune them. But browsers do not support bare modules yet.
Build tools
In real-life, browser modules are rarely used in their raw
form. Usually, we bundle them together with a special tool such as Webpack
and deploy it to the production server.
One of the benefits of using bundlers – they give more control over how modules are resolved, allowing bare modules and much more, like CSS/HTML modules.
Build tools anatomy
- Take a
main
module, the one intended to be put in HTML<script type="module">
- Analyze its dependencies: imports and then imports of imports etc.
- Build a single file with all modules (or multiple files, that’s tunable), replacing native import calls with 4. 4. bundler functions so that it works.
Special
module types like HTML/CSS modules are also supported. - In the process, other transformations and optimizations may be applied
- Unreachable code removed.
- Unused exports removed
tree-shaking
. - Development-specific statements like console and debugger removed.
- Modern, bleeding-edge JavaScript syntax may be transformed into an older one with similar functionality using Babel.
- The resulting file is minified (spaces removed, variables replaced with shorter names, etc).
- If we use bundle tools, then as scripts are bundled together into a single file (or few files), import/export statements inside those scripts are replaced by special bundler functions. So the resulting
bundled
script does not contain any import/export, it doesn’t requiretype="module"
Export and Import
Export and import directives have several syntax variants
Export before declarations
We can label any declaration as exported by placing export
before it, be it a variable, function or a class
Remember
We should not use the semicolon
after exporting class/function
Export apart from declarations
We can declare class/function in the first place and then we can export them separately in bulk or in single. Or, technically we could put export above functions as well.
*
import Usually, we use {...}
to import a list of items. If we want to import lots of items then we could probably use import *
or import * as <object>
which will return all the imports in a single object
as
import as
keyword can be used in the import statement to alias our import module
as
Export Like import as
it's similar to the export directive
Default export
Sometimes we may box all the functions/methods, objects, or constants into a single module to make it more clean and neat in that case export default
is a JOHN RAY to make one thing per module.
default export is possible with functions, class, objects, enums, etc.
Remember
- There can be only one default mode in a single file. But we can have other optional exports into the single file
- If your importing a default module then it's not required to use
{}
- For default export, we can always choose the name when importing but whereas in named export the name has to be same as defined
default
name
The In some situations, the default
keyword is used to reference the default export
Dynamic Imports
So far we have seen the import and export which are called Static
where the syntax of these static import/export in simple but strict
The import(module)
expression loads the module and returns a promise that resolves into a module object that contains all its exports. It can be called from any place in the code.
Dynamically importing module using Promise.all()
Note
We can't use static imports anywhere in that. In case if we want to use the imports we can achieve that using
import(module)
webpack has its own version of
import()
that cleverly splits the imported module into its own chunk, separate from the main bundle.Although
import()
looks like a function call, it’s a special syntax that just happens to use parentheses (similar to super()).So we can’t copy
import
to a variable or usecall/apply
with it. It’s not a function.
Reference