Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

seajs 中 require 模块跨目录产生的路径问题 #848

Closed
lchuilu opened this issue Jul 15, 2013 · 17 comments
Closed

seajs 中 require 模块跨目录产生的路径问题 #848

lchuilu opened this issue Jul 15, 2013 · 17 comments

Comments

@lchuilu
Copy link

lchuilu commented Jul 15, 2013

某模块结构如下:

PRODUCTLIST
│ - default.js
│ -   init.js
│  -  list.js
│  - lz.js
│  -  Makefile
│  -  promotion.js
│  
└─shoes
         |- init.js
         |- Makefile
         |- package.json
         |- shoes.js

seajs config 如下:

seajs.config({
  base:"http://static1.cdn.cn/resources/",
   alias: {
    "jquery": "libs/jquery/jquery.js"
    },
  debug:false,
  preload: ["jquery"],
    map: [
        [ /^(.*\.(?:css|js))(.*)$/i, "$1?v=0712" ]
      ]
});

shoes/init.js 内容:

define(function(require, exports, module){
    "require:nomunge,exports:nomunge,module:nomunge";
    require('scripts/common/header.js');
    require.async('scripts/common/scrolltotop.js',function(){
        scrolltotop.init('#gotoTop')
    });
    seajs.use([
        '../list',
        './shoes',
        '../lz',
        '../promotion'
    ], function(getprice, list, shoes, lz, promotion){
        getprice.init();
        list.init(); 
        shoes.init(); 
        lz.init();
        promotion.init(); 
    });
});

浏览器加载的shoes.js 的路径变成了 http://static1.cdn.cn/shoes.js , list,lz,promotion ,3个模块都没有载入,不知什么原因。

如果 seajs.use 中4个模块的路径使用 productlist/list , productlist/lz, productlist/promotion, productlist/shoes/shoes,则正常载入。

@popomore
Copy link
Member

请不要在模块中使用 seajs.use

@lchuilu
Copy link
Author

lchuilu commented Jul 15, 2013

