# JavaScript ES6 Modules ### Question How can you share code between files? ### Answer .... (略) **ES2015 defines a module syntax which aims to replace both AMD and CommonJS.** This will eventually be supported in both browser and Node environments :arrow_right: [Modular Programming (AMD v.s CommonJS v.s ES6) ](https://hackmd.io/iU7tBt_RTzqINZWojIWh4g?view) <img src="https://i.imgur.com/fSTr1At.png" width="600px"> <br > ### 使用 Module 的好處 <img src="https://i.imgur.com/za1Bzuu.png" width="300px"> <img src="https://i.imgur.com/0vOEI49.png" width="300px"> - **Compose software** Modules are small building blocks that we put together to build complex applications; - **Isolate components** Modules can be developed in isolation without thinking about the entire codebase; - **Abstract code** Implement low-level code in modules and import these abstractions into other modules; - **Organized code** Modules naturally lead to a more organized codebase; - **Reuse code** Modules allow us to easily reuse the same code, even across multiple projects. <br > ### JS ES6 Modules `import`, `export` 瀏覽器相容性 (2021) <img src="https://i.imgur.com/WpbOYjb.png" width="700px"> IE 已淘汰,可以開始擁抱 ES6 Module 了! <br > *** ## ES6 Modules Overview ### Modern JavaScript Development ![](https://i.imgur.com/Yvd9YL8.png) ### ES6 Modules 與 傳統 Script 比較 | | ES6 Modules | Script | | -------- | -------- | -------- | | Top-level variables| Scoped to module| Global| |Default mode|Strict mode|X| |Top-level **`this`**|`undefined`|window| |HTML linking|`<script type="module">`|`<script>`| |File downloading|Asynchronous|Synchronous| <br> ### ES6 Modules 實際上是如何運作的? ![](https://i.imgur.com/9F847Iv.png) ### 如何使用: `import`, `export`, `type="module"` ![](https://i.imgur.com/f3a2oxP.png) `index.html` ```htmlembedded <script defer type="module" src="script.js"> ``` `script.js` ```javascript import "./shoppingCart.js" console.log("Importing Module") ``` `shoppingCart.js` ```javascript console.log("Exporting Module") ``` <br > in the console ``` Exporting Module Importing Module ``` 由 console 結果可知,是先執行被 import 的 module(ex: `shoppingCart.js` ),再執行 import 這個 module 的檔案(ex: `script.js` ) <br> #### 補充:script 載入方式:`defer`, `async` ![](https://i.imgur.com/wVedIeA.png) *** ## export 的方法與 syntax - Name export - Default export ### Name export / import `shoppingCart.js` ```javascript= const cart = []; export const addToCart = function(product, quantity){ cart.push({product,quatity}); console.log(`${quantity} ${product} added to cart`); }; const totalPrice = 237; const totalQuantity = 23; export {totalPrice, totalQuantity as quantity}; ``` `script.js` ```javascript= import { addToCart, totalPrice as price, quantity } from "./shoppingCart.js"; addToCart('bread', 5); console.log(price, totalQuantity); ``` or `script.js` ```javascript= import * as ShoppingCart from "./shoppingCart.js"; ShoppingCart.addToCart('bread', 5); console.log(ShoppingCart.totalPrice, ShoppingCart.totalQuantity); ``` `* as ___` creates an object containing all modules from specified file <br> ### Default export / import > 當我們在一個 module 只想要 export 一個項目( variable 或 function ) `shoppingCart.js` ```javascript= const cart = []; const totalPrice = 237; const totalQuantity = 23; export default function(product, quantity){ cart.push({product,quatity}); console.log(`${quantity} ${product} added to cart`); }; ``` `script.js` ```javascript= import add from "./shoppingCart.js"; add('bread', 5); ``` 對於 default export 的 import,我們可以任意命名 :::warning Best Practice: 對於同一個 module,不應該混用 name export 和 default export ::: <br > #### Concept: “Live connection” between import & export (not a copy!) `shoppingCart.js` ```javascript= export const cart = []; export function addToCart(product, quantity){ cart.push({product,quatity}); console.log(`${quantity} ${product} added to cart`); }; ``` `script.js` ```javascript= import { addToCart, cart } from "./shoppingCart.js"; addToCart('pizza', 2); addToCart('bread', 5); addToCart('apple', 4); console.log(cart); // (3)[{...},{...},{...}] ``` 由 console 的結果可知,import/export 為 live connection 而非 copy 被import 的 variable 的值 (如果是 copy 的話,此處應該會 log 出 `shoppingCart.js` 第一行的空陣列) *** ## Webpack 與 Babel ### 兩者角色區別 <img src="https://i.imgur.com/gU5Lzkv.png" width=" 500px"> *** ### Babel 在整個 ES6 Module 中扮演的角色 <img src="https://i.imgur.com/F7m8coU.png" width=" 600px"> #### What is Babel > 官方解釋: > Babel is a toolchain that is mainly used to **convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.** [ES6 新增了什麼 ](https://hackmd.io/6Lruihd-Qmeu9iHoipwuvQ#%E8%A3%9C%E5%85%85%EF%BC%9A-JavaScript-ES6-%E6%96%B0%E5%A2%9E%E4%BA%86%E4%BB%80%E9%BA%BC) #### Transpile 轉譯 例如 將 `let`, `const` 轉成`var`, 將 arrow function 轉成一般 function <img src="https://i.imgur.com/Vc3dEzJ.png" width=" 300px"> :arrow_down: **Babel** <img src="https://i.imgur.com/jfv1faA.png" width=" 350px"> #### Polyfill > ES6+ 的語言特性不僅包括語法結構,還包括新的 built-in function 或是像 `Promise` 這樣的 object。 因此需要 Polyfill 去更新/添加新函数的 Script,“填補” 缺口。 *** ### Webpack <img src="https://i.imgur.com/9E0YWS6.png" width=" 500px"> ### Webpack 幫我們處理了什麼? #### Bundle 打包 > 減少 browser request JS script 的次數,改善效能與使用者體驗 <img src="https://i.imgur.com/bUmJ939.png" width="400px"> :arrow_down: <img src="https://i.imgur.com/VphN5SZ.png" width="400px"> #### Dependencies > 協調檔案彼此 dependency 的關係 <img src="https://i.imgur.com/0vOEI49.png" width="400px"> <img src="https://i.imgur.com/6FYrInA.png" width="200px"> ### Webpack 怎麼做的 <img src="https://i.imgur.com/egyhHwl.png" width=" 400px"> <img src="https://i.imgur.com/qqvGeED.png" width=" 200px"> Webpack Config ~~(此為原理示意,非目前 Webpack5 可行的配置設定方式)~~ <br > #### `npm run build` 的結果 <br > <img src="https://i.imgur.com/a3ReIt2.png" width=" 150px"> <img src="https://i.imgur.com/sIgGweI.png" width=" 450px"> 產生一個 bundle file (ex: `bundle.js` ) ~~此為示意結果,與目前 Webpack5 結果不同)~~ <img src="https://i.imgur.com/ykjWPN3.png" width=" 500px"> entry 的 html 檔加載的 script 會被配置成 bundle file 的名稱 ~~(此為示意結果,與目前 Webpack5 結果不同)~~ <br > ### Webpack 怎麼產生一個 bundle file 處理 dependency 的問題 <img src="https://i.imgur.com/GUiIqG4.png" width="400px"> webpack 協調檔案後做出的 `bundle.js` 的 **pseudo code** ## 參考資料 - Udemy - The Complete JavaScript Course 2021: From Zero to Expert! ( Jonas Schmedtmann) Section 17 - Udemy - Webpack 2: The Complete Developer's Guide ( Stephen Grider) Section 2, 3