基于gulp合并压缩Seajs模块的方式说明

之前的项目一直采用grunt来构建,然后用requirejs做模块化,requirejs官方有提供grunt的插件来做压缩合并。现在的项目切到了gulp,模块化用起了seajs,自然而然地也想到了模块合并压缩的问题。

然后一开始在解决这个问题的时候,并不是很顺利,在npm上并没有那种特别流行的专门用来做seajs合并压缩的gulp插件,虽然在seajs的github上也看了不少的issue,但是大多数都是只能将所有的模块文件合并成一个总的文件,这对于单页面的应用来说肯定没有问题,但是对于多页面的应用而言,显然就违背了模块化思想中按需加载的核心,所以我想要的是一个能够根据我每个页面各自所依赖的模块来按需合并的方法。

这个按需合并的意思,一方面是只合并一个页面所依赖的那些模块,另一方面是,还能过滤掉某些模块不参与合并,考虑这个的原因在于有些模块,比如jquery等,都属于第三方依赖的库,可能文件比较大,最重要的是你几乎不会去改动它的代码,所以这些模块不合并到页面的js中,会有助于更好地利用浏览器缓存。本文介绍一个简单可行的办法,来做基于gulp构建的中小型项目中的seajs合并压缩。

注:为了说明,seajs合并后的效果,本文提供了一个演示demo,它有两个页面:login.html和regist.html,分别用来模拟多页应用中的两个独立的文件,可通过以下链接来查看:

http://liuyunzhuge.github.io/blog/seajs/dist/html/login.html

http://liuyunzhuge.github.io/blog/seajs/dist/html/regist.html

以login.html为例,查看这个页面的源文件中,会看到它除了引用seajs以及相关的配置文件common.js外,只引用了app/login作为页面的main js,这个app/login模块其实对应的就是js/app/login.js:

但实际上,这个login.js依赖了更多的模块js,你可以通过chrome的soures来查看该页面加载的详细js资源:

在login.js合并之前,它的代码是这样的:

但是在前2个截图中,我们并没有看到mod/mod1.js , mod/mod2.js , deps/fastclick.js这三个文件,我们除了看到login.js,还看到了lib/bootstrap.js  , lib/jquery.js , lib/jquery.validate.js。这就是合并的效果。一方面保持了js/lib文件夹下的模块都不会参与合并,另一方面保证了页面的main js所依赖的其它模块,都合并到页面的main js文件中来。

该demo相关的代码可通过以下链接进行查看:

https://github.com/liuyunzhuge/blog/tree/master/seajs

1. 合并思路

其实方法还算比较简单,我最后再介绍。

1)我先说下自己对seajs的模块进行组织的一种文件夹结构,它是这样的:

这个结构借鉴于requirejs,尽量让文件组织扁平化,对于中小型前端项目来说,应该不会太麻烦。其中各个文件夹的作用是:

1)js/app 存放各个页面的main js,基本上是一个页面一个js的逻辑

2)js/deps 存放哪些需要被合并到main js的第三方模块

3)js/lib 存放哪些不需要参与合并的第三方模块

4)js/mod 存放各个项目中自己写的一些js模块

5)common.js 是seajs的配置文件。

2)在common.js中把js/lib下的模块都配置到了alias选项里面,因为这些js都不参与合并,需要使用到浏览器缓存,alias可以方便我们在修改或升级了js/lib下的文件的时候,对这些文件的加载地址做一点更新:

base配置到了js文件夹。在模块开发中,要require其他模块时,我的习惯都是直接写mod/mod1这样的模块标识,不用相对标识,即使要定义的这个模块所依赖的模块跟它存在于同一个文件夹中,这也是我为啥把base目录设置到js文件夹的原因,有点类似站点根目录的感觉。

3)合并的思路:主要是利用gulp-seajs-transport和gulp-seajs-concat这两个gulp插件。虽然它们在github上不是很热门,但是已经很好地解决我的问题了,使用起来也非常简单:

(更多内容需要查看本文开始处提供的源码链接,找到相关的gulpfile.js文件)

gulp-seajs-transport可以帮助你把seajs的模块文件从匿名模块,变成具名模块。比如js/mod/mod1.js在构建前是这样的:

但是经过transport处理后就会变成:

这个是seajs合并工作中比较关键的一点,它不像requirejs,直接做concat即可;它必须先经过一个transport的任务处理,将匿名模块变成具名模块,同时用define的第二个参数来描述这个模块的所有依赖,就像requirejs那样。只有做完了transport,才能利用gulp-seajs-concat做合并。原因请参考:https://github.com/seajs/seajs/issues/426

gulp-seajs-concat做合并的时候,就很简单了,只要告诉它一个base选项即可,这个base选项跟js/common.js中base选项保持一致。因为gulp-seajs-concat根据base和transport之后的模块,就能找到它所依赖的其它模块文件。

4)页面中使用main js时要采用这种方式:

use的参数名称,必须跟合并之后的main js的主模块ID保持一致。比如js/app/login.js合并之后是这个样子:

