<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 實戰 ## venus-in-cmd Venus是一個javascript類庫,是一個canvas的wrapper,為了學習spm,我們使用cmd的模式來重構這個類庫。 ### 安裝spm-init spm提供了初始cmd模塊的腳手架,我們可以使用下面的命令來安裝這個腳手架: ~~~ $ spm plugin install init ~~~ ### 初始化一個cmd項目 運行: ~~~ $ spm init ~~~ 就可以初始化一個cmd模塊的項目,回答一些spm的問題,就能在當前目錄生成必要的文件和文件夾: ~~~ |~examples/ | `-index.md |~src/ | `-venus.js |~tests/ | `-venus-spec.js |-LICENSE |-Makefile |-package.json `-README.md ~~~ 我們在`src`中添加`venus`的代碼。 ### 編寫cmd模塊 或者將現有的模塊轉化為cmd模塊。 本例中的[Venus](https://github.com/island205/Venus)本來就已經存在,那我們如何將其轉成cmd模塊呢? 在Venus的源碼中我驚喜地發現這段代碼: ~~~ // File: vango.js /* * wrapper for browser,nodejs or AMD loader evn */ (function(root, factory) { if (typeof exports === "object") { // Node module.exports = factory(); // AMD loader } else if (typeof define === "function" && define.amd) { define(factory); } else { // Browser root.Vango = factory(); } })(this, function() { // Factory for build Vango }) ~~~ 這段代碼可以令`vango.js`支持瀏覽器(通過script直接引入)、node環境以及AMD加載器。 于是事情就簡單了,因為我們可以很簡單地將一個Node模塊轉成CMD模塊,添加如下的wrapper即可: ~~~ // File: vango.js define(function (require, exports, module) { (function(root, factory) { if (typeof exports === "object") { // Node module.exports = factory(); // AMD loader } else if (typeof define === "function" && define.amd) { define(factory); } else { // Browser root.Vango = factory(); } })(this, function() { // Factory for build Vango // return Vango }) }) ~~~ #### UMD 上面那段有點黑魔法的代碼還有一個更復雜的形式,即[Universal Module Definition](https://github.com/umdjs/umd): ~~~ (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define('backbone', ['jquery', 'underscore'], function (jQuery, _) { return factory(jQuery, _); }); } else if (typeof exports === 'object') { // Node.js module.exports = factory(require('jquery'), require('underscore')); } else { // Browser globals root.Backbone = factory(root.jQuery, root._); } }(this, function (jQuery, _) { var Backbone = {}; // Backbone code that depends on jQuery and _ return Backbone; })); ~~~ 當然并不是所有的CMD模塊都得這么寫,你可以按照自己的方式,使用`require`、`exports`和`module`這三個關鍵字,遵循CMD的規范即可。 最后`src`有兩個文件,`venus.js`就很簡單了: ~~~ define(function (require, exports, module) { var Vango = require('./vango'); exports.Vango = Vango; }) ~~~ 我們的venus的cmd版本搞定了,vango.js作為vango具體實現,而venus.js只是這些將這些畫家暴露出來。 ### 構建 作為標準的cmd模塊,我們可以使用`spm-build`來構建,別忘了之前提到的,你可以使用`spm plugin install build`來安裝。 在項目的根目錄下運行`spm build`: ~~~ $ spm build Task: "clean:build" (clean) task Task: "spm-install" task Task: "transport:src" (transport) task transport: 2 files Task: "concat:css" (concat) task concated: 0 files Task: "transport:css" (transport) task transport: 0 files Task: "concat:js" (concat) task concated: 2 files Task: "copy:build" (copy) task Task: "cssmin:css" (cssmin) task Task: "uglify:js" (uglify) task file: ".build/dist/venus.js" created. Task: "clean:dist" (clean) task Task: "copy:dist" (copy) task copied: 2 files Task: "clean:build" (clean) task cleaning: ".build"... Task: "spm-newline" task create: dist/venus-debug.js create: dist/venus.js Done: without errors. ~~~ 從構建的log中可以看出,`spm`完全就是使用grunt來構建的,涉及到多個grunt task。你完全可以自己編寫Gruntfile.js來實現自定義的構建過程。 venus就被構建好了,`spm`在目錄中生成了一個`dist`文件夾: ~~~ |~dist/ |-venus-debug.js `-venus.js ~~~ `venus-debug.js`中的內容為: ~~~ define("island205/venus/1.0.0/venus-debug", [ "./vango-debug" ], function(require, exports, module) { var Vango = require("./vango-debug"); exports.Vango = Vango; }); define("island205/venus/1.0.0/vango-debug", [], function(require, exports, module) { // Vango's code }) ~~~ `venus.js`的內容與之一樣,只是經過了壓縮,去掉了模塊名最后的`-debug`。 `spm`將`src`中的vango.js和venus.js根據依賴打到了一起。作為包的主模塊,venus.js被放到了最前面。 > 這是Sea.js的默認約定,打包后的模塊文件其中的一個define即為該包的主模塊(ID 和路徑相匹配的那一個),也就是說,你通過`require('island205/venus/1.0.0/venus')`,雖然Sea.js加載的是整個打包的模塊,但是會把的一個factory的exports作為venus暴露的接口。 ### 發布 如果你用過npm,那你對spm的發布功能應該不會陌生了。spm也像npm一樣,有一個公共倉庫,我們可以通過`spm plublish`將venus發布到倉庫中,與大家共享。 ~~~ $ spm publish publish: island205/venus@1.0.0 found: readme in markdown. tarfile: venus-1.0.0.tar.gz execute: git rev-parse HEAD yuan: Authorization required. yuan: `spm login` first ~~~ 如果你碰到上面這種情況,你需要登錄下。 ~~~ $ spm publish publish: island205/venus@1.0.0 found: readme in markdown. tarfile: venus-1.0.0.tar.gz execute: git rev-parse HEAD published: island205/venus@1.0.0 ~~~ 接下來我們使用venus編寫一個名為pixelegos的網頁程序,你可以使用這個程序來生成一些頭像的位圖。例如,spmjs的頭像(這是github為spmjs生成的隨機頭像): ![spmjs](https://identicons.github.com/1e5ac2bf13d0dc1b93e8d663f2fdf885.png) ## pixelegos pixelegos完成后的樣子: ![pixelegos](http://pic.yupoo.com/island205/D7v3BdKT/Aiuue.jpg) ### 準備 創建一個名為`pixelegos`的文件夾,初始化一個npm項目: ~~~ $ mkdir pixelegos && cd pixelegos && npm init ~~~ 在目錄中多了一個packege.json文件,在這個文件中包含了一些pixelegos的信息,之后還會保存一些node module和spm的配置。 ### 安裝依賴 本項目中需要依賴的cmd模塊包括`backbone`、`seajs`、`venus`、`zepto`。我們運行下面的命令安裝這些依賴: ~~~ $ spm install seajs/seajs gallery/backbone zepto/zepto island205/venus ~~~ 在`pixelegos`目錄下增加了一個`sea-modules`目錄,上面的cmd依賴都安裝在這個目錄中,由于backone依賴于underscore,spm自動安裝了依賴。 ~~~ ├── gallery │ ├── backbone │ │ └── 1.0.0 │ │ ├── backbone-debug.js │ │ ├── backbone.js │ │ └── package.json │ └── underscore │ └── 1.4.4 │ ├── package.json │ ├── underscore-debug.js │ └── underscore.js ├── island205 │ └── venus │ └── 1.0.0 │ ├── package.json │ ├── venus-debug.js │ └── venus.js ├── seajs │ └── seajs │ └── 2.1.1 │ ├── package.json │ ├── sea-debug.js │ ├── sea.js │ └── sea.js.map └── zepto └── zepto └── 1.0.0 ├── package.json ├── zepto-debug.js └── zepto.js ~~~ ### 開始 新建一些html、css、js文件,結構如下: ~~~ ├── index.css ├── index.html ├── js │ ├── canvas.js │ ├── config.js │ ├── menu.js │ ├── pixelegos.js │ └── tool.js ├── package.json └── sea-modules ├── gallery ├── island205 ├── seajs └── zepto ~~~ 給index.html添加如下內容: ~~~ <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' /> <meta name="viewport" content="width=device-width" /> <link rel="stylesheet" href="/index.css" /> <script type="text/javascript" src="/sea-modules/seajs/seajs/2.1.1/sea-debug.js"></script> <script type="text/javascript" src="/config.js"></script> <script type="text/javascript"> seajs.use('/js/pixelegos') </script> </head> <body> </body> </html> ~~~ 其中,config.js在開發時用來配置alias,pixelegos作為整個程序的啟動模塊。 ~~~ // config.js seajs.config({ alias: { '$': 'zepto/zepto/1.0.0/zepto', "backbone": "gallery/backbone/1.0.0/backbone", "venus": "island205/venus/1.0.0/venus" } }) ~~~ ~~~ // pixelegos.js define(function (require, exports, module) { var Menu = require('./menu') var Tool = require('./tool') var Canvas = require('./canvas') var $ = require('$') $(function() { var menu = new Menu() var tool = new Tool() var canvas = new Canvas() tool.on('select', function(color) { canvas.color = color }) tool.on('erase', function() { canvas.color = 'white' }) }) }) ~~~ 在其他js文件中分別基于backbone實現一些pixelegos的組件。例如: ~~~ // menu.js define(function (require, exports, module) { var Backbone = require('backbone') var $ = require('$') var Menu = Backbone.View.extend({ el: $('header'), show: false, events: { 'click .menu-trigger': 'toogle' }, initialize: function() { this.menu = this.$el.next() this.render() }, toogle: function(e) { e.preventDefault() this.show = ! this.show this.render() }, render: function() { if (this.show) { this.menu.css('height', 172) } else { this.menu.css('height', 0) } } }) module.exports = Menu }) ~~~ menu.js依賴于backbone和(在config.js將zeptoalias為了),實現了頂部的菜單。 ### 當當當當 當當當當,巴拉巴拉,我們敲敲打打完成了pixelegos得功能,我們已經可以畫出那只Octocat了! ### 構建發布 終于來到了我們的重點,關于cmd模塊的構建。 > 有童靴覺得spm提供出來的構建工具很難用,搞不懂。我用下來確實些奇怪的地方,等我慢慢到來吧。 spm為自定義構建提供了兩個工具: * grunt-cmd-transport:將cmd模塊轉換成具名模塊,即將`define(function (require, exports, module) {})`轉換為`define(id, deps, function(require, exports, module) {})`,可基于package.json中的spm配置來替換被alias掉的路徑等等。本身還可以將css或者html文件轉換為cmd包。 * grunt-cmd-concat:根據依賴樹,將多個具名的cmd模塊打包到一起。 接下來就是用這些工具將我們零散的js打包成一個名為pixelegos.js的文件。 #### grunt grunt是目前JavaScript最炙手可熱的構建工具,我們先來安裝下: ~~~ " 在全部安裝grunt的命令行接口 $ npm install grunt-cli -g " 安裝需要用的grunt task $ npm install grunt grunt-cmd-concat grunt-cmd-transport grunt-contrib-concat grunt-contrib-jshint grunt-contrib-uglify --dev-save ~~~ 整個打包的流程為: 1. 將業務代碼transport成cmd的具名模塊 2. concat所有的文件到一個文件pixelegos.js 3. uglify #### 編寫Gruntfile.js文件 第一步先把js文件夾中的業務js轉換成具名模塊: ~~~ transport : { options: { idleading: '/dist/', alias: '<%= pkg.spm.alias %>', debug: false }, app:{ files:[{ cwd: 'js/', src: '**/*', dest: '.build' }] } } ~~~ 這是一些transport的配置,即將js/中的js transport到.build中間文件夾中。 接下來,將.build中的文件合并到一起(包含sea-modules中的依賴項。): ~~~ concat : { options : { include : 'all' }, app: { files: [ { expand: true, cwd: '.build/', src: ['pixelegos.js'], dest: 'dist/', ext: '.js' } ] } } ~~~ 這里我們只對pixelegos.js進行concat,因為它是app的入口文件,將`include`配置成`all`,只需要concat這個文件,就能將所有的依賴項打包到一起。`include`還可以配置成其他值: * self,相當于不做concat,只是copy該文件 * relative,只concat通過想對路徑依賴的模塊 既然我們已經transport和concat好了文件,那我們直接使用整個文件就行了,于是我們的發布頁面可寫成: ~~~ <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' /> <meta name="viewport" content="width=device-width" /> <link rel="stylesheet" href="/index.css" /> <script type="text/javascript" src="/sea-modules/seajs/seajs/2.1.1/sea.js"></script> <script type="text/javascript"> seajs.use('/dist/pixelegos') </script> </head> <body> ... </body> </html> ~~~ 當我運行index-product.html時我遇到了坑。在backbone包中并沒有指明依賴的具體包,導致打包后的js無法找到.js文件。原本以為backbone中的$會被業務級的配置所替換,但是事實并非如此。如何解決? 我們必須使用seajs.config接口提供一個dom的engine,在js/中創建engine.js文件: ~~~ // engine.js seajs.config({ alias: { '$': 'zepto/zepto/1.0.0/zepto' } }) ~~~ 接下來把這個文件和pixelegos.js concat在一起: ~~~ normalconcat: { app: { src: ['js/engine.js', 'dist/pixelegos.js'], dest: 'dist/pixelegos.js' } } ~~~ 由于grunt-contrib-concat和grunt-cmd-concat產生了task name的沖突,可以通過grunt.renameTask來修改task名。 下一步,uglify! ~~~ uglify : { app : { files: [ { expand: true, cwd: 'dist/', src: ['**/*.js', '!**/*-debug.js'], dest: 'dist/', ext: '.js' } ] } } ~~~ 大功告成,完整的Gruntfile.js如下: ~~~ module.exports = function (grunt) { grunt.initConfig({ pkg : grunt.file.readJSON("package.json"), transport : { options: { idleading: '/dist/', alias: '<%= pkg.spm.alias %>', debug: false }, app:{ files:[{ cwd: 'js/', src: '**/*', dest: '.build' }] } }, concat : { options : { include : 'all' }, app: { files: [ { expand: true, cwd: '.build/', src: ['pixelegos.js'], dest: 'dist/', ext: '.js' } ] } }, normalconcat: { app: { src: ['js/engine.js', 'dist/pixelegos.js'], dest: 'dist/pixelegos.js' } }, uglify : { app : { files: [ { expand: true, cwd: 'dist/', src: ['**/*.js', '!**/*-debug.js'], dest: 'dist/', ext: '.js' } ] } }, clean:{ app:['.build', 'dist'] } }) grunt.loadNpmTasks('grunt-cmd-transport') grunt.loadNpmTasks('grunt-contrib-concat') grunt.renameTask('concat', 'normalconcat') grunt.loadNpmTasks('grunt-cmd-concat') grunt.loadNpmTasks('grunt-contrib-uglify') grunt.loadNpmTasks('grunt-contrib-clean') grunt.registerTask('build', ['clean', 'transport:app', 'concat:app', 'normalconcat:app', 'uglify:app']) grunt.registerTask('default', ['build']) } ~~~ ## 總結 我們使用spm將一個非cmd模塊venus轉成了標準的cmd模塊venus-in-cmd,然后我們用它結合多個cmd模塊構建了一個簡單的網頁程序。很有成就,有沒有!接下來我們要進入hard模式了,我們來看看,Sea.js是如何實現的?只有了解了它的內部是如何運作的,在使用它的過程才能游刃有余!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看