知向前端
seajs+spm3修炼手册
2016-5-8 Jon
一、写在前面

    前端技术层出不穷,js模块化更是大势所趋,乱世必出英雄,seajs就是js模块化的佼佼者。


    文章适合初学者,大神请绕过。对于一个新技术的学习,主要会讲



        ->seajs定义及作用



        ->为何要用seajs



        ->seajs如何使用之理论篇



        ->seajs理论偏使用拓展之spm3



        ->seajs如何使用之实践篇



        ->seajs文章推荐。


二、seajs定义及作用?

    1,看下百度释义:

        SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制。主要目的是令JavaScript开发模块化并可以轻松愉悦进行加载,将前端工程师从繁重的JavaScript文件及对象依赖处理中解放出来,可以专注于代码本身的逻辑。SeaJS可以与jQuery这类框架完美集成。使用SeaJS可以提高JavaScript代码的可读性和清晰度,解决目前JavaScript编程中普遍存在的依赖关系混乱和代码纠缠等问题,方便代码的编写和维护。SeaJS的作者是前淘宝UED,现支付宝前端工程师玉伯。SeaJS本身遵循KISS(Keep It Simple,Stupid)理念进行开发,其本身仅有个位数的API,因此学习起来毫无压力。在学习SeaJS的过程中,处处能感受到KISS原则的精髓——仅做一件事,做好一件事。

    2,说人话:

        seajs就是一个js文件,使用它可以方便管理其它js代码,提高开发效率,易学易用。

三、为何要用seajs?

    js的发展不同于其它后台语言,没有模块化的概念,代码混乱且不易维护,从而使得js一度被认为是一门玩具语言。nodejs的出现,将js推向了舞台中央,于是一发不可收拾。社区论坛活跃度成指数函数递增(夸张下),不管前端还是后端,不会写两行js代码都不好意思说自己是程序员。就在这个大背景下,急需出现一种能让js也模块化开发的工具,从而减少依赖和命名冲突。时势造英雄,于是乎,seajs应运而生。

    什么?没听懂?来,我告诉你,其实就是解决js的两个大问题:命名空间冲突和文件依赖

    附文章一篇http://chaoskeh.com/blog/why-seajs.html进一步确认自己需要使用seajs进行js开发了。

四、seajs如何使用理论偏?

    说的比唱的好听,那该怎么使用呢?

    1,seajs修炼第一重:下载并引入seajs

        官网下载:http://seajs.org/docs/#downloads

        下载后会看到dist目录下有个sea.js,对就是他,我们的英雄小哪吒,在项目中引入它就可以了。


        为了让 sea.js内部能快速获取到自身路径,推荐手动加上 id 属性,这对性能和稳定性会有一定提升,推荐默认都加上。



        <script src="js/sea.js" id="seajsnode"></script>


    2,seajs修炼第二重:使用seajs函数“define”(函数基本就这一个)

        说明:使用define函数来定义一个模块,据CMD规范。一个文件就是一个模块。所以一个js文件中只有一个define。SeaJS中模块的概念有点类似于面向对象中的类——模块可以拥有数据和方法,数据和方法可以定义为公共或私有,公共数据和方法可以供别的模块调用。

        1)define是如何处理参数的:

         fn.define = function(id, deps, factory)

           define可以接收的参数分别是模块ID,依赖模块数组及工厂函数;

           如果只有一个参数,则赋值给factory。

           如果有两个参数,第二个赋值给factory;第一个如果是array则赋值给deps,否则赋值给id。

           如果有三个参数,则分别赋值给id,deps和factory。

        2)定义一个模块

            define(function(require,exports, module) {

                var a  = require('./a');//引入a模块 即引入a.js,js文件后缀名可省略

                //require是同步的 所以下面可以使用require过来的模块

                a.fun1();//调用a.js里面定义并暴露给外部的fun1函数

                a.name;//调用a.js里面定义并暴露给外部的fun1属性

                var data1 = 1; //私有属性

                var func1  = function() { //私有方法

                exports.name='定义name属性暴露给外部';

                exports.fun2= function(){

                    console.log('定义了fun2函数并通过exports暴露给外部');

                }

            });


              require——记载依赖模块。通过这个参数来进行对其他模块的加载。

           exports——接口点,将数据或方法定义在其上则将其暴露给外部调用。

           module——模块的元数据。是一个对象,有属性:

                module.id——模块的ID。

                module.dependencies储了此模块依赖的所有模块的ID列表的一个数组。

                module.exports——与exports指向同一个对象。

          3)除了外面多了一层define(function(){});其他使用类似nodejs

        4)除了使用exports来向外部暴露属性方法还可以使用return

        5)当return语句是模块的唯一代码,可以直接返回一个json对象

            define({

              data: 1,

              func:function() {

                return'hello';

              }

            });

    3,seajs修炼第三重:熟悉require对象

        require对象进行加载依赖的模块,或者可以使用require.async('./a')来进行异步加载,即当使用到的时候才进行加载。

        加载完成后的回调函数

        require('./a',function(a){});

        使用require对象来进行加载模块,其实使用正则表达式进行验证加载的,所以其参数必须是特定的字符串,不能是表达式。

    4,seajs修炼第四重:使用seajs.config进行全局配置

    seajs.config({

      //Sea.js 的基础路径

      //Sea.js 在解析顶级标识时,会相对 base 路径来解析。详情请参阅 模块标识

      //注意:一般请不要配置 base 路径,把 sea.js 放在合适的路径往往更简单一致。

      base:'src/js/jslib/',

      //对较长的常用路径设置别名。

      alias: {

        'app':'src/js/app/'

      },

      //获取js时script标签的charset属性

      charset:'utf-8',

      //待脚本加载的最长时间,以毫秒为单位。

      timeout: 20000,

      //值为 true 时,加载器会使用 console.log 输出所有警告和错误。 默认为 false, 加载器只抛出异常。另外,还可以将 debug 值设为2。

      //这种情况下, 每个脚本请求都会加上唯一时间戳。这在测试期间很有用,可以强制浏览器每次都请求最新版本。

      debug:false,

      //普通模块加载前,提前加载初始化特定模块。

      preload: [ // 在老浏览器中,提前加载好ES5和json模块:

        Function.prototype.bind ? '' : 'es5-safe',

        this.JSON ? '' : 'json'

      ],

      // 变量配置

      vars: {

        'locale': 'zh-cn'

      },

      // 映射配置

      map: [

        ['http://example.com/js/app/', 'http://localhost/js/app/']

      ]

    });

    5,seajs修炼第五重:使用seajs.use 载入入口模块

    //单模块模式

    seajs.use('./a');

    //回调模式

    seajs.use('./a',function(a){

      a.dosomething();

    });

    //多模块模式

    seajs.use(['./a','./b'],function(a,b) {

      a.dosomething();

      b.dosomething();

    });

    6,seajs修炼第六重:注意事项

    1)Sea.js模块文件推荐下面写法

      define(function(require, exports, module) {

        // 模块代码

      });

    2)seajs配合现有js使用

      define(function() {

        //现有js代码

        return $.noConflict();

      });

      如:var $ = require('./jquery');

        //加载jquery返回值为null

        //解决方法

        define(function(){

          //jquery源代码

          return $.noConflict();

        });

    3)module.exports通常用于对外提供对象

      define(function(require, exports, module) {

        var obj={};

        obj.name='abc';

        obj.fun1=function(){};

        module.exports=obj;

      });

    4)版本差异

      2.1.0版

        去除 data-main、data-config 等语法糖功能,保持简单纯粹。

      2.3.0

        去掉css支持,推荐link标签同步引入。如果实在要用,可以用seajs-css插件来完成。

        preload移除,推荐script标签同步引入。如果实在要用,可以用seajs-preload插件来完成。

        去掉根据 sea.js 路径自动猜测 base 路径的功能。交给用户自己配置。

