基于AMD(requirejs)机制,加载后现代的 javascript 近亲文件(如 coffee-script 、 react 、 ecmascript6 等),实时编译(转换)为 js,并将结果缓存在 HTML5 的 localStorage,并基于 AMD 机制进行加载。
取名 any 包含了 anytime 和 anything 的含义。
目前分为3个分支:
3个分支的源代码部分都是一样的,唯一的区别是bower.json中 main
和 dependencies
的不同。
bower install https://git.oschina.net/janpoem/require-any.git // or 你只使用es6 bower install https://git.oschina.net/janpoem/require-any.git#babel // or 你只使用coffee bower install https://git.oschina.net/janpoem/require-any.git#coffee
已经register到bower了,可以直接:
bower install require-any // or 你只使用es6 bower install require-any#babel // or 你只使用coffee bower install require-any#coffee
核心的文件 require-any.js
实现如下内容:
requirejs([any!test/Error.jsx])
。 本类库预设的实现了两个实时翻译器( XHR 加载,并将翻译结果缓存在 LocalStorage ):
下面这个是ecmascript6的例子:
import hello from "any!./hello.coffee"; console.log(hello); let fun = () => console.log('hello e2s6') class Test { } module.exports = Test;
他会转换出以下的javascript:
define(["module", "any!./hello.coffee"], function (module, _hello) { "use strict"; var _hello2 = _interopRequireDefault(_hello); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } console.log(_hello2.default); var fun = function fun() { return console.log('hello es6'); }; var Test = function Test() { _classCallCheck(this, Test); }; module.exports = Test; });
而如下面的jsx文件:
var React = require('react'); module.exports = React.createClass({ displayName: 'Test', getInitialState: function() { return { count: 0 } }, click: function(event) { this.setState({ count: this.state.count + 1 }); }, render: function () { return ( <button onClick={this.click}> Test + {this.state.count} </button> ); } });
是不是很像我们做的npm文件?这个则会转换成这样的javascript:
define(['module', 'react'], function (module, React) { 'use strict'; module.exports = React.createClass({ displayName: 'Test', getInitialState: function getInitialState() { return { count: 0 }; }, click: function click(event) { this.setState({ count: this.state.count + 1 }); }, render: function render() { return React.createElement( 'button', { onClick: this.click }, 'Test + ', this.state.count ); } }); });
基本的流程:
可以参考 js/main.js
文件
var rjsConfig = { //baseUrl: './js', isDebug: true, paths: { 'react': 'bower_components/react/react', 'react-dom': 'bower_components/react/react-dom', 'babel': 'bower_components/babel-standalone/babel', 'coffee-script': 'bower_components/coffee-script/extras/coffee-script', 'coffee-react-transform': 'src/coffee-react-transform', // 指定加载的协议,你可以指定任意名称,比如load 'any': 'src/require-any', // babel 转换器 'coffee-transform': 'src/coffee-transform', // coffee-script 转换器 'babel-transform': 'src/babel-transform' }, any: { // 指定缓存存储的空间 cacheKey: 'my-cache', // 是否编译模式,如果是编译模式,则直接加载这个模块的js文件 // any!test.jsx,当build = true,则会去加载 test.js 文件 build: false, // 是否显示调试的信息 debug: true, // 声明相关的,插件 plugins: { coffee: 'coffee-transform', es6: 'babel-transform' }, // 后缀文件名的别名,指定用哪个插件来进行处理 ext: { cjsx: 'coffee', jsx: 'es6' }, // 后缀转换(编译)时的参数,以后缀名为指向。 // 如果这里指定了jsx,则优先取jsx的配置。 // 如果没指定jsx,则会加载es6的配置。 options: { es6: { plugins: ["transform-es2015-modules-amd"] } } } }; rjsConfig.urlArgs = "version=" + (new Date()).valueOf(); requirejs.config(rjsConfig);
可以参考 index.html
requirejs(['any!test/hello.coffee', 'any!test/Table.cjsx', 'react', 'react-dom', 'any!test/Test.jsx', 'any!test/Error.jsx'], function(hello, Table, React, ReactDOM, Test, Error) { ReactDOM.render(React.createElement(Table), document.getElementById('test1')); ReactDOM.render(React.createElement(Test), document.getElementById('test2')); });
上述中,如果 config.any.build
为 true
的话,所有any前缀请求都会去掉相应的后缀文件名,即加载这个模块的js文件。如:test/hello.js。