<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 文件即可。