iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 14
2
Modern Web

平時沒注意的 JavaScript - JS 生態系及週邊工具整理系列 第 15

前端也需要編譯?Transpile、Compile、Minify、Uglify 基本介紹

在 Day10 的時候,我有預告之後會介紹的幾個主題,包含了 npm、Webpack、Babel

現在我們有了 JavaScript 基本模組化的概念後

終於可以來打魔王,也就是介紹「Webpack」了!

什麼是 Webpack

我們花了許多篇幅介紹「前端模組化」

基本概念就是,我們想自幹一套 JavaScript 原生缺乏的模組系統

我們看了許多民間自幹的模組化套件,像是

  1. 最早的 Yui,完全自創的模組化語法
  2. 從 Node.js 而來的 CommonJS 規範,以及各種支援 CommonJS 的模組化套件
  3. 分叉出來的 AMD 規範,支援他的 RequireJS

我們前幾天講述歷史的時候,有提到 AMD 規範比較沒落了

所以後來前端模組化,我們幾乎都是使用 CommonJS 的規範

知識補充

在我們介紹有哪些前端模組化方案可以使用前

這邊會先介紹一些實際「使用前端模組化」會是什麼樣子

比較能幫助我們了解為什麼接下來介紹的工具,會有這些功能

1. 在前端實作模組化,是需要把 code 做 transpile(轉譯) 的

這邊有人會叫他 compile(編譯) 或是 transpile(轉譯)
(我知道編譯有特別定義,不過如果在前端的討論範圍不會有太大影響)

因為原生 JavaScript 不支援 像是 require, export 這些 CommonJS 定義的物件

所以我們寫完一份模組化的 code

實際上,丟到瀏覽器,他是執行不起來的

這邊現在主流的做法,是使用一些 task runner (建置工具)

這些 task runner 有點像是 livereload 這樣的開發工具

他會在你每次儲存後,都把你剛剛寫的 code 都轉成瀏覽器版本的 JavaScript

舉例

像是我們待會會介紹到的 Webpack,他也有提供轉譯的功能

原本我們開發上寫了一個 module

// app.js
document.write('<h1>Hello World</h1>');

他編譯出來的結果大概會長這樣(簡略版)

/******/ (function(modules) {
             // 實際把這些模組抓進來執行
/******/     // The module cache
	/******/ 	var installedModules = {};

	/******/ 	// The require function
	/******/ 	function __webpack_require__(moduleId) {

	/******/ 		// Check if module is in cache
	/******/ 		if(installedModules[moduleId])
	/******/ 			return installedModules[moduleId].exports;

	/******/ 		// Create a new module (and put it into the cache)
	/******/ 		var module = installedModules[moduleId] = {
	/******/ 			exports: {},
	/******/ 			id: moduleId,
	/******/ 			loaded: false
	/******/ 		};

	/******/ 		// Return the exports of the module
	/******/ 		return module.exports;
	/******/ 	}
	/******/ })
 /******/ ([
	            // 一個一個模組
	/***/       function(module, exports) {
		          document.write('<h1>Hello World</h1>');
	/***/       }
	/******/ ]);

第一次看可能很嚇人

不過你會發現,基本上他還是沒有超出我們的知識範圍

這段 code 的功用很簡單

他寫了一個 IIFE (立即執行的 function)

並且把你寫的所有模組都當作參數,丟進這個執行器裡面去跑

全程都包在 IIFE 裡面,沒有全域變數

2. 通常不只有模組需要編譯,你還會編譯語法

像是常用的框架 Vue, React, Angular

都會發展出自己特別的語法

(像是 Vue 有 .vue、React 有 .jsx)

這些語法跟 Module 一樣,原生瀏覽器是不認得的

所以我們也會得把他做一次編譯

3. 根據特定規則的轉譯

最後,寫完 code 時,我們還會根據自己需求而做 minify 或是 uglify

什麼是 minify, uglify

如果你有打開網頁看原始碼的習慣

像是 Facebook,你可能會發現你看到的原始碼很髒很亂

變數全部都是 a, b c ,並且都寫在同一行

不,這不是因為在 Facebook 工作寫的 code 就這麼髒

這是使用特定的工具像是 https://javascript-minifier.com/ 轉譯出來的


(Vue 的 minify 版本)

要這樣做的原因有兩個

  1. 把變數跟 code 寫的越短,可以省掉不少瀏覽器 Parse(解析) 的時間 (這就是 minify)
  2. 雖然這些 code 是公開的,但是如果有人想研究你的前端秘密的話,至少會比較不方便 (這是 uglify)

minify 通常只會把它轉成越短越好

而 uglify(混淆器),通常還會把其他邏輯打散

明天

今天我們簡單介紹了我們在前端使用 task runner 會做的事情

通常 task runner 很簡單

我們會指定一系列我們寫完的 code 該怎麼被轉譯

像是今天我使用 JSX 以及模組化的 style 來寫了一個網站

我的 task runner 設定就會長得像

  1. 第一步,把 JSX 轉成JS
  2. 第二步,把模組化的語法轉成瀏覽器看得懂的 IIFE
  3. 第三步,把這些 IIFE ,再作進一步的 minify

希望這樣可以幫助了解前端為何會發展出 task runner 這樣的機制

明天會介紹常用的 task runner,再會!


上一篇
package-lock.json 有什麼用,淺談 Yarn, NPM5 與 npm shrinkwrap
下一篇
Vue-Cli 所創建的 package.json + Webpack 設定大解析
系列文
平時沒注意的 JavaScript - JS 生態系及週邊工具整理33

尚未有邦友留言

立即登入留言