模块压缩后无法加载,保留require关键字后可以加载的问题 #1153

本文记录了在使用SeaJS进行模块打包过程中遇到的问题及解决方案,包括模块压缩后无法正常加载、模块重复加载等问题,并分享了最终实现单文件打包的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 Closed
blackey629 opened this  issue on 7 Apr · 18 comments

3 participants

blackey629 army8735 偏右
blackey629
blackey629 commented  on 7 Apr

我在按照实际项目搭建seajs环境时碰到该问题,模块压缩后无法正常加载,但是我手动保留require关键字之后可以正常运行。seajs版本为2.3.0

下图是压缩后的请求过程

qq20140406234619

下图是自动保留require关键字后的请求过程

qq20140406234910

项目结构,模块module/pp是存在的

qq20140406235537

以下是关键代码

    <script id="seajsnode" src="../dist/3rd-lib/sea.js" type="text/javascript"></script>
    <script type="text/javascript">
    seajs.config({  
        base: "../dist", 
        alias: {
            "jquery": "jquery/jquery/1.10.1/jquery"
        }  
    });  
    seajs.use("main/groupsend");
    </script>

请各位帮忙诊断一下,谢谢了。

army8735
Owner
army8735 commented  on 7 Apr

你不构建直接用某个压缩器压缩的么……呃,这种用法的确压缩器会把factory的require参数给混淆掉,提取依赖的正则自然就挂了。

blackey629
blackey629 commented  on 7 Apr

构建用的grunt,我看seajs的example应用里的require关键词都被替换了,能够正常运行,是否我的环境哪个地方没配置到?有没有同学碰到过类似的坑?

army8735
Owner
army8735 commented  on 7 Apr

因为那些依赖被构建提取到了define(id:String = null, deps:Array = null, factory:Object)的第二个deps参数数组上。

army8735
Owner
army8735 commented  on 7 Apr

想想目前的xmd方式的确蛮多坑的,一不注意就要掉进去。未来的es6 module会是银弹吗?

blackey629
blackey629 commented  on 7 Apr

我调试了一下seajs的源码发现,确实用正则表达式来解析模块依赖,如果保留require关键字时,能够正常解析出依赖模块,但是压缩后就解析不出来了。

seajs自带的demo将main和模块压缩到一块了。但是就像我搭建的环境,几个页面共同依赖某些模块,能否将main和模块分开压缩呢?

偏右
Owner
afc163 commented  on 7 Apr

@blackey629 
一、#426 已经说的很清楚了。
二、seajs 自带的 demo 并没有将 main 和其他模块压缩到一块,就是分开压缩的。

blackey629
blackey629 commented  on 7 Apr

@afc163 问题已经解决,原因是我的grunt配置文件有问题,在uglify的时候,输入文件没有设置成transport之后的文件,而是设置成了最原始文件了,所以没有解析到dependencies。

谢谢 @afc163 和 @army8735 的热心帮助。

又出现一个新问题,在加载完成压缩文件后,又请求了一遍被压缩的模块。如图,pp.js中已经有 msgsender模块的定义,但是又单独请求了msgsender模块。
qq20140407180554

我看了 #948 ,但是没有看懂是怎么回事,望指点~~

army8735
Owner
army8735 commented  on 8 Apr

看着像#930

blackey629
blackey629 commented  on 8 Apr

我看了 #930 之后,也检查了自己的环境,没看出问题。

qq20140408142454

如图,开发环境的basejs文件夹,构建后的basedist文件夹,我将js/module下的所有文件合并到dist/module/pp.js中,这样只要加载了pp.js,其他的所有模块应该都加载的,也遵守ID和路径匹配原则啊。

难道说concat的时候,定义的src文件按照依赖有先后顺序吗?

army8735
Owner
army8735 commented  on 8 Apr

传上来看看……

blackey629
blackey629 commented  on 8 Apr

访问地址:http://programshare.duapp.com/pp.jsp

目前使用seajs为debug版本,2.3.0。

偏右
Owner
afc163 commented  on 8 Apr

#1146 和这个是同一个问题。

http://programshare.duapp.com/skins/dist/main/menu.js 文件里面依赖了 module/pp 和 module/menudata ,这两是并行下载的,互相无法知道谁包含了谁,都会发请求。

blackey629
blackey629 commented  on 8 Apr

为了简化调试,我只调用了main/groupsend.js,注释掉main/menu。构建后的groupsend,代码如下:

define("main/groupsend",["module/msgsender","jquery","template","module/msgsendertmpl","module/popwin","module/selectappmsg","module/appmsg"],function(a){var b=a("module/msgsender"),c=new b("#js-msgSender");c.render()});

我将concat之后的文件名改为msgsender.js,然后测试还是有问题。从后面代码可以看出,groupsend只依赖module/msgsender,我又把其依赖项手动处理为["module/msgsender"],这样就没有问题了。

可以看出确实是由于并行加载导致的。

#1146 给出的答案感觉没有通用性。seajs模块划不能随便乱分,是否有一定的划分原则呢?,请指点一下。

army8735
Owner
army8735 commented  on 8 Apr

并行产生的冗余是没办法的,一般上线后都会打包成一个文件,所以很少出现。

blackey629
blackey629 commented  on 8 Apr

我本来的思路:应用有多个页面,就做多个main模块,每一个页面都调用对应的main.js,这就相当于应用的main函数,然后公用的模块可以由这些页面的main调用。

那看来这种思路和seajs有冲突?将所有的js构建为一个文件,然后只有一个main,在这里面根据页面做路由,这样应该可行吧?

army8735
Owner
army8735 commented  on 8 Apr

不冲突。写多了就有划分包依赖的经验了。程序员都是处女座……

blackey629
blackey629 commented  on 9 Apr

ok,明白了,还是得多实践,非常感谢 @army8735 和 @afc163 的解答。

army8735 army8735 closed this  on 9 Apr
crossjs crossjs referenced this issue in  pandorajs/dialog  on 27 Apr
 Open

一个“BUG”,做个记录 #1

blackey629
blackey629 commented  on 4 May

我终于将所有的SeaJS模块打包成了一个文件,解决了重复加载的问题,说一说我的思路吧。

主要思路就是加上了模块的路由。原来每一个页面对应一个主模块,后来我在这些主模块之上增加了一个简单的入口模块,主要作用是路由,根据页面的请求url解析主模块的名称,然后使用require.async()函数加载对应主模块。举例说明:

请求url为http://localhost/pp/index.htm,根据既定的规则解析出模块名称为index,同时应该存在主模块为index,这样就能加载了。

image

路由模块的代码

define(function(require){
    var r = new RegExp(/\w+.htm/g);
    var url = location.href;
    var postfix = url.match(r);
    var moduleName = 'index';

    if(postfix && postfix.length > 0){
        moduleName = postfix[0].split('.')[0];
    }

    var module = 'main/' + moduleName;
    require.async(module, function(cb) {
        if(!cb) {
            alert('页面加载错误,请刷新!');
        }
    })
});

所有的页面只调用入口模块main就OK了。

这种做法的缺点是SesJs模块和请求的url耦合在一起了,不过在当前项目的环境下还是很合适的,因为控制层+jsp采用了一套框架,url也有规则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值