jspm 是一个包管理器,使用 SystemJS 这个模块加载器进行模块的管理。SystemJS 是一个所谓 universal module loader
,基于 ES6 module loader,除了能加载 ES6 模块,还支持 CommonJS,AMD 及 globals 语法。
1. How jspm load modules
jspm 通过 registry 加载模块,它其实没有自己的仓库,目前只能加载 npm
和 github
上的模块,当然也可以自己通过它的 registry
机制「注册」一些模块之后使用。
jspm 要解决的就是浏览器端模块加载的问题,通过它前端代码可以无缝地使用 npm
和 github
上的大量模块,只需 jspm install example
,然后在代码中 import example from "example"
(ES6 语法) 就行了,SystemJS 会帮我们在浏览器加载 example
,而且是异步的。
1.1 Install jspm
1.1.1 Install jspm CLI:
1
| $ npm install jspm/jspm-cli -g
|
1.1.2 Install local jspm:
1 2
| $ cd my-project $ npm install jspm --save-dev
|
1.2 Create a project and setup
初始化一个 jspm 项目使用 jspm init
命令。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| $ 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]: ok Verified package.json at package.json Verified config file at config.js Looking up loader files... system.js system.js.map system.src.js es6-module-loader.js.map es6-module-loader.js es6-module-loader.src.js
Using loader versions: es6-module-loader@0.16.6 systemjs@0.16.11 Looking up github:jmcriffey/bower-traceur-runtime Looking up github:jmcriffey/bower-traceur Updating registry cache... ok Installed traceur-runtime as github:jmcriffey/bower-traceur-runtime@0.0.88 (0.0.88) ok Installed traceur as github:jmcriffey/bower-traceur@0.0.88 (0.0.88) ok Loader files downloaded successfully
|
这会在项目根目录下创建一个 config.js
文件,一个 package.json
和一个 jspm_packages
目录。
- config.js: 各模块的配置,比如要安装的模块,它的可引用的名称与实际位置的映射。
- package.json: 即 npm 的 package.json,jspm 的依赖都将在这个文件中。
- jspm_packages: 使用
jspm install
安装的模块都在这个目录下。jspm init
默认会安装 system.js
,es6-module-loader.js
和 bower-traceur
。
1.3 Basic usage
新建一个 test
目录,进行 jspm 的初始化:
1 2
| $ mkdir test; cd $_ $ jspm init
|
在 test
目录下,创建一个 index.html
文件:
1 2 3 4 5 6 7 8 9 10 11 12
| <!DOCTYPE html> <html> <head> <script src="jspm_packages/system.js"></script> <script src="config.js"></script> <script> System.import('./app'); </script> </head> <body> </body> </html>
|
以及一个 app.js
:
1
| console.log('Hello from future.')
|
现在执行 python -m SimpleHTTPServer
,打开 http://localhost:8000,可以看到浏览器加载了 app.js
。
安装一些依赖模块试试:
1 2 3 4 5 6 7
| $ jspm install jquery Updating registry cache... Looking up github:components/jquery ok Installed jquery as github:components/jquery@^2.1.4 (2.1.4) ok Install tree has no forks. ok Install complete.
|
因为 jquery 已经在 jspm 的 registry 中注册了,可以直接这么安装;对于未注册的包,需要这样:jspm install npm:some-other-lib
,详细可参考 jspm geting started。
编辑 app.js
:
1 2 3
| import $ from 'jquery'; console.log($.fn.jquery);
|
刷新浏览器,页面将会加载 jquery
,同时还有 traceur
。
2. Write the todomvc
我们这个 todomvc 基于 todomvc-jquery 编写,所以我们不准备花太多时间讲 todomvc 本身的实现,主要讲一些 ES6 的用法,及如何使用 jspm/SystemJS 管理依赖模块。
2.1 Setup
1 2
| $ mkdir todomvc-jquery-es6; cd $_ $ jspm init
|
2.2 Create the App
2.2.1 View
我们直接使用 todomvc-jquery 的 index.html
文件。因为它使用了 todomvc-common 和 todomvc-common-css 的 css,所以需要安装它们,安装的步骤很简单:
1
| $ jspm install npm:todomvc-common npm:todomvc-app-css
|
之后在 index.html
中引入这两个 css:
1 2 3 4 5 6 7
| ... <head> ... <link rel="stylesheet" href="jspm_packages/npm/todomvc-common@1.0.2/base.css"> <link rel="stylesheet" href="jspm_packages/npm/todomvc-app-css@2.0.1/index.css"> </head> ...
|
2.2.2 Model and Controller
在项目的根目录下,创建一个 js
目录,在此目录下新建三个文件:
- app.js: 这是我们这个 todomvc 的入口文件,在 HTML 中引入它即可;
- todo-app.js: 这里定义了 App;
- util.js: 一些 helper 函数。
todomvc-jquery 使用 handlebars 做模版引擎,使用 director 做客户端路由,所以我们需要安装它们,同时也别忘了安装 jquery:
1
| $ jspm install jquery handlebars npm:director
|
todo-app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import $ from 'jquery'; import Handlebars from 'handlebars'; import director from 'director'; import * as util from './util'; const ENTER_KEY = 13; const ESCAPE_KEY = 27; export default class App { constructor() { this.todos = util.store('todos-jquery'); this.cacheElements(); this.bindEvents(); director.Router({ '/:filter': (filter) => { this.filter = filter; this.render(); } }).init('/all'); } ... };
|
todo-app.js
后面的内容我们就省略了,它其实就 export
了一个 App
class,注意文件开头我们使用了 ES6 的模块引入语法。
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13
| import $ from 'jquery'; import Handlebars from 'handlebars'; import App from './todo-app'; $(()=> { Handlebars.registerHelper('eq', function(a, b, options) { return a === b ? options.fn(this) : options.inverse(this); }); new App(); });
|
2.3 Wrap it up
如前所述,我们直接在index.html
里 import
app.js 就行了:
1 2 3 4 5 6
| ... <script src="jspm_packages/system.js"></script> <script src="config.js"></script> <script> System.import('js/app'); </script>
|
2.4 Bundle for production
jspm 也提供了 bundle 的功能,只需要执行:
就可以把所有的依赖打包到 bundle.js
文件中,在 index.html
中引入它就行了:
1 2
| ... <script src="bundle.js"></script>
|
点击查看完整代码,可以在这里看 Demo。
3. Reference