# 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: ![ES6 Modules in Node](https://hackmd.io/_uploads/S1LgO2AOn.png) :::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` ![](https://i.imgur.com/PdI1La8.png) - `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. ![](https://i.imgur.com/2lp87Ed.png) ## 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)文件