五、seajs理论偏使用拓展之spm3

    使用seajs写好的程序会发现很多js文件,这样直接发布项目服务器请求这么多次肯定是不友好的,当然seajs也意识到了这个问题,使用spm3可以合并压缩seajs的众多js文件。

    spm3是seajs修炼第七重,也是最后一层。

    下面介绍下spm3的使用方法:

    1、基于nodejs 需安装nodejs 可输入node -v测试

    2、然后安装spm

    npm install spm -g

    3、查看安装版本spm -v

    4、在项目下创建package.json 也可以用 npm init

    {

        "name": "mizi",

        "version": "1.0.0",

        "description": "with seajs",

        "author": "haha",

        "license": "MIT",

        "spm": {

          "main": "static/js/main.js"

        }

      }

    spm 字段是包含与 spm 构建相关的一些属性。这里把入口文件定义为 main.js (默认为 index.js)

    main入口文件,要压缩的文件

    5、执行

    spm build

    6、构建完成修改下页面引入js的路径

    如若不能运行但不报错可能是因为:

    spm3 当中,支持的书写规范从 CMD 模块 转向了 CommonJS。因此在构建之前,要先把原 CMD 模块的 define 包装去掉。构建之后 spm3 会自动在代码外添加。

    包装(如果没有去掉,构建后会发现原 define 外又添加了一层 define,会导致代码不能执行)。

    作者疑问

    1、为何我本地只生成了一个main.js 并没有生成main-debug.js呢。

    2、上面的即使不去掉 define 包装也是可以用的呀,亲测。

    3、命令行输入 spm init 并没有资料上说的那种会构建很多代码

    分析:是不是因为我spm3用的是3.9.0版本导致

    还请看到并知道的不吝留言告知

六、seajs如何使用之实践篇

    通过两个例子加强下seajs和spm3的使用吧

    github例子源码

七、seajs文章推荐:很多还没讲到,下面推荐seajs更多资料

    seajs官方文档:http://seajs.org/docs/

    深入探寻seajs的模块化与加载方式:http://www.jb51.net/article/64024.htm

    《Hello Sea.js》入门指南:http://island205.github.io/HelloSea.js/
评论:
sbf111
2016-09-28 09:32 回复
请问一下站长微信编纂页面是怎样做出来的?
19463333
2016-09-26 23:30 回复
博主太拼了 还广告推广
乐天堂
2016-09-26 23:29 回复
也欢迎博主到我的博客瞧一瞧.
19461688
2016-09-26 23:29 回复
很厉害 文章写得很好 顶
ca662
2016-09-26 22:49 回复
赞一个 十分不错 很有个性
tytgswzrol
2016-09-25 15:33 回复
seajs spm3修炼手册 - 勿恨水长东
yzc1188
2016-09-25 15:17 回复
谁也不是有阿谁禀赋的,在本人很小的领域里发挥特长的吧
bifa788
2016-09-24 20:41 回复
博主博客做的比力共同,对于技巧也有必然研究。同好中人。
frxemfgtzd
2016-09-24 18:35 回复
seajs spm3修炼手册 - 勿恨水长东
qg999
2016-09-24 18:22 回复
文章写的真的挺好,学习了
1 2 3
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容