第一个define对应的模块就是合并后文件内的主模块,红框的内容就是该主模块的id,seajs use这个模块的时候,参数名称必须和这个id一致。否则seajs即使成功的加载到了这个文件,也不会执行任何模块内的代码。因为seajs有一个规则:ID 和路径匹配原则,其中有点跟这个相关,就是:当seajs use到一个文件内包含多个模块时,会根据use的参数名来寻找这个文件内的主模块,只有它们完全匹配,才能找得到。

5)压缩混淆:使用gulp-uglify:

但是要注意那个mangle,必须把require exports module排除掉,否则会引发一些意外的问题。

2. 本文小结

本文内容虽然很简单,但是在刚切到gulp和seajs的时候,还是费了不少时间才把本文的问题解决,虽然在准备demo的时候进展地比我当时的情况要顺利的多…不管怎么样,希望本文的内容多多少少能帮助到一些朋友。

(0)

相关推荐

  • 深入探寻seajs的模块化与加载方式

    由于一直在使用,所以了解了下seajs的源代码.这里是我对下面几个问题的理解: 1.seajs的require(XXX)的方法是怎样实现模块加载的? 2.为什么需要预加载? 3.为什么需要构建工具? 4.构建前后的代码究竟有些什么区别,为什么要这么做? 问题1: seajs的require(XXX)的方法是怎样实现模块加载的? 代码逻辑比较绕,对源代码的理解放在文章的末尾,这里先简单梳理下模块加载的逻辑: 1.从seajs.use方法入口,开始加载use到的模块. 2.use到的模块这时mod缓

  • seajs模块之间依赖的加载以及模块的执行

    本文介绍的是seajs模块之间依赖的加载以及模块的执行,下面话不多说直接来看详细的介绍. 入口方法 每个程序都有个入口方法,类似于c的main函数,seajs也不例外.系列一的demo在首页使用了seajs.use() ,这便是入口方法.入口方法可以接受2个参数,第一个参数为模块名称,第二个为回调函数.入口方法定义了一个新的模块,这个新定义的模块依赖入参提供的模块.然后设置新模块的回调函数,用以在loaded状态之后调用.该回调函数主要是执行所有依赖模块的工厂函数,最后在执行入口方法提供的回调.

  • seajs模块压缩问题与解决方法实例分析

    本文实例讲述了seajs模块压缩问题与解决方法.分享给大家供大家参考,具体如下: 在优化整理项目代码时,想使用seajs来把代码模块化.看了下官方5分钟上手教程,觉得很不错,也没多想就一直开发下去了,也没出什么问题.等一同事说把代码打包个放到设备上去测试一下,发现怎么也跑不起来,郁闷了. 于是单步调试一把,发现模块一直加不进来.看了一下seajs的原码,明白了是怎么回事. define模块解析依赖有两种途径,一种是从define(id, deps, factory)中的deps来:还有一种是解析

  • seajs学习之模块的依赖加载及模块API的导出

    前言 SeaJS非常强大,SeaJS可以加载任意 JavaScript 模块和css模块样式,SeaJS会保证你在使用一个模块时,已经将所依赖的其他模块载入到脚本运行环境中. 通过参照上文的demo,我们结合源码分析在简单的API调用的背后,到底使用了什么技巧来实现各个模块的依赖加载以及模块API的导出. 模块类和状态类 首先定义了一个Module类,对应与一个模块 function Module(uri, deps) { this.uri = uri this.dependencies = d

  • seajs中最常用的7个功能、配置示例

    本文实例讲述了seajs中最常用的7个功能.配置.分享给大家供大家参考,具体如下: 1. seajs.config seajs.config({ // 设置路径,方便跨项目调用 paths: { 'path1': '....', 'path2': '....' }, // 设置别名,方便调用 alias: { 'class1': '...', 'class2': '...' } }); 2. seajs.use 用来在页面中加载一个或多个模块 // 加载一个模块 seajs.use('./a')

  • 把jQuery的类、插件封装成seajs的模块的方法

    注:本文使用的seajs版本是2.1.1一.把Jquery封装成seajs的模块 复制代码 代码如下: define(function () { //这里放置jquery代码 把你喜欢的jquery版本放进来就好了 return $.noConflict();}); 调用方法:这样引进就可以像以前一样使用jquery 复制代码 代码如下: define(function (require, exports, module) {    var $ = require('./js/jquery');

  • seajs中模块的解析规则详解和模块使用总结

    seajs github 模块标识已经说的相对清楚了.但并没有面面俱到,特别是当你需要手写 [模块ID]和[模块依赖]的时候,或者自己写自动化工具来做 transport 的时候(ps:spm貌似适应性不是很强也不易用,毕竟每个项目的目录结构可能相差很大,且不易改变.当然如果他的定位是包管理工具就别指望它来做你的项目的自动化构建工具了),ID的解析规则就需要了解透彻了.注意事项:1. 顶级标识始终相对 base 基础路径解析.2. 绝对路径和根路径始终相对当前页面解析.3. require 和

  • 基于gulp合并压缩Seajs模块的方式说明

    之前的项目一直采用grunt来构建,然后用requirejs做模块化,requirejs官方有提供grunt的插件来做压缩合并.现在的项目切到了gulp,模块化用起了seajs,自然而然地也想到了模块合并压缩的问题. 然后一开始在解决这个问题的时候,并不是很顺利,在npm上并没有那种特别流行的专门用来做seajs合并压缩的gulp插件,虽然在seajs的github上也看了不少的issue,但是大多数都是只能将所有的模块文件合并成一个总的文件,这对于单页面的应用来说肯定没有问题,但是对于多页面的

  • require.js 加载 vue组件 r.js 合并压缩的实例

    准备: vue.js 原本是学习vue组件 require.js 然后想到用require 加载 r.js 文件太多 合并 文件目录 忽略部分文件及文件夹 一.先说vue 组件 先引入vue 再引入vue组件 Vue.extend({}) 定义组件 template data methods Vue.component(),注册组件的标签,标签在html中是一个挂载点 new Vue() 进行实例化 index.html // css引入 略 <div id="header"&g

  • 小心!AngularJS结合RequireJS做文件合并压缩的那些坑

    在项目使用了AngularJS框架,用RequireJS做异步模块加载(AMD),在做文件合并压缩时,遇到了一些坑,有些只是解决了,但不明白原因. 那些坑 1. build.js里面的paths必须跟main.js里面的保持一致. 这个build.js就是r.js使用的配置文件,而main.js就是RequireJS的main文件.在合并压缩时候,build.js文件里面也需要写paths,而且还是跟main.js一样,我很奇怪为什么就不能识别main里面的require.config的path

  • 基于对象合并功能的实现示例

    前言 jQuery 中的 $.extend() 是经常使用到工具函数,多用于合并参数(对象),具体用法在这里不过多赘述,可通过传参控制合并过程中是否使用深度拷贝:而ES2015中新增的 Object.assign()方法,也可以实现对象的合并,不过合并过程中使用的是浅拷贝:本文参考了jQuery的extend方法的源码,将自己实现对象合并,即将多个对象的属性复制到目标对象上,若有相同的属性,后面的对象覆盖前面的. 浅拷贝的方式实现对象合并 之前的一篇博文 有专门介绍对象和数组的深浅拷贝,不了解的

  • JS中使用gulp实现压缩文件及浏览器热加载功能

    gulp类似于grunt,都是基于Node.js的前端构建工具.不过gulp压缩效率更高. 一.安装gulp 首先,你要安装过nodejs,如果没有安装过的同学请自行下载.  先再命令行里输入   npm install gulp -g   下载gulp 二.创建gulp项目 创建一个你需要项目文件夹,然后在根目录输入  npm init  (npm init命令会为你创建一个package.json文件,这个文件保存着这个项目相关信息.比如你用到的各种依赖) 三.使用npm install 安

  • 详解使用grunt完成requirejs的合并压缩和js文件的版本控制

    最近有一个项目使用了 requirejs 来解决前端的模块化,但是随着页面和模块的越来越多,我发现我快要hold不住这些可爱的js文件了,具体表现在每个页面都要设置一堆 requirejs 的配置( baseUrl , paths 之类的). 不知谁说过,一些事重复做了三次,就该考虑一下自动化了,于是我小心翼翼的掏出了我的 grunt . 我们得使用 grunt-contrib-requirejs 这个插件来实现如上所说的自动化功能,这个就是根据 r.js 封装的 grunt 插件. 安装 gr

  • 基于java解析JSON的三种方式详解

    本文实例分析了基于java解析JSON的三种方式.分享给大家供大家参考,具体如下: 一.什么是JSON? JSON是一种取代XML的数据结构,和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度. JSON就是一串字符串 只不过元素会使用特定的符号标注. {} 双括号表示对象 [] 中括号表示数组 "" 双引号内是属性或值 : 冒号表示后者是前者的值(这个值可以是字符串.数字.也可以是另一个数组或对象) 所以 {"name"

  • 基于Django contrib Comments 评论模块(详解)

    老版本的Django中自带一个评论框架.但是从1.6版本后,该框架独立出去了,也就是本文的评论插件. 这个插件可给models附加评论,因此常被用于为博客文章.图片.书籍章节或其它任何东西添加评论. 一.快速入门 快速使用步骤: 安装包:pip install django-contrib-comments 在django的settings中的INSTALLED_APPS处添加'django.contrib.sites'进行app注册,并设置SITE_ID值. 在django的settings中

  • r.js来合并压缩css文件的示例

    如何使用r.js来合并压缩css文件.在r5下新建一个css文件夹,里面有四个css文件:main.css.nav.css.form.css.grid.css. main.css是合并的主文件,或称配置文件.要合并的文件使用@import引入.如下 main.css @importurl("nav.css"); @importurl("grid.css"); @importurl("form.css"); 另外三个是普通的css文件,里面定义的各

随机推荐