[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 服務的企業用戶,需要自行完成域名備案工作。