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

require 书写约定 #259

Closed
lifesinger opened this issue Jul 6, 2012 · 59 comments
Closed

require 书写约定 #259

lifesinger opened this issue Jul 6, 2012 · 59 comments
Milestone

Comments

@lifesinger
Copy link
Member

require 书写约定

使用 Sea.js 书写模块代码时,需要遵循一些简单规则。

只是书写和调试时的规范!!!构建后的代码完全不需要遵循下面的约定!!!!!!

1. 正确拼写

模块 factory 构造方法的第一个参数 必须 命名为 require

// 错误!
define(function(req) {
  // ...
});

// 正确!
define(function(require) {
  // ...
});

2. 不要修改

不要重命名 require 函数,或在任何作用域中给 require 重新赋值。

// 错误 - 重命名 "require"!
var req = require, mod = req("./mod");

// 错误 - 重定义 "require"!
require = function() {};

// 错误 - 重定义 "require" 为函数参数!
function F(require) {}

// 错误 - 在内嵌作用域内重定义了 "require"!
function F() {
  var require = function() {};
}

3. 使用直接量

require 的参数值 必须 是字符串直接量。

// 错误!
require(myModule);

// 错误!
require("my-" + "module");

// 错误!
require("MY-MODULE".toLowerCase());

// 正确!
require("my-module");

在书写模块代码时,必须遵循这些规则。其实只要把 require 看做是语法关键字 就好啦。

关于动态依赖

有时会希望可以使用 require 来进行条件加载:

if (todayIsWeekend)
  require("play");
else
  require("work");

但请牢记,从静态分析的角度来看,这个模块同时依赖 play 和 work 两个模块,加载器会把这两个模块文件都下载下来。 这种情况下,推荐使用 require.async 来进行条件加载。

Why?

这些约定初看起来会有些小不爽,其实也的确可以通过每次都编译的方式来去掉这些限制。但编译的方式,会给开发调试带来麻烦,代码的实现复杂度也会增加。Sea.js 的核心设计原则是保持简单,遵循 New Jersey Approach

简单性:设计必须简单,这既是对实现的要求,也是对接口的要求。实现的简单要比接口的简单更加重要。简单是设计中需要第一重视的因素。

因为简单,所以可靠!

参考文档

@lifesinger
Copy link
Member Author

有任何问题,欢迎留言交流。
注意:已解决的问题,会在整理后删除掉。

This was referenced Mar 5, 2013
@nnzbz
Copy link

nnzbz commented Jul 3, 2013

很不理解,在框架中用到一个动态加载依赖的设计是很正常的,不会是不良设计的根源,不可能要求以后每添加一个模块就要在这里加个else,而其实只要简单传个变量过来就可以做到的,代码也是相当的优雅

@lifesinger
Copy link
Member Author

@nnzbz 那只有等浏览器以后来支持了。

@nnzbz
Copy link

nnzbz commented Jul 4, 2013

我水平面比较低,能讲解一下为什么只能是字符串直接量吗?我好学习一下

@afc163
Copy link
Member

afc163 commented Jul 4, 2013

@nnzbz 看文中的参考文档。

@zzuhan
Copy link

zzuhan commented Sep 4, 2013

@nnzbz 因为在要执行某个模块时,会预加载这个模块中的依赖,里面变量都未执行,所以。。。

@luhang02
Copy link

为什么我写的require("$")返回结果是空的因为jquery.js没有exports,而arale的模块require同一个js是正常的

@sprying
Copy link

sprying commented Feb 17, 2014

看了《程序员》上关于玉伯 的 模块化开发思想,当时也想到了将函数字符串化,再正则提取。Seajs正是如此,但有许多限制。

@emilley
Copy link

emilley commented Apr 14, 2014

为什么require来进行条件加载,两个文件就都加载进来了?而require.async只加载进来需要的文件?

@afc163
Copy link
Member

afc163 commented Apr 14, 2014

@emilley 这篇文档不就是解释你的问题的?

@hi-zhaolei
Copy link

e42b29288c800c5ce42071c28f717de4
fa26926299b75ee5e34517867d59bbe6

