# NodeJS

JavaScript on the ”Server”

# Node Project Setup

  • Go over basics of creating node-based projects

    • npm init to initialize projects 初始化项目
    • npm install or npm i to install local node modules to your project 安装模块
      • --save to save dependency to package.json
        • defaults to this without flag now in current versions 在当前版本中默认为这个没有标记
      • --save-dev to save dependency as a development dependency
        保存为开发依赖项
    • npx will run local project binaries found in the node_modules folder
      npx 将运行在 node_modes 文件夹中找到的本地项目二进制文件
  • There is an alternative package manager called yarn that many people use instead of npm .

    • It was created by Facebook to enhance npm .
    • npm has now adopted many of the thing's yarn introduced.
    • Fully compatible with npm .

# ES6 Modules

  • ES6 Modules provide a way to split up your JavaScript code into separate modules and only import what is needed when you need it.
    ES6 模块提供了一种方法,可以将 JavaScript 代码分割成单独的模块,只在需要的时候导入。

  • NodeJS has a module system implemented with CommonJS .
    NodeJS 有一个用 CommonJS 实现的模块系统。

    • There have been other libraries and frameworks (CommonJS, AMD, UMD) that have enabled modules in JS but ES6 Modules is a native implementation.
      已经有其他的库和框架 (CommonJS, AMD, UMD) 在 JS 中启用了模块,但 ES6 模块是一个本地实现。
  • Most modern browsers support the ES6 syntax.
    大多数现代浏览器都支持 ES6 语法。

  • We will be using ES6 modules with the React framework and webpack
    将在 React 框架和 webpack 中使用 ES6 模块

# What do we get?

  • Modules can be more easily reusable.
    模块可以更容易地重用。
    Code can be put in smaller files that encapsulate functionality and can be shared between different applications.
    代码可以放在封装功能的较小文件中,并且可以在不同的应用程序之间共享。
  • All the code in a ES6 module is private by default and executes in strict mode.
    默认情况下,ES6 模块中的所有代码都是私有的,并在严格模式下执行。
    You must explicitly export what you want to use outside the module.
    必须明确地导出想要在模块外使用的内容。
  • Helps solve issues with namespace and naming conflicts.
    帮助解决命名空间和命名冲突的问题。

# Creating Modules

  • ES6 modules are stored in JS files. There is exactly one module per file and one file per module.
    ES6 模块存储在 js 文件中,每个文件只有一个模块,每个模块只有一个文件。
  • You can have named exports and/or a single default export
    可以命名导出和 / 或单个默认导出
  • You can export things like variables, objects, classes, functions.
    你可以导出变量,对象,类,函数之类的东西。

# Use the export keyword

  • Named exports

    export function add(){}
    export const PI = 3.1415;
  • Default exports

    • use export default , can be anonymous, only one per module
    export default function(){}
    • export multiple named exports also as default
    export default {add, Car, PI};

# Importing Modules

  • Import statement used to access what export has made available in a module
    Import 语句,用于访问模块中的 export
  • Imports must be in the top level of a module (first lines in file or script tag)
    导入必须位于模块的顶层 (文件或脚本标记的第一行)
  • Import and export can only be used in script tags that add the type="module" attribute. This goes for both external and embedded.
    Import 和 export 只能在添加 type="module" 属性的脚本标记中使用。这个包括外部的和嵌入的。
  • ES Modules do not work with file:// protocol
Adding module code to an HTML page
<script type="module" src="./module.js"></script>
<script type="module">
// import statements
// Embedded JS Code
</script>

# Import Statements

  • Default import

    import localName from 'src/my_lib';
  • Namespace import
    imports the module as an object (with one property per named export).
    将模块作为对象导入 (每个命名的 export 有一个属性)。

    import * as localName from 'src/my_lib';
  • Named imports

    import { name1, name2 } from 'src/my_lib';
  • Renamed imports

    import { name1 as localName1, name2 } from 'src/my_lib';
    import { default as localName } from 'src/my_lib';
  • Combining imports (default must come first)
    组合导入 (默认值必须放在第一位)

    import theDefault, * as localName from 'src/my_lib';
    import theDefault, { name1, name2 } from 'src/my_lib';

