<nav id="myaffix">
目錄
</nav>
我的經驗,前端開發上要解決的問題能簡單分為兩個階段:
- 開發階段
- 部署階段
其中開發階段要解決:
- 第三方包安裝、使用、依賴關系的維護
- 自有代碼的依賴關系維護及使用
先來聊聊開發階段的解決方案。
包管理器#
最初在 jQuery 站點上,文檔可能是這樣寫的:
- 下載 jquery.min.js 文件
- 保存到 js 目錄
- 在 HTML 文件中使用
script
標簽引用 jquery
因為 jQuery 不依賴其它庫,所以相對來說,上面的操作還算簡單。
但如果碰上有依賴關系的,比如 Bootstrap 依賴于 jQuery,我們可能就需要分開下載 Bootstrap 與 jQuery。好在這一類第三方庫通常都在下載文件中打包好依賴了。但這樣又有一個問題,如果另一個庫也同樣打包一個 jQuery,并且版本與 Bootstrap 里打包的不一致呢。可以想像,這樣的情況并不少見,我們的開發目錄最終容易失控 – 添加包很容易,刪除就難了。另外,手工來做這件事,效率太低。
包管理器的意義就在這里。它封裝了細節,自動化處理我們的需求。我們只需要提問題,它們提供答案:
- 我要使用 jQuery – 好,
bower install jquery
- 我要使用 Bootstrap – 好,
bower install bootstrap
,順便會把依賴 jQuery 一起安裝了 - 我想了想,還是刪除 Bootstrap 吧 – 好,
bower uninstall bootstrap
包管理器會維護一個依賴清單,個中關系一目了然。
當然,以上只是用 bower 舉例,市面上同類產品還非常多,比如 duojs,本文的主角 jspm 也是一個,甚至 npm 都算。
加載器#
包管理器解決了我們管理各種模塊的需求。接下來,我們要利用這些模塊來開發,那么就會碰上如何使用這些模塊的問題了。
目前 ES6 模塊的標準還沒在瀏覽器中得到完全落實,過渡期間我們有許多規范或不規范的模塊:
- CommonJS
- AMD
- ES6 Modules
- 命名空間方式定義
- 其它
如果只使用單一規范,比如針對 AMD,我們可能會用 RequireJS;ES6 的模塊,我們可能會用到 ES6 Module Loader Polyfill;CommonJS 規范的模塊,我們可能用 SystemJS – 它同樣可用于加載 AMD/ES6 模塊。
CSS 加載器??
上面提及的加載器,通常是針對 JavaScript 模塊的,CSS 并沒有嚴格意義的模塊,那它怎么管理?我們的包管理器當然會連著包的 CSS 文件一同管理。那我們該如何使用這些模塊中的 CSS 呢?舉 SystemJS 來說,我們可以通過它的插件執行 import
命令動態插入 CSS。打包的時候,SystemJS 默認會把整個 CSS 文件打包入 JS 文件中。當然,我們也可以借助 bower 與 gulp.js 及 gulp.js 的 wiredep 插件 這樣的組合實現在頁面上「主動」插入 link
標簽 – 但這需要搭配 gulp.js 等工具。
走完開發階段,我們來看看部署階段要解決的幾個明顯問題:
- CSS 文件合并、壓縮等
- JavaScript 文件合并、壓縮、混淆等
不過,還是先正式介紹 jspm 與 SystemJS 的用法。
jspm#
如前所說的,jspm 是一個瀏覽器端包管理器。
安裝 jspm
npm install jspm -g
初始化目錄
在安裝完 jspm 后,我們在命令行下就有一個 jspm
命令可用。
創建一個目錄,執行 jspm init
即可在該目錄下初始化開發環境:
Package.json file does not exist, create it? [yes]:
Would you like jspm to prefix the jspm package.json properties under jspm? [yes]:
Enter server baseURL (public folder path) [.]:
Enter jspm packages folder [./jspm_packages]:
Enter config file path [./config.js]:
Configuration file config.js doesn't exist, create it? [yes]:
Enter client baseURL (public folder URL) [/]:
Which ES6 transpiler would you like to use, Traceur or Babel? [traceur]:
如果你用過 yeoman 一類工具,對這類提示應該非常熟悉。
安裝第三方庫
比如要安裝 jQuery:
jspm install jquery
這條命令會從 github:components/jquery 上讀取下載。
還可以從 npm 上下載安裝:
jspm install npm:jquery
創建 HTML 文件
創建一個 index.html 文件如下:
<!doctype html>
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app');
</script>
首先我們需要引用 jspm_packages/system.js
,這個是 jspm 提供的萬用加載器。之后是 config.js
文件,我們安裝的各種包、依賴等信息都在這個文件中維護,之后我們用全局的 System.import
執行 index.html 同一目錄下的 app.js 文件。
在 app.js 文件中,我們使用 ES6 語法:
import $ from 'jquery';
$(function() {
console.log($);
});
假定我們要在 index.html 中使用 Bootstrap,那么先通過 jspm
安裝:
jspm install bootstrap
然后把 app.js 文件修改如下:
import bootstrap from 'bootstrap';
$(function() {
console.log($);
});
我們并沒有 import
jQuery,這是因為 jspm 維護有 bootstrap 的依賴,會自動加載 jQuery,不需要我們再手動 import
。
import bootstrap from 'bootstrap'
一行是加載了 Bootstrap 的 js 模塊。那么,Bootstrap 的 CSS 部分如何加載呢?我們需要用到 jspm 的 CSS 插件。
首先,安裝 jspm 的 css 插件:
jspm install css
然后在 app.js 中添加一行:
import 'bootstrap/css/bootstrap.css!';
! 表示這會經過插件處理。
這時如果在本地服務器上打開 index.html 文件,借助瀏覽器的開發者工具查看:
[resp_image id=’16028′ caption=” ]
Wow,請求有點多 – 但這只是開發階段。
打包 JavaScript
我們終于說到 JavaScript 的打包了。
jspm 里,js 文件的打包非常簡單,舉上面的例子說,如果我們只有一個 js 入口的話,則執行:
jspm bundle-sfx app build.js --minify
就可以將所有需要的 js 文件包括 CSS 文件打包到一個 build.js 文件中。
之后修改 index.html 文件中 script 部分如下:
<!-- <script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
System.import('app');
</script>-->
<script src="build.js"></script>
這時打開 index.html 頁面,就只剩下 index.html 與 build.js 兩個請求了。
打包 CSS
在上在一個步驟中,我們把 CSS 文件連著一起打包進了 js 中,這可能并不是多數人想要的結果。
我們可以通過定義 config.js 文件改變這種行為。
打開 config.js 文件,添加 seperateCSS: true
:
System.config({
"baseURL": "/",
"separateCSS": true
});
再次執行 jspm bundle-sfx app build.js --minify
,會在 index.html 同級目錄下生成一個 build.js 與 build.css,在 index.html 中引用 build.css 文件即可。