@lifesinger 模块构造函数的第一个参数必须用require么?我在2个项目里使用seajs,2.1.0版本,我发现前一个版本将第一个参数写成任何样子都可以,但是第二个项目却不行,第一个参数必须要require才能识别,2.2.1和2.1.0都做了测试,能帮忙解决一下这个疑惑么?

@afc163
Copy link
Member

afc163 commented Apr 18, 2014

你看下并理解楼上这篇文档就行了。

包括 #426

@hi-zhaolei
Copy link

@afc163 我看过文档了,我看第一个约定就是工厂第一个参数必须为require,我这边不用require也可以应该是什么原因导致的呢?cmd压缩也说要保留require关键字,但是grunt打包没有保留require也一切正常。

@hi-zhaolei
Copy link

@afc163 还是没找到答案,提点一两下被

@afc163
Copy link
Member

afc163 commented Apr 18, 2014

压缩操作。经过上面的提取操作后,构建工具就可以调用任何 JS 压缩工具来进行压缩了,require 参数也可以被压缩成任意字符。


由于各种原因,暂时无法使用 Sea.js 配套的构建工具来压缩时 ... 压缩时,不要压缩 require 参数 ... 或者自己写工具来保证 id 和 dependencies 的预先提取。

@hi-zhaolei
Copy link

@afc163 这个我知道,问题是你看我的截图,我没提取id和依赖,没有压缩,依然可以直接使用第一个参数,这是为什么....但是在另一个项目,确实修改require无法正确加载,提取id和依赖后解析正常,我想知道截图这种情况是怎么导致的

@afc163
Copy link
Member

afc163 commented Apr 18, 2014

把 require 改为 e 后,如果也没有提前提取依赖数组的话,seajs 无法提前获取本模块的依赖,就不会去载入 jQuery 和 underscore,这样你的逻辑很可能就跑不通了。

但是如果你在别的代码里恰好提前定义了 jQuery 和 underscore 的话。那么这个改了名的 require 作为一个正常的函数,依然可以去拿到已定义的 jQuery 和 underscore,这个功能是没有变化的。

改名后,缺少的只是提前读取依赖的特性。

当然,上面的恰好是一个不推荐的应用场景,也不符合模块化的定义,建议安装 seajs 推荐的方式来进行书写和打包。

@hi-zhaolei
Copy link

@afc163 截图这个模块就是整个项目的入口,之前没有定义过jquery之类的东西.....我log打印出来第一个参数,不管是不是require结果都一样,应该不提前获取模块依赖,也可以请求加载吧,问题是现在的项目,修改require就解析错误,exec解析失败,why,好奇怪.....

@afc163
Copy link
Member

afc163 commented Apr 18, 2014

不提前获取模块依赖,就不会请求加载。

之前要是没定义过 jQuery 之类的,那么第一个 require (e) 的地方肯定就报错了。

空说无凭,上线上能访问的静态 demo 吧。

@liudan92221
Copy link

我估计里面肯定是用了toStrng()把方法里面的require提出来进行模块id解析的,等会去看看源码。

@zhishaofei3
Copy link

比如说我有一个placeholder模块 用来在IE8以下浏览器模拟placeholder
我在入口文件里 我需要根据浏览器来决定是否require("placeholder")
用if和else不行 用动态加载貌似也不行 因为下面马上会用placeholder里面的方法了啊

@zhishaofei3
Copy link

@iamweilee 那我这种情景 还有办法优化吗 chrome下也要加载这个js了?但是我压根没用它

@southwhale
Copy link

那你就用异步require吧,然后在回调里写业务逻辑,具体你看看seajs的demo

@szlijia
Copy link

szlijia commented Aug 26, 2014

