blob: c524a72bc024be689f8f2c521f6785912794d3df [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.7.1">
<title>Modules</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- ************* Meta ************* -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<!-- ************* OpenGraph ************-->
<meta name="description" content="The Eclipse N4JS language and its IDE enable high-quality JavaScript development for large Node.js projects.">
<meta property="og:site_name" content="Eclipse N4JS"/>
<meta property="og:title" content="Eclipse N4JS Language and IDE"/>
<meta property="og:url" content="https://numberfour.github.io/n4js"/>
<meta property="og:description" content="The Eclipse N4JS language and its IDE enable high-quality JavaScript development for large Node.js projects."/>
<meta property="og:image" content="../images/n4js.png">
<!-- ************* Favicon ************-->
<link rel="icon" href="../images/favicon.ico" />
<link rel="icon" type="image/png" href="../images/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="../images/favicon-16x16.png" sizes="16x16" />
<!-- ************* Back-to-top JQuery ************* -->
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<!-- ************* Prism.js Syntax Highlighter ******-->
<link href="../styles/prism.min.css" rel="stylesheet"/>
<script src="../scripts/prism.js"></script>
<!-- ************* Styles ************* -->
<link rel="stylesheet" type="text/css" href="../styles/n4js-adoc.css">
<!-- ****************** NavBar ****************** -->
<div id="menubar">
<div class="banner">
<a href="../index.html"><img id="logo" src="../images/n4js-logo.png" alt="Eclipse N4JS Language and IDE"></a>
</div>
<ul>
<li><a href="../downloads.html"></i>Download</a></li>
<li><a href="../community.html"></i>Community</a></li>
<li><a href="../userguides/index.html">Documentation</a></li>
</ul>
</div>
<button id="tocbutton">TOC</button>
</head>
<body class="book">
<div id="header">
</div>
<div id="content">
<h1 id="_modules" class="sect0"><a class="link" href="#_modules">Modules</a></h1>
<div class="openblock partintro">
<div class="title">Modules</div>
<div class="content">
Large-scale projects of almost any language require good modularization for maintenance reasons.
It&#8217;s vital for projects that modules don&#8217;t become oversized and comprise a well-defined purpose
that is easy to comprehend for developers. The N4JS IDE helps for keeping track of your code modules and validates their usage.
</div>
</div>
<div class="sect1">
<h2 id="_multiple_exports"><a class="link" href="#_multiple_exports">Multiple Exports</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>While it&#8217;s a good habit to assign one module for a single type, it may
be suitable to define multiple types or variables in a single module in cases where they
correspond or are related.
ECMAScript 2015 allows for this with the module syntax it defines. The good news is
that N4JS already supports most of it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-n4js" data-lang="n4js">export public function inc(): void { ++count; }
export public var count = 5;
export default public class Foo {
public callOnIt(): void { }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Importing an ECMAScript 2015 module and consuming exports is as easy as the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-n4js" data-lang="n4js">import { inc, count } from 'Counter';// Named imports
import Foo from 'Counter'; // Default import
import { readFile } from 'fs' // Node.js core modules
import express from 'express'; // npm modules
import * as plainJsModule+ from 'plainJsModule'; // Dynamic import</code></pre>
</div>
</div>
<div class="paragraph">
<p>The module could also be imported as a whole:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-n4js" data-lang="n4js">import * as foo from 'Counter'; // Namespace import</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Anonymous default exports and relative module paths are not yet supported. The module specifier is the relative path of the
module in its source folder. Optionally the project name can be used as prefix, e.g., in case of ambiguities.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_n4js_ide_organizes_imports"><a class="link" href="#_n4js_ide_organizes_imports">N4JS IDE Organizes Imports</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Manually writing import statements is not necessary: the N4JS IDE does this automatically.
The IDE will recognise all projects involved via various runtime and
library dependencies that are defined in by the user in the manifest.n4mf file.
Simply write the type or variable you require and press <span class="keyseq"><kbd>Ctrl</kbd>+<kbd>SPACE</kbd></span>.
Content assist within the IDE will add the missing import statement for you:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/moduleimport.png" alt="moduleimport">
</div>
</div>
<div class="paragraph">
<p>When pasting in a code snippet, you could use <span class="keyseq"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>O</kbd></span>
(on Windows and Linux, <span class="keyseq"><kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>O</kbd></span> on Mac) which organizes your imports and
will add any that are missing. This is also used to clean up any unused imports:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/organizeimports.png" alt="organizeimports">
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_import_removal"><a class="link" href="#_import_removal">Import Removal</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>When developing in N4JS, you may notice that you sometimes need to import types to cast
a variable or use it for a constraint in a generic.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-n4js" data-lang="n4js">import Foo from 'Counter';
var someOtherVar: Object;
(someOtherVar as Foo).callOnIt();
export function &lt;T extends Foo&gt; bar(t: T): void { }</code></pre>
</div>
</div>
<div class="paragraph">
<p>The compiler will notice that there&#8217;s no runtime code dependency on the
imported module and will omit loading the module.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_read_only_views"><a class="link" href="#_read_only_views">Read-only Views</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>ES2015 modules have the concept of read-only views. Although you cannot modify anything imported from
a module, your binding is live. In the case that the exporting party has modified
the export, you will read the current value. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-n4js" data-lang="n4js">import {inc, count} from 'Counter';
console.log(count); // 5
inc();
console.log(count); // 6</code></pre>
</div>
</div>
<div class="paragraph">
<p>Although highly discouraged, read-only views allow to support some cyclic
dependencies across modules. N4JS might even reorder type definitions to achieve this.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_loader_details"><a class="link" href="#_loader_details">Loader Details</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>So far, there&#8217;s no engine/platform that has implemented the ES2015 specification natively. N4JS
and most other transpilers, transpile modules into the SystemJS format.</p>
</div>
<div class="paragraph">
<p>N4JS' output format goes a bit further and emits an unified format that works as well in a
synchronous CommonJS/Node.js environment.
Keep in mind, however, that when you load a module the CommonJS way, you are
limited to this with regard to cyclic dependencies because it has to resolve all
dependencies synchronously.</p>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
</div>
</div>
<div class="Grid social" style="color:#d5dfea">
<div class="Cell Cell--2-12 m-Cell--withMargin">
<h2>Quick Links</h2>
<ul>
<li><a href="../downloads.html">Download</a></li>
<li><a href="../userguides/index.html">Documentation</a></li>
<li><a href="https://github.com/eclipse/n4js/">Source</a></li>
<li><a href="https://github.com/eclipse/n4js/issues">Issues</a></li>
</ul>
</div>
<div class="Cell Cell--2-12 m-Cell--withMargin">
<br/><br/>
<ul>
<li><a href="https://www.eclipse.org/forums/index.php/f/365/">Forum</a></li>
<li><a href="http://n4js.blogspot.de/">Blog</a></li>
<li><a href="https://dev.eclipse.org/mailman/listinfo/n4js-dev">Mailing List</a></li>
<li><a href="https://projects.eclipse.org/projects/technology.n4js">Eclipse Project Page</a></li>
<li><a href="https://twitter.com/n4jsdev">Tweets by n4jsdev</a></li>
</ul>
</div>
<div class="Cell Cell--2-12 m-Cell--withMargin">
<br/><br/>
<ul>
<li><a href="http://www.eclipse.org/">Eclipse Home</a></li>
<li><a href="http://www.eclipse.org/legal/privacy.php">Privacy Policy</a></li>
<li><a href="http://www.eclipse.org/legal/termsofuse.php">Terms of Use</a></li>
<li><a href="http://www.eclipse.org/legal/copyright.php">Copyright Agent</a></li>
<li><a href="http://www.eclipse.org/legal/">Legal</a></li>
</ul>
</div>
<div style="clear: both; height: 0; overflow: hidden;"></div>
</div>
<script>
// Toggle the table of contents
$( "button#tocbutton" ).click(function() {
if ($("#tocbutton").css('right') == '25px') {
$( "#tocbutton" ).animate({right: '215px'},"slow");
$( "#toc.toc2" ).animate({right: '0'},"slow");
}
else {
$( "#tocbutton" ).animate({right: '25px'},"slow");
$( "#toc.toc2" ).animate({right: '-13rem'},"slow");
}
});
</script>
<script type="text/javascript">
// Create a back to top button
$('body').prepend('<a href="#" class="back-to-top">Back to Top</a>');
var amountScrolled = 300;
$(window).scroll(function() {
if ( $(window).scrollTop() > amountScrolled ) {
$('a.back-to-top').fadeIn('slow');
} else {
$('a.back-to-top').fadeOut('slow');
}
});
$('a.back-to-top, a.simple-back-to-top').click(function() {
$('html, body').animate({
scrollTop: 0
}, 700);
return false;
});
</script>
</body>
</html>