[TOC]
网站托管是云引擎的一个子模块,允许你用 Node.js 开发一个 Web 程序,提供云函数和 Hook,还可以提供静态文件的托管和自定义的路由、绑定你自己的域名。你可以用它为你的移动应用提供一个介绍和下载页、开发一个管理员控制台或完整的网站,或者运行一些必须在服务器端运行的自定义逻辑。
如果你还不知道如何创建云引擎项目,本地调试并部署到云端,可以先阅读一下 [云引擎快速入门](https://leancloud.cn/docs/leanengine_quickstart.html)。其他相关文档包括:
* [云引擎服务概览](https://leancloud.cn/docs/leanengine_overview.html)(全部功能的概述)
* [命令行工具使用指南](https://leancloud.cn/docs/leanengine_cli.html)
* [LeanCache 使用指南](https://leancloud.cn/docs/leancache_guide.html)(使用内存缓存服务来提升性能)
* [云引擎项目示例](https://leancloud.cn/docs/leanengine_examples.html)
* [云引擎常见问题和解答](https://leancloud.cn/docs/leanengine_faq.html)
这篇文档以 Node.js 为例,但云引擎还支持其他多种语言,你可以选择自己熟悉的技术栈进行开发:
* [Node.js]()
* [Python](https://leancloud.cn/docs/leanengine_webhosting_guide-python.html)
* [PHP](https://leancloud.cn/docs/leanengine_webhosting_guide-php.html)
* [Java](https://leancloud.cn/docs/leanengine_webhosting_guide-java.html)
## [项目骨架](#项目骨架)
你的项目根目录项目 必须 有一个 `package.json` 文件,才会正确地被云引擎识别为 Node.js 项目。
因为一些历史遗留问题,请确保你的项目中 没有 名为 `cloud/main.js` 的文件。
### [package.json](#package_json)
Node.js 的 `package.json` 中可以指定 [很多选项](https://docs.npmjs.com/files/package.json),它通常看起来是这样:
~~~
{
"name": "node-js-getting-started",
"scripts": {
"start": "node server.js"
},
"engines": {
"node": "4.x"
},
"dependencies": {
"express": "4.12.3",
"leanengine": "1.2.2"
}
}
~~~
其中云引擎会尊重的选项包括:
* `scripts.start` 启动项目时使用的命令;默认为 `node server.js`,如果你希望为 node 附加启动选项(如 `--es_staging`)或使用其他的文件作为入口点,可以修改该选项。
* `scripts.prepublish` 会在项目部署最后运行一次;可以将构建命令(如 `gulp build`)写在这里。
* `engines.node` 指定所需的 Node.js 版本;出于兼容性考虑默认版本仍为比较旧的 `0.12`,因此建议大家自行指定一个更高的版本,建议使用 `4.x` 版本进行开发,你也可以设置为 `*` 表示总是使用最新版本的 Node.js。
* `dependencies` 项目所依赖的包;云引擎会在部署时用 `npm install --production` 为你安装这里列出的所有依赖。
* `devDependencies` 项目开发时所依赖的包;云引擎目前 不会 安装这里的依赖。
建议你参考我们的 [项目模板](https://github.com/leancloud/node-js-getting-started/blob/master/package.json) 来编写自己的 `package.json`。
### [健康监测](#健康监测)
你的应用在启动时,云引擎的管理程序会每秒去检查你的应用是否启动成功,如果 30 秒 仍未启动成功,即认为启动失败;在之后应用正常运行的过程中,也会有定期的「健康监测」,以确保你的应用正常运行,如果健康监测失败,云引擎管理程序会自动重启你的应用。
健康检查的 URL 包括你的应用首页(`/`)和 Node.js SDK 负责处理的 `/__engine/1/ping`,只要 两者之一 返回了 HTTP 200 的响应,就视作成功。因此请确保你的程序使用了 Node.js SDK,或你的应用 首页能够正常地返回 HTTP 200 响应。
除此之外,为了支持云引擎的云函数和 Hook 功能,管理程序会使用 `/1.1/functions/_ops/metadatas` 这个 URL 和 Node.js SDK 交互,请确保将这个 URL 交给 Node.js SDK 处理,或 返回一个 HTTP 404 表示不使用云函数 和 Hook 相关的功能。
关于如何加载 Node.js SDK,见下面的 [Web 框架](#Web_框架) 和 [LeanCloud SDK](#LeanCloud_SDK) 小节。
## [Web 框架](#Web_框架)
Node SDK 为 [express](http://expressjs.com/) 和 [koa](http://koajs.com/) 提供了集成支持,如果你使用这两个框架,只需通过下面的方式加载 Node SDK 提供的中间件即可。
你可以在你的项目根目录运行 `npm install leanengine@next --save` 来安装 Node SDK。
### [Express](#Express)
~~~
var express = require('express');
var AV = require('leanengine');
AV.init({
appId: process.env.LEANCLOUD_APP_ID || 'csXFgnEzBkodigdDUARBrEse-gzGzoHsz',
appKey: process.env.LEANCLOUD_APP_KEY || 'K2CE4ChmGnUwI8mMBgTRHw7y',
masterKey: process.env.LEANCLOUD_APP_MASTER_KEY || 'l3fwovKapDmHHC6lDHNfJhR5'
});
var app = express();
app.use(AV.express());
app.listen(process.env.LEANCLOUD_APP_PORT);
~~~
你可以使用 express 的路由定义功能来提供自定义的 HTTP API:
~~~
app.get('/', function(req, res) {
res.render('index', {title: 'Hello world'});
});
app.get('/time', function(req, res) {
res.json({
time: new Date()
});
});
app.get('/todos', function(req, res) {
new AV.Query('Todo').find().then(function(todos) {
res.json(todos);
}).catch(function(err) {
res.status(500).json({
error: err.message
});
});
});
~~~
更多最佳实践请参考我们的 [项目模板](https://github.com/leancloud/node-js-getting-started) 和 [云引擎项目示例](https://leancloud.cn/docs/leanengine_examples.html)。
### [Koa](#Koa)
~~~
var koa = require('koa');
var AV = require('leanengine');
AV.init({
appId: process.env.LEANCLOUD_APP_ID || 'csXFgnEzBkodigdDUARBrEse-gzGzoHsz',
appKey: process.env.LEANCLOUD_APP_KEY || 'K2CE4ChmGnUwI8mMBgTRHw7y',
masterKey: process.env.LEANCLOUD_APP_MASTER_KEY || 'l3fwovKapDmHHC6lDHNfJhR5'
});
var app = koa();
app.use(AV.koa());
app.listen(process.env.LEANCLOUD_APP_PORT);
~~~
你可以使用 koa 来渲染页面、提供自定义的 HTTP API:
~~~
app.use(function *(next) {
if (this.url === '/') {
// https://github.com/tj/co-views
yield coViews('views')('index', {title: 'Hello world'});
} else {
yield next;
}
});
app.use(function *(next) {
if (this.url === '/time') {
this.body = {
time: new Date()
};
} else {
yield next;
}
});
app.use(function *(next) {
if (this.url === '/todos') {
return new AV.Query('Todo').find().then(todos => {
this.body = todos;
});
} else {
yield next;
}
});
~~~
使用 Koa 时建议按照前面 [package.json](#package_json) 一节将 Node.js 的版本设置为 `4.x` 以上。
### [其他 Web 框架](#其他_Web_框架)
你也可以使用其他的 Web 框架进行开发,但你需要自行去实现 [健康监测](#健康监测) 中提到的逻辑。下面是一个使用 Node.js 内建的 [http](https://nodejs.org/api/http.html) 实现的最简示例,可供参考:
~~~
require('http').createServer(function(req, res) {
if (req.url == '/') {
res.statusCode = 200;
res.end();
} else {
res.statusCode = 404;
res.end();
}
}).listen(process.env.LEANCLOUD_APP_PORT);
~~~
## [LeanCloud SDK](#LeanCloud_SDK)
云引擎中的 Node SDK 是对 [JavaScript 存储 SDK](https://github.com/leancloud/javascript-sdk) 的拓展,增加了服务器端需要的云函数和 Hook 相关支持,在云引擎中你需要用 `leanengine` 这个包来操作 [LeanCloud 的存储服务](https://leancloud.cn/docs/leanstorage_guide-js.html) 中的数据,你可以在你的项目根目录运行 `npm install leanengine@next --save` 来安装 Node SDK。
Node SDK 的 [API 文档](https://github.com/leancloud/leanengine-node-sdk/blob/master/API.md) 和 [更新日志](https://github.com/leancloud/leanengine-node-sdk/releases) 都在 GitHub 上。
~~~
var AV = require('leanengine');
AV.init({
appId: process.env.LEANCLOUD_APP_ID || 'csXFgnEzBkodigdDUARBrEse-gzGzoHsz',
appKey: process.env.LEANCLOUD_APP_KEY || 'K2CE4ChmGnUwI8mMBgTRHw7y',
masterKey: process.env.LEANCLOUD_APP_MASTER_KEY || 'l3fwovKapDmHHC6lDHNfJhR5'
});
// 你可以使用 useMasterKey 在云引擎中开启 masterKey 权限,将会跳过 ACL 和其他权限限制。
AV.Cloud.useMasterKey();
// 使用 JavaScript 的 API 查询云存储中的数据。
new AV.Query('Todo').find().then(function(todos) {
console.log(todos);
}).catch(function(err) {
console.log(err)
});
~~~
Node SDK 有过两个大版本:
* `0.x`:最初的版本,对 Node.js 4.x 及以上版本兼容不佳,建议用户参考 [升级到云引擎 Node.js SDK 1.0](https://leancloud.cn/docs/leanengine-node-sdk-upgrade-1.html) 来更新
* `1.x`:推荐使用 的版本,彻底废弃了全局的 currentUser,依赖的 JavaScript 也升级到了 1.x 分支,支持了 Koa 和 Node.js 4.x 及以上版本。
## [本地运行和调试](#本地运行和调试)
在你首次启动应用之前需要先安装依赖:
~~~
npm install
~~~
然后便可以在项目根目录,用我们的命令行工具来启动本地调试了:
~~~
lean up
~~~
更多有关命令行工具和本地调试的内容请看 [命令行工具使用指南](https://leancloud.cn/docs/leanengine_cli.html)。
## [部署](#部署)
### [命令行部署](#命令行部署)
在你的项目根目录运行:
~~~
lean deploy
~~~
使用命令行工具可以非常方便地部署、发布应用,查看应用状态,查看日志,甚至支持多应用部署。具体使用请参考 [命令行工具指南](https://leancloud.cn/docs/leanengine_cli.html)。
### [Git 部署](#Git_部署)
除此之外,还可以使用 git 仓库部署。你需要将项目提交到一个 git 仓库,我们并不提供源码的版本管理功能,而是借助于 git 这个优秀的分布式版本管理工具。我们推荐你使用 [GitHub](https://github.com/)、[Coding](https://coding.net/) 或者 [OSChina](http://git.oschina.net/) 这样第三方的源码托管网站,也可以使用你自己搭建的 git 仓库(比如 [Gitlab](http://gitlab.org/))。
你需要先在这些平台上创建一个项目(如果已有代码,请不需要选择「Initialize this repository with a README」),在网站的个人设置中填写本地机器的 SSH 公钥(以 GitHub 为例,在 Settings => SSH and GPG keys 中点击 New SSH key),然后在项目目录执行:
~~~
git remote add origin git@github.com:<username>/<repoName>.git
git push -u origin master
~~~
然后到云引擎的设置界面填写你的 Git 仓库地址,如果是公开仓库建议填写 https 地址,例如 `https://github.com/<username>/<repoName>.git`。
如果是私有仓库需要填写 ssh 地址 `git@github.com:<username>/<repoName>.git`,还需要你将云引擎分配给你的公钥填写到第三方托管平台的 Deploy keys 中,以 GitHub 为例,在项目的 Settings => Deploy keys 中点击 Add deploy key。
设置好之后,今后需要部署代码时就可以在云引擎的部署界面直接点击「部署」了,默认会部署 master 分支的代码,你也可以在部署时填写分支、标签或具体的 Commit。
### [预备环境和生产环境](#预备环境和生产环境)
对于免费版应用,云引擎只有一个「生产环境」,对应的域名是 `{应用的域名}.leanapp.cn`。
升级到专业版后会有一个额外的「预备环境」,对应域名 `stg-{应用的域名}.leanapp.cn`,两个环境所访问的都是同样的数据,你可以用预备环境测试你的云引擎代码,每次修改先部署到预备环境,测试通过后再发布到生产环境;如果你希望有一个独立数据源的测试环境,建议单独创建一个应用。
如果访问云引擎遇到「No Application Configured」的错误,通常是因为对应的环境还没有部署代码。例如免费版应用没有预备环境,或专业版应用尚未发布代码到生产环境。
关于免费版和专业版的更多差别,请参考 [云引擎运行方案](https://leancloud.cn/docs/leanengine_plan.html)。
有些时候你可能需要知道当前云引擎运行在什么环境(开发环境、预备环境或生产环境),从而做不同的处理:
~~~
var NODE_ENV = process.env.NODE_ENV || 'development';
if (NODE_ENV === 'development') {
// 当前环境为「开发环境」,是由命令行工具启动的
} else if(NODE_ENV == 'production') {
// 当前环境为「生产环境」,是线上正式运行的环境
} else {
// 当前环境为「预备环境」
}
~~~
在客户端 SDK 调用云函数时,可以通过 REST API 的特殊的 HTTP 头 `X-LC-Prod` 来区分调用的环境。
* `X-LC-Prod: 0` 表示调用预备环境
* `X-LC-Prod: 1` 表示调用生产环境
客户端 SDK 都有类似于 `setProduction` 的方法,比如 [JavaScript SDK API 的 AV.setProduction(production)](https://leancloud.github.io/javascript-sdk/docs/AV.html#.setProduction),其中 `production` 设置为 `0` 则该 SDK 将请求预备环境;设置为 `1` 将请求生产环境,默认为 `1`。
### [设置域名](#设置域名)
你可以在 [云引擎 > 设置](https://leancloud.cn/cloud.html?appid=csXFgnEzBkodigdDUARBrEse-gzGzoHsz#/conf) 的「Web 主机域名」部分,填写一个自定义的二级域名,例如你设置了 `myapp`,那么你就可以通过我们的二级域名来访问你的网站了:
* `http://myapp.leanapp.cn`(中国区)
* `http://myapp.avosapps.us`(美国区)
DNS 可能需要等待几个小时后才能生效。
## [用户状态管理](#用户状态管理)
云引擎提供了一个 `AV.Cloud.CookieSession` 中间件,用 Cookie 来维护用户(`AV.User`)的登录状态,要使用这个中间件可以在 `app.js` 中添加下列代码:
~~~
app.use(AV.Cloud.CookieSession({ secret: 'my secret', maxAge: 3600000, fetchUser: true }));
~~~
Koa 需要添加一个 `framework: 'koa'` 的参数:
~~~
app.use(AV.Cloud.CookieSession({ framework: 'koa', secret: 'my secret', maxAge: 3600000, fetchUser: true }));
~~~
你需要传入一个 secret 用于签名 Cookie(必须提供),这个中间件会将 `AV.User` 的登录状态信息记录到 Cookie 中,用户下次访问时自动检查用户是否已经登录,如果已经登录,可以通过 `req.currentUser` 获取当前登录用户。
`AV.Cloud.CookieSession` 支持的选项包括:
* fetchUser:是否自动 fetch 当前登录的 AV.User 对象。默认为 false。 如果设置为 true,每个 HTTP 请求都将发起一次 LeanCloud API 调用来 fetch 用户对象。如果设置为 false,默认只可以访问 `req.currentUser` 的 `id`(`_User` 表记录的 ObjectId)和 `sessionToken` 属性,你可以在需要时再手动 fetch 整个用户。
* name:Cookie 的名字,默认为 `avos.sess`。
* maxAge:设置 Cookie 的过期时间。
在 Node SDK 1.x 之后我们不再允许通过 `AV.User.current()` 获取登录用户的信息(详见 [升级到云引擎 Node.js SDK 1.0](https://leancloud.cn/docs/leanengine-node-sdk-upgrade-1.html#废弃_currentUser)),而是需要你:
* 在云引擎方法中,通过 `request.currentUser` 获取用户信息。
* 在网站托管中,通过 `request.currentUser` 获取用户信息。
* 在后续的方法调用显示传递 user 对象。
你可以这样简单地实现一个具有登录功能的站点:
~~~
// 处理登录请求(可能来自登录界面中的表单)
app.post('/login', function(req, res) {
AV.User.logIn(req.body.username, req.body.password).then(function(user) {
res.saveCurrentUser(user); // 保存当前用户到 Cookie
res.redirect('/profile'); // 跳转到个人资料页面
}, function(error) {
//登录失败,跳转到登录页面
res.redirect('/login');
});
})
// 查看个人资料
app.get('/profile', function(req, res) {
// 判断用户是否已经登录
if (req.currentUser) {
// 如果已经登录,发送当前登录用户信息。
res.send(req.currentUser);
} else {
// 没有登录,跳转到登录页面。
res.redirect('/login');
}
});
// 登出账号
app.get('/logout', function(req, res) {
req.currentUser.logOut();
res.clearCurrentUser(); // 从 Cookie 中删除用户
res.redirect('/profile');
});
~~~
## [实现常见功能](#实现常见功能)
### [发送 HTTP 请求](#发送_HTTP_请求)
推荐使用 [request](https://www.npmjs.com/package/request) 这个第三方模块来完成 HTTP 请求。
安装 request:
~~~
npm install request --save
~~~
代码示例:
~~~
var request = require('request');
request({
method: 'POST',
url: 'http://www.example.com/create_post',
json: {
title: 'Vote for Pedro',
body: 'If you vote for Pedro, your wildest dreams will come true'
}
}, function(err, res, body) {
if (err) {
console.error('Request failed with response code ' + res.statusCode);
} else {
console.log(body);
}
});
~~~
### [获取客户端 IP](#获取客户端_IP)
如果你想获取客户端的 IP,可以直接从用户请求的 HTTP 头的 `x-real-ip` 字段获取,示例代码如下:
~~~
app.get('/', function(req, res) {
console.log(req.headers['x-real-ip']);
res.send(req.headers['x-real-ip']);
});
~~~
### [文件上传](#文件上传)
托管在 云引擎 的网站项目可以直接使用内置的 LeanCloud JavaScript SDK 的 API 文件相关的接口直接处理文件的上传。
假设前端 HTML 代码如下:
~~~
<form enctype="multipart/form-data" method="post" action="/upload">
<input type="file" name="iconImage">
<input type="submit" name="submit" value="submit">
</form>
~~~
然后配置应用使用 [multiparty](https://www.npmjs.com/package/multiparty) 中间件:
~~~
var multiparty = require('multiparty');
~~~
接下来定义文件上传的处理函数,构建一个 Form 对象,并将 req 作为参数进行解析,会将请求中的文件保存到临时文件目录,并构造 files 对象:
~~~
var fs = require('fs');
app.post('/upload', function(req, res){
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
var iconFile = files.iconImage[0];
if(iconFile.size !== 0){
fs.readFile(iconFile.path, function(err, data){
if(err) {
return res.send('读取文件失败');
}
var theFile = new AV.File(iconFile.originalFilename, data);
theFile.save().then(function(theFile){
res.send('上传成功!');
}).catch(console.error);
});
} else {
res.send('请选择一个文件。');
}
});
});
~~~
### [Session](#Session)
有时候你需要将一些自己需要的属性保存在 session 中,你可以增加通用的 `cookie-session` 组件,详情可以参考 [express.js · cookie-session](https://github.com/expressjs/cookie-session)。该组件和 `AV.Cloud.CookieSession` 组件可以并存。
express 框架的 `express.session.MemoryStore` 在云引擎中是无法正常工作的,因为云引擎是多主机、多进程运行,因此内存型 session 是无法共享的,建议用 [express.js · cookie-session 中间件](https://github.com/expressjs/cookie-session)。
### [LeanCache](#LeanCache)
首先添加相关依赖到 `package.json` 中:
~~~
"dependencies": {
...
"redis": "2.2.x",
...
}
~~~
然后可以使用下列代码获取 Redis 连接:
~~~
var client = require('redis').createClient(process.env['REDIS_URL_<实例名称>']);
// 建议增加 client 的 on error 事件处理,否则可能因为网络波动或 redis server 主从切换等原因造成短暂不可用导致应用进程退出。
client.on('error', function(err) {
return console.error('redis err: %s', err);
});
~~~
关于 LeanCache 的更多使用方法请看 [LeanCache 使用指南](https://leancloud.cn/docs/leancache_guide.html)。
### [重定向到 HTTPS](#重定向到_HTTPS)
为了安全性,我们可能会为网站加上 HTTPS 加密传输。我们的 云引擎 支持网站托管,同样会有这样的需求。
因此我们在 云引擎 中提供了一个新的 middleware 来强制让你的 `{应用的域名}.leanapp.cn` 的网站通过 https 访问,你只要这样:
Express:
~~~
app.enable('trust proxy');
app.use(AV.Cloud.HttpsRedirect());
~~~
Koa:
~~~
app.proxy = true;
app.use(AV.Cloud.HttpsRedirect({framework: 'koa'}));
~~~
部署并发布到生产环境之后,访问你的 云引擎 网站二级域名都会强制通过 HTTPS 访问。
### [多进程运行](#多进程运行)
因为 Node.js 本身的单线程模型,无法充分利用多个 CPU 核心,所以如果你使用了 2CPU 或以上的实例,需要自行使用 Node.js 的 [cluster](https://nodejs.org/api/cluster.html) 配置多进程运行,创建一个 `server-cluster.js`:
~~~
var cluster = require('cluster');
// 取决于你的实例的可用 CPU 数量
var workers = 2;
if (cluster.isMaster) {
for (var i = 0; i < workers; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log('worker %s died, restarting...', worker.process.pid);
cluster.fork();
});
} else {
require('./server.js')
}
~~~
然后在 `package.json` 中将 `scripts.start` 改为 `node server-cluster.js` 即可:
~~~
"scripts": {
"start": "node server-cluster.js"
}
~~~
多进程运行要求你的程序中没有在内存中维护全局状态(例如锁),建议在首次切换到多进程或多实例运行时进行充分的测试。
## [线上环境](#线上环境)
### [环境变量](#环境变量)
云引擎平台默认提供下列环境变量供应用使用:
| 变量名 | 说明 |
| --- | --- |
| `LEANCLOUD_APP_ID` | 当前应用的 App Id |
| `LEANCLOUD_APP_KEY` | 当前应用的 App Key |
| `LEANCLOUD_APP_MASTER_KEY` | 当前应用的 Master Key |
| `LEANCLOUD_APP_ENV` | 当前的应用环境:
* 开发环境没有该环境变量,或值为 `development`(一般指本地开发)
* 预备环境值为 `stage`
* 生产环境值为 `production`
|
| `LEANCLOUD_APP_PORT` | 当前应用开放给外网的端口,只有监听此端口,用户才可以访问到你的服务。 |
| `LEANCLOUD_APP_INSTANCE` | 云引擎实例名称,在多实例环境可以通过此变量标示自己。 |
| `LEANCLOUD_REGION` | 云引擎服务所在区域,值为 `CN` 或 `US`,分别表示国内节点和美国节点。 |
旧版云引擎使用的以 `LC_` 开头的环境变量(如 `LC_APP_ID`)已经被弃用。为了保证代码兼容性,`LC_` 变量在一段时间内依然有效,但未来可能会完全失效。为了避免报错,建议使用 `LEANCLOUD_` 变量来替换。
你也可以在 [云引擎 > 设置](https://leancloud.cn/cloud.html?appid=csXFgnEzBkodigdDUARBrEse-gzGzoHsz#/conf) 页面中添加自定义的环境变量。其中名字必须是字母、数字、下划线且以字母开头,值必须是字符串,修改环境变量后会在下一次部署时生效。
按照一般的实践,可以将一些配置项存储在环境变量中,这样可以在不修改代码的情况下,修改环境变量并重新部署,来改变程序的行为;或者可以将一些第三方服务的 Secret Key 存储在环境变量中,避免这些密钥直接出现在代码中。
~~~
// 在云引擎 Node.js 环境中使用自定义的环境变量
var MY_CUSTOM_VARIABLE = process.env.MY_CUSTOM_VARIABLE;
console.log(MY_CUSTOM_VARIABLE);
~~~
### [日志](#日志)
在控制台的 [云引擎 / 日志](https://leancloud.cn/cloud.html?appid=csXFgnEzBkodigdDUARBrEse-gzGzoHsz#/log) 中可以查看云引擎的部署和运行日志,还可以通过日志级别进行筛选。
应用的日志可以直接输出到「标准输出」或者「标准错误」,这些信息会分别对应日志的 `info` 和 `error` 级别,比如下列代码会在 info 级别记录参数信息:
~~~
console.log('hello');
console.error('some error!');
~~~
日志单行最大 4096 个字符,多余部分会被丢弃;日志输出频率大于 600 行/分钟,多余的部分会被丢弃。
你可以通过设置一个 `DEBUG=leancloud:request` 的环境变量来打印由 LeanCloud SDK 发出的网络请求。在本地调试时你可以通过这样的命令启动程序:
~~~
env DEBUG=leancloud:request lean up
~~~
当有对 LeanCloud 的调用时,你可以看到类似这样的日志:
~~~
leancloud:request request(0) +0ms GET https://api.leancloud.cn/1.1/classes/Todo?&where=%7B%7D&order=-createdAt { where: '{}', order: '-createdAt' }
leancloud:request response(0) +220ms 200 {"results":[{"content":"1","createdAt":"2016-08-09T06:18:13.028Z","updatedAt":"2016-08-09T06:18:13.028Z","objectId":"57a975a55bbb5000643fb690"}]}
~~~
我们不建议在线上生产环境开启这个日志,否则将会打印大量的日志。
### [时区](#时区)
在云引擎的中国区系统默认使用北京时间(`Asia/Shanghai`),美国区默认使用 UTC 时间。
需要注意 JavaScript 中 Date 类型的不同方法,一部分会返回 UTC 时间、一部分会返回当地时间(在中国区是北京时间):
| 函数 | 时区 | 结果 |
| --- | --- | --- |
| `toISOString` | UTC 时间 | 2015-04-09T03:35:09.678Z |
| `toJSON`(JSON 序列化时) | UTC 时间 | 2015-04-09T03:35:09.678Z |
| `toUTCString` | UTC 时间 | Thu, 09 Apr 2015 03:35:09 GMT |
| `getHours` | UTC 时间 | 3 |
| `toString`(`console.log` 打印时) | 当地时间 | Thu Apr 09 2015 03:35:09 GMT+0000 (UTC) |
| `toLocaleString` | 当地时间 | Thu Apr 09 2015 03:35:09 GMT+0000 (UTC) |
同时在构造 Date 对象时也要注意传递给 Date 一个带时区(无论是 UTC 还是本地时区,例如要使用 `2011-10-10T14:48:00.000Z` 而不是 `2011-10-10T14:48:00`)的对象,否则 Date 将 [不知道以什么样的方式来理解这个时间](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse)。
提醒大家需要在构造和展示时间对象时注意区分,否则就会出现时间「偏差八小时」的现象。
### [依赖缓存](#依赖缓存)
云引擎实现了一个缓存机制来加快构建的速度,所谓构建就是指你的应用在云引擎上安装依赖的过程,目测存在两种机制。
Node.js、Java 采用的:如果 `package.json` 或 `pom.xml` 和上次构建相比没有修改,就直接采用上次安装的依赖,只将新的应用代码替换上去。
Python、PHP 采用的:每次构建结束时将依赖目录打包,下次构建时将上次的依赖包解压到原处,再运行包管理器来安装依赖,可以复用已有的依赖项。
如果你遇到了与依赖安装有关的问题,可以在控制台部署时勾选「下载最新依赖」,或通过命令行工具部署时添加 `--noCache` 选项。
## [备案和自定义域名](#备案和自定义域名)
如果需要绑定自己的域名,进入 [应用控制台 > 账号设置 > 域名绑定](https://leancloud.cn/settings.html#/setting/domainbind),按照步骤填写资料即可。
国内节点绑定独立域名需要有 ICP 备案,只有主域名需要备案,二级子域名不需要备案;如果没有 ICP 备案,请进入 [应用控制台 > 账号设置 > 域名备案](https://leancloud.cn/settings.html#/setting/domainrecord),按照步骤填写资料进行备案。
备案之前要求云引擎已经部署,并且网站内容和备案申请的内容一致。仅使用云引擎托管静态文件、未使用其他 LeanCloud 服务的企业用户,需要自行完成域名备案工作。