Skip to content
leeight edited this page Apr 9, 2014 · 5 revisions

EDP自带了一个小型的WebServer,用于前端开发时的调试工作。

注意:该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]

指定WebServer配置文件

通过--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]

配置WebServer

运行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配置时,有下面几个东西需要了解和注意:

port

监听端口号。为了防止和其他常用的WebServer冲突,默认为8848,不为80或8080。

directoryIndexes

是否允许显示目录下的文件索引。

documentRoot

WebServer使用的文档根目录。默认为配置文件所在的当前目录。

injectResource

该方法用于EDP将内置的资源处理函数注入到配置模块中,从而在配置模块里可以使用内置资源处理函数。请保持该方法的存在,并使用默认实现,不要修改它。

getLocations

该方法返回一个数组,数组的每一项是一个具有locationhandlerObject,代表能被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

file接受一个参数 @param {string} file,如果指定了文件,会渲染指定文件,否则会根据请求的路径输出文件内容。

  1. 如果pathname是一个目录,会调用listDirectory输出当前目录文件列表
  2. 如果pathname是一个文件,直接输出文件内容

两种情况都会以config中配置的documentRoot作为根目录。

参数:

  • file: {string} 指定的输出文件
{
    location: /^.*$/,
    handler: file()
}

content

直接输出指定固定内容。

参数:

  • content: {string} 输出内容
{
    location: '/hello',
    handler: content('Hello World!')
}

header

设置指定的response header,新设置的头会覆盖context.header 中已有的项。

参数:

  • header: {Object} response header
{
    location: /^.*$/,
    handler: header({'x-copyright': 'your name'})
}

contentType

输出固定Content-Type头,会覆盖已有的content-type的值。

参数:

  • contentType: 返回的contentType的值
{
    location: /^.*$/,
    handler: contentType('text/plain')
}

json

将数据按JSON格式输出,将自动设置为JSON的Content-Type

参数:

  • data: 需要返回的data
{
    location: '/data',
    handler: json({
        // ...
    })
}

jsonp

将JSON数据按jsonp的方式输出,将自动设置为JS的Content-Type

参数:

  • data: 需要返回的参数,如果JSON.stringify失败,则使用context.content代替
  • callbackKey: 回调函数名在url中的key值,默认使用callback
{
    location: '/data',
    handler: jsonp(
        {
            // ...
        },
        'callbackFunction'
    )
}

dumpRequest

打印请求信息,打印的内容包括:

  • 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()
}

redirect

重定向,根据permanent决定返回头是302还是301

参数:

  • location: 重定向地址
  • permanent: 是否永久,如果是永久,则status code是301,否则是302
{
    location: '/',
    handler: redirect('/404')
}

less

context.content进行less编译

参数:

  • compileOptions: less编译参数
  • encoding: 源编码方式
{
    location: /\.less($|\?)/,
    handler: [
        file(),
        less()
    ]
}

autoless

对css资源的请求,自动查找相应的同名less文件,并编译输出

参数:

  • compileOptions: less编译参数
  • encoding: 源编码方式
{
    location: /\.css($|\?)/,
    handler: [
        autoless()
    ]
}

stylus

context.content进行stylus编译

参数:

  • compileOptions: less编译参数
  • encoding: 源编码方式
{
    location: /\.styl($|\?)/,
    handler: [
        file(),
        stylus()
    ]
}

autostylus

对css资源的请求,自动查找相应的同名stylus文件,并编译输出

参数:

  • compileOptions: less编译参数
  • encoding: 源编码方式
{
    location: /\.css($|\?)/,
    handler: [
        autostylus()
    ]
}

autocss

对css资源的请求,自动查找相应的同名stylus或者less文件,并编译输出,autostylus和autoless都是基于autocss实现

参数:

  • compileOptions: less编译参数
  • encoding: 源编码方式
{
    location: /\.css($|\?)/,
    handler: [
        autocss()
    ]
}

coffee

context.content进行coffee编译

{
    location: /\.coffee($|\?)/,
    handler: [
        file(),
        coffee()
    ]
}

autocoffee

对js资源的请求,自动查找相应的同名coffee文件,并编译输出

参数:

  • encoding: 源编码方式
{
    location: /\.js($|\?)/,
    handler: [
        autocoffee()
    ]
}

php

处理对php文件的请求,当前只处理url后缀是php的请求,根据当前pathname找到php文件,调用php-cgi,输出执行后的内容

参数:

  • opt_handler: php-cgi可执行文件的路径,默认为path中的php-cgi
  • opt_suffix: 文件后缀名(当前不可用)
  • opt_forwardPathName: 函数,将此函数的返回值作为php文件的路径
{
    location: /\.php($|\?)/,
    handler: [
        php()
    ]
}

proxy

后端代理当前请求,转发到对应的主机上

参数:

  • hostname: 主机名,可为域名或者IP
  • port: 端口,默认80
{
    location: /\.js($|\?)/,
    handler: proxy('127.0.0.1', '8081')
}

proxyNoneExists

如果当前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

如下示例中的配置会将html2js.js的文件定位到html2js文件,并调用html2js转化为js文件输出

参数:

  • compileOptions: 编译参数
  • encoding: 源编码方式
{
    location: /\.js($|\?)/,
    handler: html2js()
}

livereload

在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

listDirectory

输出指定的dir目录或者当前请求的pathname对应的目录下的文件列表

参数:

  • dir: 指定路径,默认为当前请求的pathname
{
    location: /\/$/,
    handler: listDirectory()
}

addRequestHeader

配合Proxy Handler使用,添加一些自定义的Request Header

参数:

  • headers: 自定义请求头
{
    location: /\.js($|\?)/,
    handler: [
        addRequestHeader({
            'host': 'www.baidu.com'
        }),
        proxy()
    ]
}

write

输出当前context的内容,并结束请求

注意:write对一般开发者来说不要去使用,edp webserver会默认在handlers的最后面增加一个write handler,如果开发者调用的write,最后面一个write handler执行的时候会报错

home

主索引页

查找当前pathname路径下的指定索引文件,如果没找到,则使用listDirectory来作为输出

参数:

  • file: {string|Array} 主索引文件,如果是数组,则从0开始寻找可用的主索引文件,找到了一个会忽略其他的文件
{
    location: '/',
    handler: home('index.html')
}

delay

延迟输出

参数:

  • time: 延迟输出的时间,单位为ms
{
    location: '/hello',
    handler: [
        content('Hello World!'),
        delay(500)
    ]
}

empty

输出空内容

{
    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';
    }
}