使用require 火狐浏览器出现卡死的情况,这是我使用的方法不对吗?
define(function(require) {
"use strict";
window.$ = window.jQuery = $ = require('jquery');
require('layer/layer.min');

出现卡死

@saraOrg
Copy link

saraOrg commented Sep 12, 2014

哇 这么多人回复了!

@jsCONFIG
Copy link

jsCONFIG commented Oct 8, 2014

这个直接字符串是不是为了用于打包时候的匹配检测啊?

@Grantlv
Copy link

Grantlv commented Dec 4, 2014

大神,我想问一个seajs的require 和nodejs的require 的问题。虽然前者是前端,后者是服务器,但是有没有考虑到node-webkit? 如果我在node-webkit 桌面应用项目中用nodejs和seajs 他们的require是不是会冲突?

@wangxian
Copy link

wangxian commented Dec 4, 2014

@grantSeajs

Sea.js 的 require 是一个形参,node-webkit的 require 是全局的,不影响。
对于 requirejs, node-webkit 的 wiki 上提供了官方的解决方案
见:https://github.com/rogerwang/node-webkit/wiki/faq-name-conflict

@meiyouqing
Copy link

define("base/easing/1.3.0/easing", ["jquery"], function(require) {
var jQuery = require("jquery");
...
})
请问为什么浏览器提示“jQuery”是null了?路径都没有错,jquery也顺利加载了
还要我只要用var $ = require('jquery');,就会提示“$()"为object is not a function

@sky-620
Copy link

sky-620 commented Mar 12, 2015

用require加载一个文件,然后new的时候报错

我的代码是这样的
require('charts/component/colorFac');
var color = new gradientColor('#013548','#554851',10);

colorFac文件为是这样的
(function(win){
function gradientColor(startColor,endColor,step){
.....
}
gradientColor.prototype.colorRgb = function(sColor){
......
};
.....
})(window);

然后总是报错,gradientColor is not defined。我不清楚这是什么原因,看着colorFac.js文件已经加载了~~

我想知道这是为啥呢?难道colorFac非得按照seajs的写法写?还是new的时候,colorFac.js文件没加载?

@hi-zhaolei
Copy link

@helloqinqin 一般不会有这种情况发生,gradientColor is not defined说明全局肯定没有这个类存在,你得先确定库文件内部对外的接口是如何处理的,可能是进行过模块化的兼容,试试gradientColor=require('charts/component/colorFac');获取文件对外的api。还不行的话,确认一下gradientColor类名是否正确

@sky-620
Copy link

sky-620 commented Mar 12, 2015

@ZLStone
首先谢谢了~
1.确定及肯定名字没错~
2.gradientColor=require('charts/component/colorFac'); 断点,gradientColor为空
3.从sources可以看到colorFac.js是加载了的

不过没有对colorFac.js用defined模块化。我想着,这个也不能强制要那么写的

@hi-zhaolei
Copy link

@helloqinqin 不需要强制写,至少我用的2.1.0不需要,还是文件本身的问题,如果确定加载成功,全局没有,看看文件代码吧...

@sky-620
Copy link

sky-620 commented Mar 13, 2015

@ZLStone
1.我按照define进行模块化了,并且把colorFac.js中的gradientColor方法前面的g大写了,然后就能行了~

2.我又把colorFac.js按照原来的,并且把gradientColor方法前面的g大写了,还是不行

我的seajs是2.3.0 具体什么原因还得多做实验,才能得出啊

@zhs23
Copy link

zhs23 commented Mar 16, 2015

这种是不是以后加反射来处理了

@tiny-component
Copy link

用$=require('jquery')时,为什么alert($)返回的是null

@tbx19930222
Copy link

希望有大牛帮我解答一下,为什么在safari浏览器下http://www.51go.me/加载的这么慢,是seajs的原因吗,有几个js我是require进来的

@xxiiaass
Copy link

第一个参数'require',在压缩时候会改名,导致无法正常执行,有什么好的办法吗

@virtuecai
Copy link

@xxiiaass 同问

@catFishTail
Copy link

IE10 如果用require加载模块会得到结果NULL,这里指的不是jquery,而是项目里面的其他JS文件。

@zengxiaoluan
Copy link

zengxiaoluan commented Jan 8, 2019

第一个参数'require',在压缩时候会改名,导致无法正常执行,有什么好的办法吗

require 关键字不压缩或者提前把依赖声明:

define('file:///D:/zengxiaoluan/learn_seajs/dist/foo.js', ['file:///D:/zengxiaoluan/learn_seajs/dist/bar.js', 'https://vuejs.org/js/vue.min.js'], function(require, exports, module) {
  var bar = require('file:///D:/zengxiaoluan/learn_seajs/dist/bar.js');

  new Vue({
    el: '#app',
    data: {
      msg: bar.bar()
    }
  });

  require('https://vuejs.org/js/vue.min.js');

  module.exports = 'foo';
});

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

No branches or pull requests