如果不是用 seajs.use 使用什么比较好呢? 而且对于我这个问题, 如果使用require 有如下的问题:
1,require('../list') 时,根本没有下载 productlist/list.js 这个文件,
2, require((‘./shoes’), 会报错 ReferenceError: jQuery is not defined 。
请问如何解决。

@nuintun
Copy link

nuintun commented Jul 15, 2013

记好define定义的模块中不能出现userequire的文件如果在当前目录用./list就行了,../是父目录的意思,建议仔细阅读 #258

@lifesinger
Copy link
Member

require('./list.js')

init.js 和 list.js 是平级的。

@lifesinger
Copy link
Member

不对,针对你的项目结果,productlist 是一个模块,shoes 则是另一个模块,这种跨模块的引用,可以:

seajs.config({

  paths: {
      'productlist': 'http://path/to/productlist'
  }

})

然后在 shoes/init.js 里

define(function(require, exports, module){
    "require:nomunge,exports:nomunge,module:nomunge";
    require('scripts/common/header.js');
    require.async('scripts/common/scrolltotop.js',function(){
        scrolltotop.init('#gotoTop')
    });

    require('productlist/list').init()
    require('productlist/shoes').init()
    require('productlist/lz').init()
    require('productlist/promotion').init()

});

@lifesinger
Copy link
Member

如果 productlist 就在 base 目录下,上面的 paths 配置也可以去掉。

@lchuilu
Copy link
Author

lchuilu commented Jul 15, 2013

明白了,
lz.js 代码如下:

define(function(require, exports, module) {"require:nomunge,exports:nomunge,module:nomunge";
    require.async('libs/jquery/jquery.lazyload.js');
    exports.init = function() {
           ..
    }
})

调用的话应该用 require('../lz').init() ,这样吧?

@lifesinger
Copy link
Member

调用的话应该用 require('../lz').init() ,这样吧?

是在什么地方调用 lz.js? 不同文件里调用,写法不一样。比如在 list.js 里调用 lz.js,只需要 require('./lz.js') 就好,在 shoes.js 里调用 lz.js ,则使用 require('productlist/lz.js')

基本原则是:同模块内的文件调用,用相对路径,跨模块的文件调用,用 top-level id 去调用。

@lchuilu
Copy link
Author

lchuilu commented Jul 16, 2013

@lifesinger 感谢!
我配置

seajs.config({
base:"http://path/resources/",
  paths: {
      'pl': 'http://path/resources/scripts/productlist'
  }
})

后,把 shoes/init.js 改成如下:

define(function(require, exports, module){
    "require:nomunge,exports:nomunge,module:nomunge";
    require('scripts/common/header.js');
    require.async('scripts/common/scrolltotop.js',function(){
        scrolltotop.init('#gotoTop')
    });
    require('pl/list').init()
    require('./shoes').init()
    require('pl/lz').init()
    require('pl/promotion').init()
});

发现 require('pl/list').init() 中最后浏览器引用的地址是: http://path/resources/pl/list.js 而不是 预想的 http://path/resources/scripts/productlist/list.js . 这是为什么?

不过使用 相对路径 :

    require('../list').init()
    require('./shoes').init()
    require('../lz').init()
    require('../promotion').init()

是可以正确读到文件的。
ps: seajs 是1.3.1 版本
不过以上两种写法在 spm-build 的时候都会报错如下:

[z@z-141 shoes]$ spm-build
           Task: "clean:build" (clean) task
           Task: "spm-install" task
           Task: "transport:src" (transport) task
           warn: found id in "dist/init-debug.js"
           warn: found id in "dist/init.js"
           warn: can't find module scripts/common/header
           warn: can't find module scripts/common/getprice
           warn: can't find module scripts/common/header
           warn: can't find module scripts/common/getprice
      transport: 8 files
           Task: "concat:css" (concat) task
       concated: 0 files
           Task: "transport:css" (transport) task
      transport: 0 files
           Task: "concat:js" (concat) task
           warn: file .build/list.js not found
           warn: file .build/lz.js not found
           warn: file .build/promotion.js not found
           warn: file .build/list-debug.js not found
           warn: file .build/lz-debug.js not found
           warn: file .build/promotion-debug.js not found
       concated: 2 files
           Task: "copy:build" (copy) task
           Task: "cssmin:css" (cssmin) task
           Task: "uglify:js" (uglify) task
           file: ".build/dist/init.js" created.
           Task: "clean:dist" (clean) task
       cleaning: "dist"...
           Task: "copy:dist" (copy) task
         copied: 2 files
           Task: "clean:build" (clean) task
       cleaning: ".build"...
           Task: "spm-newline" task
         create: dist/init.js
         create: dist/init-debug.js
           Done: but with warnings.

list.js ,lz.js ,promotion.js 这3个上一级目录的模块均未找到,打包失败。

@lifesinger
Copy link
Member

囧,升级 Sea.js 到 2.1.1

@lchuilu
Copy link
Author

lchuilu commented Jul 16, 2013

@lifesinger @popomore
已升级到2.1.1 。 paths 可用了。不过 经过spm build 的模块全部失效。 具体情况是 :
header.js 代码如果如下:

define("http://path/resources/scripts/common/header", [ "libs/util/modernizr", "./loginfo", "./menu", "./cartpop", "./hpop", "./analytics", "scripts/common/topsuggest" ], function(require, exports, module) {
    require('libs/util/modernizr.js');
    require('./loginfo');
    require('./menu');
    require('./cartpop');
    require('./hpop');
    require('./analytics'); 
    require('scripts/common/topsuggest.js').init();
console.log(1)
})

则在和header.js 同级的 init.js 中 require('./header') ,header.js中的代码不执行。
console.log(1) 都显示不出。
如果 header.js代码如下:

define(function(require, exports, module) {
    require('libs/util/modernizr.js');
    require('./loginfo');
    require('./menu');
    require('./cartpop');
    require('./hpop');
    require('./analytics'); 
    require('scripts/common/topsuggest.js').init();
console.log(1)
})

则在于header.js 同级的 init.js 中 require('./header') ,header.js中的代码可以执行。

这是为什么? 之前使用seajs 1.3.1 的时候正常。

@lifesinger
Copy link
Member

spm 升级到最新版了没?http://docs.spmjs.org/

@lchuilu
Copy link
Author

lchuilu commented Jul 16, 2013

@lifesinger spm 升级到了2.1.6 .
而且header.js 写全 id ,和依赖无法执行的那个问题,应该跟spm无关啊?

@lifesinger
Copy link
Member

则在和header.js 同级的 init.js 中 require('./header') ,header.js中的代码不执行。

在 init.js 里,通过 console.log(require.resolve('./header')) 看下解析的 header 路径是否正确。

@lchuilu
Copy link
Author

lchuilu commented Jul 17, 2013

resolve了一下路径没有错误。
而且


define(function(require, exports, module) {
require('libs/util/modernizr.js');
require('./loginfo');
require('./menu');
require('./cartpop');
require('./hpop');
require('./analytics');
require('scripts/common/topsuggest.js').init();
console.log(1)
})
console.log(0)

中, 0和1 都可以打出来。如果

define("http://path/resources/scripts/common/header", [ "libs/util/modernizr", "./loginfo", "./menu", "./cartpop", "./hpop", "./analytics", "scripts/common/topsuggest" ], function(require, exports, module) {
    require('libs/util/modernizr.js');
    require('./loginfo');
    require('./menu');
    require('./cartpop');
    require('./hpop');
    require('./analytics'); 
    require('scripts/common/topsuggest.js').init();
    console.log(1)
})
 console.log(0)

则只能打出0,1打不出。

@lchuilu
Copy link
Author

lchuilu commented Jul 17, 2013

我发现什么原因了。 是因为

define("http://path/resources/scripts/common/header", [ "libs/util/modernizr", "./loginfo", "./menu", "./cartpop", "./hpop", "./analytics", "scripts/common/topsuggest" ], function(require, exports, module) {
    require('libs/util/modernizr.js');
    require('./loginfo');
    require('./menu');
    require('./cartpop');
    require('./hpop');
    require('./analytics'); 
    require('scripts/common/topsuggest.js').init();
    console.log(1)
})

加重部分的路径不对。应该是 "http://path/resources/scripts/common/dist/header", [ "libs/util/modernizr", "../loginfo", "../menu", "../cartpop", "../hpop", "../analytics"" 之前在1.3.1的时候好像无所谓,升级到2.1.1就必须对应路径了。

@lifesinger
Copy link
Member

对,有这个调整。1.3.1 会去「猜」路径,会带来不少诡异的 bug。2.x 后,必须严格匹配。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants