# Node.js - Intro
###### tags: `nodejs`, `backend`
## Node.js
https://nodejs.org/en/
- allows us to run Javascript outside the browser
- Node.js is created using the **V8 engine** to read and run JS outside the browser
- popular for building servers
## Install Node.js
### Install
https://nodejs.org/en/download/
- automatically installs **NPM** for you
### Check node version
```shell
$ node -v
```
### Run node in the terminal
```shell
$ node
```
### Update latest version
- Download the latest version on the [website](https://nodejs.org/en/)
- Only update NPM:
```shell
$npm install npm@latest -g
```
Ref. https://docs.npmjs.com/try-the-latest-stable-version-of-npm
## global vs. window
- `window` object is provided by the browser
- Node uses `global` instead
- Node comes with its own properties and methods; won't have browser-specific things e.g. `document`, `fetch`)
全域變數 `var`: `window` 上的全域變數會覆寫到 `window`,`global` 則不會(只會在該 js 檔案裡)
- In browser: `window.prop`
```javascript
//script1.js
var a = 1
console.log(window.a); // 1
```
- In global: `global.prop`
```javascript
var a = 1
console.log(global.a); // undefined
global.a = 1
```
## process
One of the *global* object has is `process`
```javascript
process
```
means the process what is running now in the terminal; what the computer is doing
#### exit the process
```javascript
process.exit()
```
Exit the process and back to the terminal
## globalThis (ES2020)
```javascript
globalThis === window // true
```
- `globalThis` works outside the browser as well
- exists as both part of the window and Node, so that you can have unified variables across different platforms
- able to have unified code base
## Running script.js in Node
1. create a file
```bash
$ touch script.js
```
2. run script.js file
```bash
$ node script.js
```
- after the process is done, runs `process.exit` to end the process
- within node we can run what `global` objects we have.
e.g. Use `__dirname` to get directory
```javascirpt
// script.js
console.log(__dirname);
```
## Modules in Node
### ES6 import/export
:::warning
ES6 imports only works in *Node version **12.2.0*** or higher
:::
**Export: `export default var1`**
```javascript
//script2.js
const largeNumber = 356;
export default largerNumber;
//simplified way:
export const largeNumber = 356;
```
**Import: `import var1 from './filePath'`**
```javascript
//script.js
import largeNumber from 'script2.js'
//or import doing destructuring
import {largeNumber} from './script2.js'
const a = largeNumber;
const b = 5;
console.log(a+b); // SyntaxError: Unexpected token import
```
### CommonJS modules (in the old version of Node)
:::warning
If ran in older version which Node has not yet been introduced with the ES6 import/export feature: `SyntaxError: Unexpected token import`
:::
**Export: `module.exports = { prop1: value1 }`**
```javascript
//script2.js
const largeNumber = 356;
module.exports = largeNumber
// or export an object
module.exports = {
largerNumber: largeNumber
};
```
- `module` is a global object we have access to
**Import: `require('./filePath')`**
```javascript
//script.js
const script2 = require ('./script2.js')
const a = script2.largeNumber; // get access to the property of script2
const b = 5;
console.log(a+b); //361
```
### ES6 Modules in Node
Export: `export const variableName = value;`
```javascript
// script2.js
export const largeNumber = 356;
```
Import: `import { variableName } from './filePath'`
```javascript
//script.js
import {largeNumber} from './script2.js'
```
- `{}` - destructuring
- `'./script2'` - it's okay not to indicate file type
Run node:
```shell
$ node script.js
```
Got an error:

:::warning
Warning: To load an ES module, set **"type": "module"** in the package.json or use the .mjs extension.
:::
#### Enabling ES6 Modules in Node
Because Node is created with CommonJS import/export in mind, we needs to specify how we want Node to read the file.
Ref. https://nodejs.org/api/esm.html#enabling
> Node.js has two module systems: **CommonJS modules** and **ECMAScript modules**. Authors can tell Node.js to use the ECMAScript modules loader via the `.mjs` file extension, the package.json `"type"` field, or the `--input-type` flag.
>
> Outside of those cases, Node.js will use the CommonJS module loader.
#### Two methods to load ES module in Node:
- `.mjs` file method:
1. Rename `.js` to `.mjs` files
2. Make sure the syntax we're importing is `.mjs`
- file path:`import {largeNumber} from './script2.mjs'`
- run: `$ node script.mjs`
- `package.json` method:
1. create a `package.json` file
```shell
$ npm init -y
```
- `-y` to say yes to all the options
2. in `package.json` file, add `"type": "module"`
### Types of Modules in Node
**Built-in modules: pre-installed with Node**
- e.g. `fs` module - file system module
- e.g. `http` module - used to build a server
- these modules are without the path
**Package (e.g. NPM)**
[nodemon](https://www.npmjs.com/package/nodemon)
1. create a package.json file
```shell
$ npm init
```
2. install nodemon in dev
```shell
$ npm install nodemon --save-dev
```
- you'll see `nodemon` in `package.json`'s `devDependencies`

- `devDependencies`: dependencies we only use when we're developing; won't be included when we actually deployed the app
- Beacause it's is in the`node_modules/.bin` file, we can use the command `$ nodemon`.
3. Set scripts in package.json file:
```json
"scripts":{
"start": "nodemon script.js"
},
```
4. Run `$npm start` to start nodeman. It will constantly watch the changes and keeps running the `$ node script.js` command.

## Node Module - Path
- `__dirname` - 目錄路徑
- `__filename` - 檔名
```javascript
var path = require('path'); // 取用 path 模組
// 取得目錄路徑
console.log(**path.dirname**('xx/yy/zz.js')); // Return: **/xx/yy** --> 回傳「資料夾名稱」
// 合併路徑
// Syntax: **.join(目前路徑, 欲合併的路徑)**
console.log(**path.join**(__dirname, '/xx')); // Return: /Users/userName/Desktop/project/xx
// 取得檔名
console.log(**path.basename**('xx/yy/zz.js')); // zz.js
// 取得副檔名
console.log(**path.extname**('xx/yy/zz.js')); // .js
//分析路徑
console.log(**path.parse**('xx/yy/zz.js')) // {root:'/', dir:'/xx/yy', base:'zz.js', ext:'.js', name:'zz'}
```
當你載入 `var path = require('path');` ,便可用下述語法取得檔案與目錄路徑
- **抓目錄路徑**: `path.**dirname**('**/xx/yy**/zz.js')`:回傳 `/xx/yy`
- **路徑合併**:`path.**join**(__dirname,'/xx')` 回傳 **前後路徑合併**
- **抓檔名**: `path.**basename**('/xx/yy/**zz.js**')` - 回傳 `zz.js`
- **抓副檔名**: `path.**extname**('/xx/yy/zz.**js**')` - 回傳 `js`
- **分析路徑**: `path.**parse**('/xx/yy/zz.js')` - 回傳 上述綜合物件
Ref. [Node.js PATH API](https://nodejs.org/api/path.html)文件