# JS 的奇幻旅程 <br> ## 套件管理工具、Module Bundler [TOC] ---- Made by FanRende (030Mortal#5525) <img src="https://i.imgur.com/jbmRCOw.png" width="25%"> --- ## 套件是什麼? > 不要重複造輪子 使用別人公開的程式碼作為開發的一部分 ---- ### 套件管理工具 Javascript 廣為使用的有兩個工具 `npm`、`yarn` 在這邊我會使用 `npm` 來做範例 <span class="gray">(因為我沒用過 `yarn`)</span> ---- ### Node Package Manager <div class="flex-container"> <div class="flex-content"> ```json // package.json { "name": "my-vite-app", "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "tsc && vite build", "preview": "vite preview" }, "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@vitejs/plugin-react": "^3.0.0", "typescript": "^4.9.3", "vite": "^4.0.0" } } ``` </div> <div class="flex-content"> ```json // package.lock.json { "name": "my-vite-app", "version": "0.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "my-vite-app", "version": "0.0.0", "dependencies": { "@types/node": "^18.11.18", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@types/react": "^18.0.26", "@types/react-dom": "^18.0.9", "@vitejs/plugin-react": "^3.0.0", "typescript": "^4.9.3", "vite": "^4.0.0" } }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/...", "integrity": "sha512-...", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" } } }, "dependencies": { "@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/...", "integrity": "sha512-...", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" } }, "@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/...", "integrity": "sha512-...", "dev": true, "requires": { "@babel/highlight": "^7.18.6" } } } } ``` </div> </div> ---- #### npm 指令 - `npm install` - 安裝該目錄下 package.json / package.lock.json 中的套件 - `npm install <package>` - 安裝指定套件 - `npm run <script>` - 執行 package.json 中的 script ---- ### Node Package Executor 如果想要執行一個 package 可以使用 `npx` 可以不需要在全域安裝該 package e.g. `npx create-react-app my-app` --- ## Module Bundler 將前端開發工程化 可以將各個部件模組化後利用 webpack 等工具整合 ---- ### webpack - Entry (`./src/index.js`) - Output (`/dist/main.js`) - Loaders - 除了 html, js, css 外的檔案需要用 loader - sass: sass-loader - Plugins - Mode - production - development - Browser Compatibility ---- #### Tree shaking 把模組相依樹搖一搖 看哪些模組沒用到就搖下來 為了實現這個功能需要靜態分析程式碼 ---- #### Dynamic import 載入使用者當前頁面需要的檔案就好 #### Dead Code elimination ```javascript if (false) { console.log("out") } ``` #### Code Splitting 可以將第三方程式碼利用 cdn 進行快取 #### Minify 變數命名、code style minify ---- #### Hot Module Replacement 另外啟動一個 server 監聽檔案變化 ```mermaid graph TD; class init initial; classDef red stroke:#f66,stroke-width:4px; index((index)) ma((moduleA)) mb((moduleB)) mc((moduleC)) md((moduleD)) me((moduleE)) class mc red; class me red; index ---> ma; index ---> mb; ma ---> mc; ma ---> md; mb ---> me; ``` ---- ### Vite 法語中的**快** ,是念 Vite 不是 Vite(?) 由於它不會在 build 時編譯所有檔案 而是需要時才 load 進來 因此速度相較 webpack 快非常多 而他的 HSM 利用了 webSocket/Chokidar/esbuild 技術也會讓他的即時熱更新比 webpack 快 ---- #### React with Vite - CRA - `npx create-react-app my-app` - Vite - `npm create vite@latest` - `npm create vite@latest my-app --template react` - `npm create vite@latest my-app -- --template react` --- ## Babel 將 Javascript 先轉換成抽象語法樹,再用各種 plugin 來轉換對應的程式碼 ---- ### Abstract Syntax Tree 抽象語法樹 <div class="flex-container"> <div class="flex-content"> ```json { "type": "Program", "start": 0, "end": 40, "body": [ { "type": "ExpressionStatement", "start": 0, "end": 27, "expression": { "type": "CallExpression", "start": 0, "end": 26, "callee": { "type": "MemberExpression", "start": 0, "end": 11, "object": { "type": "Identifier", "start": 0, "end": 7, "name": "console" }, "property": { "type": "Identifier", "start": 8, "end": 11, "name": "log" }, "computed": false }, "arguments": [ { "type": "Literal", "start": 12, "end": 25, "value": "hello world", "raw": "'hello world'" } ] } } } ``` </div> <div class="flex-content"> `console.log('hello world')` `console` -> CallExpression `log` -> MemberExpression `hello world` -> Literal </div> </div> ---- ### jsx <div class="flex-container"> <div class="flex-content"> ```javascript function MyComponent() { return React.createElement("div", null, React.createElement("span", null, "hello world" )); } // 等價於 function MyComponent() { return <div> <span>hello world</span> </div> } ``` </div> <div class="flex-content"> 透過 babel plugin 將 jsx 與 React.createElement 相互轉換 </div> </div> --- 參考 / 延伸閱讀: [為什麼前端需要工程化? — webpack](https://f2e.kalan.dev/frontend-engineering/8.html) [Babel 簡介](https://f2e.kalan.dev/frontend-engineering/9.html) [前端技能樹的十萬個為什麼](https://ithelp.ithome.com.tw/users/20141641/ironman/5767) <!-- <span style="margin-left: 50vw"></span> --> <style> .gray { color: gray; font-size: 0.5em; } .json { font-size: 0.5em !important; line-height: 1.5em !important; } .mermaid { background-color: #fcf8eb !important; } .flex-container { display: flex; justify-content: center; } .flex-content { flex-grow: 1; } </style> <style> /* Customize website's scrollbar like Mac OS Not supports in Firefox and IE */ /* total width */ body::-webkit-scrollbar { background-color: #fff; width: 16px; } /* background of the scrollbar except button or resizer */ body::-webkit-scrollbar-track { background-color: #fff; } /* scrollbar itself */ body::-webkit-scrollbar-thumb { background-color: #babac0; border-radius: 16px; border: 4px solid #fff; } /* set button(top and bottom of the scrollbar) */ body::-webkit-scrollbar-button { display:none; } </style>
{"metaMigratedAt":"2023-06-17T19:04:58.450Z","metaMigratedFrom":"YAML","title":"JS 的奇幻旅程 套件管理工具、Module Bundler","breaks":true,"description":"簡介套件管理工具及 Module Bundler","slideOptions":"{\"theme\":\"solarized\",\"transition\":\"fade\",\"previewLinks\":true}","contributors":"[{\"id\":\"82f6b599-31b8-4112-9dc5-7d7b7d6a3ebb\",\"add\":10447,\"del\":3388}]"}
    486 views
   Owned this note