# Reference

  • https://exploringjs.com/es6/ch_modules.html#sec_modules-in-browsers
  • https://www.freecodecamp.org/news/how-to-use-es6-modules-and-why-theyre-important-a9b20b480773/
  • https://www.sitepoint.com/understanding-es6-modules/
  • https://www.bignerdranch.com/blog/default-exports-or-named-exports-why-not-both/
  • https://github.com/mdn/js-examples/tree/master/modules

# DEMO

index
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ES Modules Demo</title>
    <script src="main.js" type="module"></script>
</head>
<body>
    <h1>ES Modules Demo</h1>
    <button id="btn">Click Me!</button>
    <script type="module">
        import {sum, PI} from './math_module.js';
        //import named export
        console.log('--Import Named Export--');
        console.log('Sum 1: ' + sum(1,2,3,4,5));
        console.log('PI: ' + PI);
    </script>    
    <script type="module">
        import * as mathMod from './math_module.js';
        //all exports as object
        console.log('--Import all exports as object--');
        console.log(mathMod);
        console.log('Sum 2: ' + mathMod.sum(1,2,3));
        console.log('PI2: ' + mathMod.PI);
    </script>   
    <script type="module">
        import {sum as s, Rectangle as Rect, Circle} from './math_module.js';
        //named imports with alias
        console.log('--named imports with alias--');
        let c = new Circle(5);
        console.log('Circle Area is: ' + c.area);
        let r = new Rect(8, 5);
        console.log('Rect Perimeter is: ' + r.perimeter);
        console.log('Sum 3: ' + s(1,2,3,4,5,6,7));
    </script>
    <script type="module">
        import mathMod from './math_module.js';
        //import default export
        console.log('--import default export--');
        console.log(mathMod);
        console.log('Sum 4: ' + mathMod.sum(1,2,3,4,5,6,7,8));
        let c = new mathMod.Circle(8);
        console.log('Circle Area is: ' + c.area);
    </script>  
    <script type="module">
        import o, {msg} from './main.js';
        //import default export and named export from main.js
        console.log('--import default export and named export from main.js--');
        console.log(o);
        msg();
    </script>  
</body>
</html>
main
import * as mathMod from './math_module.js';
window.addEventListener('DOMContentLoaded', function(){
    console.log('DOMContentLoaded - main.js');
    console.log(mathMod);
    document.getElementById('btn').addEventListener('click', function(){
        console.log('Button Clicked');
        let sum = mathMod.sum(1,2,3,4,5,6);
        console.log('Sum from main.js: ' + sum);
        let c = new mathMod.Circle(20);
        console.log('Circle Area from main.js: ' + c.area);
        alert(`Sum: ${sum}, Circle Circumference: ${c.circumference}`);
    });
}); //end DOM Content Ready
let obj = {name: 'Brian', email: 'bbailey4@iit.edu'};
export function msg() {
    alert('Hello ' + obj.name);
}
export default obj;
math_module
export function sum(...args) {
    return args.reduce((accumulator, currentValue) => accumulator + currentValue);
}
export class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }
    calcArea() {
        return this.width * this.height;
    }
    get area() {
        return this.calcArea();
    }
    get perimeter() {
        return (2 * this.height) + (2 * this.width);
    }
}
export class Circle {
    constructor(radius) {
        this.radius = radius;
    }
    calcArea() {
        return Math.PI * (this.radius * this.radius);
    }
    get area() {
        return this.calcArea();
    }
    get circumference() {
        return (2 * Math.PI * this.radius);
    }
}
export const PI = 3.1415;
export default {sum, Rectangle, Circle, PI};