-
Notifications
You must be signed in to change notification settings - Fork 171
WebServer
EDP自带了一个小型的WebServer
,用于前端开发时的调试工作。
注意:该WebServer
设计时并未充分考虑抗压性和健壮性, 不得 用于线上服务。
通过下面的命令,将根据默认的配置文件,启动WebServer
。在默认
情况下,WebServer
使用8848
端口,并且将当前目录
做为DocumentRoot。
$ edp webserver start
edp INFO EDP WebServer start, http://192.168.1.105:8848
edp INFO root = [/Users/errorrik/test], listen = [8848]
在Linux/Mac环境下,可以使用edp webserver start &
,使其在后台运行,以便可以继续使用命令行。通过jobs -l
命令可以查看哪些东西在后台运行。
通过--port
参数,可以指定WebServer
的监听端口。
$ edp webserver start --port 8888
edp INFO EDP WebServer start, http://192.168.1.105:8888
edp INFO root = [/Users/errorrik/test], listen = [8888]
通过--config
参数,可以指定WebServer
的配置文件。
$ edp webserver start --config=ws-config.js
edp INFO EDP WebServer start, http://192.168.1.105:8898
edp INFO root = [/Users/cire/tttt/src], listen = [8898]
运行edp webserver start
时,默认使用的配置文件
为当前目录下的edp-webserver-config.js
。如果该文件不存在,将使用默认配置
。你可以新建一个edp-webserver-config.js
,或者使用其他文件名,在运行命令时通过--config
参数指定。
配置文件是一个node module
,EDP在WebServer
启动前将require
它,所以,配置文件后缀必须为.js
。
下面是EDP的构建默认配置。通过edp提供的项目管理功能来初始化项目
时,生成的edp-webserver-config.js
与此可能不同。
exports.port = 8848;
exports.directoryIndexes = true;
exports.documentRoot = __dirname;
exports.getLocations = function () {
return [
{
location: /\/$/,
handler: home( 'index.html' )
},
{
location: /^\/redirect-local/,
handler: redirect('redirect-target', false)
},
{
location: /^\/redirect-remote/,
handler: redirect('http://www.baidu.com', false)
},
{
location: /^\/redirect-target/,
handler: content('redirectd!')
},
{
location: '/empty',
handler: empty()
},
{
location: /\.css($|\?)/,
handler: [
autoless()
]
},
{
location: /\.less($|\?)/,
handler: [
file(),
less()
]
},
{
location: /^.*$/,
handler: [
file(),
proxyNoneExists()
]
}
];
};
exports.injectResource = function ( res ) {
for ( var key in res ) {
global[ key ] = res[ key ];
}
};
我们建议:通过edp提供的项目管理功能来初始化项目
,在其生成的edp-webserver-config.js
上进行WebServer
配置自定义。
在自定义自己的WebServer
配置时,有下面几个东西需要了解和注意:
监听端口号。为了防止和其他常用的WebServer
冲突,默认为8848,不为80或8080。
是否允许显示目录下的文件索引。
WebServer
使用的文档根目录。默认为配置文件
所在的当前目录。
该方法用于EDP将内置的资源处理函数
注入到配置模块中,从而在配置模块里可以使用内置资源处理函数
。请保持该方法的存在,并使用默认实现,不要修改它。
该方法返回一个数组,数组的每一项是一个具有location
和handler
的Object
,代表能被location
匹配上的资源,使用handler
进行处理。
location
可以是一个string
,也可以是一个RegExp
。
handler
可以是一个资源处理函数function({Object}context)
,也可以是一个包含多个资源处理函数的数组Array.function({Object}context)
。你可以使用EDP WebServer
自带的资源处理函数,也可以自己编写一个Javascript Function做为资源处理函数。
详细了解资源处理函数
,请阅读接下来的两个章节。
EDP WebServer
在请求到来时,将请求和应答封装成一个context
对象。在资源处理阶段,EDP WebServer
将这个context
对象传递给资源处理函数,资源处理函数通过操作这个context
对象,来达到各种目的:输出相应的http状态码
、输出相应的内容
、输出相应的请求头
等。
所以,资源处理函数应该是类似如下的形式:
function error(context) {
context.status = 500;
}
context
对象包含如下内容:
-
request
: 请求对象,可以从该对象上获得用户请求信息 -
response
: 响应对象,不建议直接操作该对象 -
status
: 状态码 -
content
: 响应体的内容 -
header
: 响应头内容 -
end
: function,调用该函数将终结对请求的响应 -
stop
: 资源处理暂停。如果资源处理为异步时,需要调用该函数,让处理链暂停 -
start
: 资源处理开始。如果资源处理为异步,当处理完成时,需要调用该函数,让处理链启动,继续向下走
通常,在资源处理函数中,我们可能会这样操作context
对象:
- 添加响应头:
context.header['Content-Type'] = 'text/javascript'
- 设置响应内容:
context.content = JSON.stringify(jsonData)
- 设置返回状态码:
context.status = 404
- 读取请求信息:
context.request.pathname
EDP内置了一些资源处理函数
,可以满足对常见资源的处理。下面列举一些常用的内置资源处理函数
。
file接受一个参数 @param {string} file
,如果指定了文件,会渲染指定文件,否则会根据请求的路径输出文件内容。
- 如果
pathname
是一个目录,会调用listDirectory
输出当前目录文件列表 - 如果
pathname
是一个文件,直接输出文件内容
两种情况都会以config中配置的documentRoot
作为根目录。
参数:
-
file
: {string} 指定的输出文件
{
location: /^.*$/,
handler: file()
}
直接输出指定固定内容。
参数:
-
content
: {string} 输出内容
{
location: '/hello',
handler: content('Hello World!')
}
设置指定的response header,新设置的头会覆盖context.header
中已有的项。
参数:
-
header
: {Object} response header
{
location: /^.*$/,
handler: header({'x-copyright': 'your name'})
}
输出固定Content-Type头,会覆盖已有的content-type
的值。
参数:
-
contentType
: 返回的contentType的值
{
location: /^.*$/,
handler: contentType('text/plain')
}
将数据按JSON格式输出,将自动设置为JSON的Content-Type
参数:
-
data
: 需要返回的data
{
location: '/data',
handler: json({
// ...
})
}
将JSON数据按jsonp的方式输出,将自动设置为JS的Content-Type
参数:
-
data
: 需要返回的参数,如果JSON.stringify
失败,则使用context.content代替 -
callbackKey
: 回调函数名在url中的key值,默认使用callback
{
location: '/data',
handler: jsonp(
{
// ...
},
'callbackFunction'
)
}
打印请求信息,打印的内容包括:
-
url
: request.url -
method
: request.method -
httpVersion
: request.httpVersion -
protocol
: request.protocol -
host
: request.host -
auth
: request.auth -
hostname
: request.hostname -
port
: request.port -
search
: request.search -
hash
: request.hash -
headers
: request.headers -
query
: request.query -
body
: request.bodyBuffer
{
location: /^.*$/,
handler: dumpRequest()
}
重定向,根据permanent决定返回头是302还是301
参数:
-
location
: 重定向地址 -
permanent
: 是否永久,如果是永久,则status code是301,否则是302
{
location: '/',
handler: redirect('/404')
}
对context.content
进行less编译
参数:
-
compileOptions
: less编译参数 -
encoding
: 源编码方式
{
location: /\.less($|\?)/,
handler: [
file(),
less()
]
}
对css资源的请求,自动查找相应的同名less文件,并编译输出
参数:
-
compileOptions
: less编译参数 -
encoding
: 源编码方式
{
location: /\.css($|\?)/,
handler: [
autoless()
]
}
对context.content
进行stylus编译
参数:
-
compileOptions
: less编译参数 -
encoding
: 源编码方式
{
location: /\.styl($|\?)/,
handler: [
file(),
stylus()
]
}
对css资源的请求,自动查找相应的同名stylus文件,并编译输出
参数:
-
compileOptions
: less编译参数 -
encoding
: 源编码方式
{
location: /\.css($|\?)/,
handler: [
autostylus()
]
}
对css资源的请求,自动查找相应的同名stylus或者less文件,并编译输出,autostylus和autoless都是基于autocss实现
参数:
-
compileOptions
: less编译参数 -
encoding
: 源编码方式
{
location: /\.css($|\?)/,
handler: [
autocss()
]
}
对context.content
进行coffee编译
{
location: /\.coffee($|\?)/,
handler: [
file(),
coffee()
]
}
对js资源的请求,自动查找相应的同名coffee文件,并编译输出
参数:
-
encoding
: 源编码方式
{
location: /\.js($|\?)/,
handler: [
autocoffee()
]
}
处理对php文件的请求,当前只处理url后缀是php的请求,根据当前pathname找到php文件,调用php-cgi,输出执行后的内容
参数:
-
opt_handler
: php-cgi可执行文件的路径,默认为path中的php-cgi -
opt_suffix
: 文件后缀名(当前不可用) -
opt_forwardPathName
: 函数,将此函数的返回值作为php文件的路径
{
location: /\.php($|\?)/,
handler: [
php()
]
}
后端代理当前请求,转发到对应的主机上
参数:
-
hostname
: 主机名,可为域名或者IP -
port
: 端口,默认80
{
location: /\.js($|\?)/,
handler: proxy('127.0.0.1', '8081')
}
如果当前context.status
等于404时,代理转发当前请求
查找config中的proxyMap,如果配置有如下:
exports.proxyMap = {
'127.0.0.1:8080': 'www.baidu.com:80'
};
则会把127.0.0.1:8080的请求代理到www.baidu.com:80
{
location: /^.*$/,
handler: [
file(),
proxyNoneExists()
]
}
如下示例中的配置会将html2js.js
的文件定位到html2js
文件,并调用html2js转化为js文件输出
参数:
-
compileOptions
: 编译参数 -
encoding
: 源编码方式
{
location: /\.js($|\?)/,
handler: html2js()
}
在html代码的body结束标签前增加下面一个script标签
<script src="http://{options.ip}:{options.port}/livereload.js"></script>
参数:
-
options
: LiveReload的参数 -
options.ip
: LiveReload服务器的IP地址,默认为当前机器的ip地址 -
options.port
: LiveReload服务器的端口号,默认为8898 -
options.encoding
: 文件编码,默认为utf-8
输出指定的dir目录或者当前请求的pathname对应的目录下的文件列表
参数:
-
dir
: 指定路径,默认为当前请求的pathname
{
location: /\/$/,
handler: listDirectory()
}
配合Proxy Handler使用,添加一些自定义的Request Header
参数:
-
headers
: 自定义请求头
{
location: /\.js($|\?)/,
handler: [
addRequestHeader({
'host': 'www.baidu.com'
}),
proxy()
]
}
输出当前context的内容,并结束请求
注意:write对一般开发者来说不要去使用,edp webserver会默认在handlers的最后面增加一个write handler,如果开发者调用的write,最后面一个write handler执行的时候会报错
主索引页
查找当前pathname路径下的指定索引文件,如果没找到,则使用listDirectory
来作为输出
参数:
-
file
: {string|Array} 主索引文件,如果是数组,则从0开始寻找可用的主索引文件,找到了一个会忽略其他的文件
{
location: '/',
handler: home('index.html')
}
延迟输出
参数:
-
time
: 延迟输出的时间,单位为ms
{
location: '/hello',
handler: [
content('Hello World!'),
delay(500)
]
}
输出空内容
{
location: '/empty',
handler: empty()
}
当内置的资源处理函数无法满足自己需求的时候,也可以很方便的添加一个自定义的资源处理函数。假定我们希望将符合POST /data/***
特征的请求以mockup数据返回,但是mockup的数据放在src/mockup
目录下面,那么我们可以添加一个自己的处理函数mockup
,同时配合file
来完成这个工作。
exports.getLocations = function () {
return [
...
{
location: /^\/data\//,
handler: [
mockup(),
file()
]
},
...
];
}
其中mockup
的实现很简单,就是把pathname
的内容修改一下,后续交给file
处理即可。
function mockup() {
return function( context ){
var pathname = context.request.pathname;
context.request.pathname = '/src/mockup/' + pathname + '.json';
}
}