Skip to content

Instantly share code, notes, and snippets.

@pjchender
Last active May 1, 2017 05:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pjchender/b578f0a127d8d09124d2436e9e9b720e to your computer and use it in GitHub Desktop.
Save pjchender/b578f0a127d8d09124d2436e9e9b720e to your computer and use it in GitHub Desktop.
[Treehouse][Node]Build a Simple Dynamic Site with Node.js @ Treehouse
var router = require('./router.js')
// 問題:我們希望能夠用瀏覽器的方式查詢使用者在 treehouse 的點數
// 解決:使用 NodeJS 來展現檔案
// 1. 建立一個網路伺服器
const http = require('http')
const hostname = '127.0.0.1'
const port = 3000
const server = http.createServer((request, response) => {
router.home(request, response)
router.user(request, response)
})
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`)
})
<div id="profile">
<img src="{{avatarUrl}}" alt="Avatar" id="avatar">
<p><span>{{username}}</span></p>
<ul>
<li><span>{{badges}}</span> Badges earned</li>
<li><span>{{javaScriptPoints}}</span> JavaScript points</li>
<li><a href="/">search again</a></li>
</ul>
</div>
var fs = require('fs')
// 將模版 {{}} 填入值
// mergeValue (陣列, 內容)
function mergeValue (values, content) {
// 疊代取得 key 值
for (let item in values) {
// 將所有 {{key}} 取代成 values 物件中對應的 value
content = content.replace(`{{${item}}}`, values[item])
}
// 回傳將資料代入 template 後的 content
return content
}
// 選擇模版,要填入的值,並回傳結果
// view(模版檔名,填入的值,寫入回應)
function view (templateName, values, response) {
// 讀取 Template 檔案
var fileContents = fs.readFileSync('./views/' + templateName + '.html', {encoding: 'utf8'})
// 將值塞入模版中
fileContents = mergeValue(values, fileContents)
// 將成品回傳
response.write(fileContents)
}
module.exports.view = view
var Profile = require('./profile.js')
var render = require('./render.js')
var queryString = require('querystring')
// 處理 HTTP Route GET / POST / (例如,Home)
function homeRoute (request, response) {
// if url == "/" && GET
if (request.method.toLowerCase() === 'get'){
if (request.url === '/') {
// show search
response.statusCode = 200
response.setHeader('Content-Type', 'text/html')
render.view('header', {}, response)
render.view('search', {}, response)
render.view('footer', {}, response)
}
} else {
// if url == "/" && POST
// 從 post body 取得資料
request.on('data', function (postBody) {
// 取得 username
let query = queryString.parse(postBody.toString())
// redirect to /:username
response.writeHead(303, {'Location': '/' + query.username})
response.end()
})
}
}
// 處理 HTTP Route GET /:username (例如,/chalkers)
// if url == "/..."
function userRoute (request, response) {
var username = request.url.replace('/', '')
if (username.length > 0) {
response.statusCode = 200
response.setHeader('Content-Type', 'text/html')
render.view('header', {}, response)
// 從 Treehouse 取的 JSON 檔
var studentProfile = new Profile(username)
// on "end"
studentProfile.on('end', function (profileJSON) {
// show profile
// 儲存所需要的資料
var values = {
avatarUrl: profileJSON.gravator_url,
username: profileJSON.profile_name,
badges: profileJSON.badges.length,
javaScriptPoints: profileJSON.points.JavaScript
}
// 簡單的回覆
render.view('profile', values, response)
render.view('footer', {}, response)
})
// on "error"
studentProfile.on('error', function (error) {
render.view('error', {errorMessage: error.message}, response)
render.view('search', {}, response)
render.view('footer', {}, response)
})
}
}
module.exports.home = homeRoute
module.exports.user = userRoute
@pjchender
Copy link
Author

pjchender commented Apr 3, 2017

app.js

[建立伺服器]

//  載入 http 模組
const http = require('http')

const hostname = '127.0.0.1'
const port = 3000

//  建立伺服器
const server = http.createServer((request, response) => {
 //  載入路由檔
})

// 監聽伺服器
server.listen(port, hostname, () => {
})

@pjchender
Copy link
Author

pjchender commented Apr 3, 2017

router.js

建立路由相關

  • 使用 req.method 來取得 request 的方法(例如,GET)
  • 使用 req.url 來取得 request 的 URL
  • 使用 res.setHeader('Content-Type', 'text/html') 來設定 response 的 header
  • 使用 res.writeHead(303, {'Location': '/' + query.username}) 來寫和 header 有關的訊息
  • 使用 res.end() 表示結束 response
// 載入模組
var Profile = require('./profile.js')
var render = require('./render.js')
var queryString = require('querystring')
function homeRoute (request, response) {
  //  如果網址是 "/" 且為 get
  if (request.url === '/') {
    //  顯示結果
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/plain')
    response.write('Header\n')
    response.end('Footer\n')
  }
}

對 request 做一些事

    request.on('data', postBody => {
      let query = queryString.parse(postBody.toString())
    }

對 response 做一些事

    response.statusCode = 200
    response.setHeader('Content-Type', 'text/plain')
    response.write('寫入 response 內容')
    response.end('response 結尾')  //  在這之後不能再寫入 response

@pjchender
Copy link
Author

pjchender commented Apr 3, 2017

render.js

[渲染(render)模版]

  • 使用 `replace('target', 'value') ,將模版的內容填入資料
  • 使用 fs.readFileSync('./views/' + templateName + '.html', {encoding: 'utf8'}) 讀取檔案內容
  • 使用 res.write(...) 寫入網頁內容
var fs = require('fs')

//  將模版 {{}} 填入值
function mergeValue (values, content) {
  //  疊代取得 key 值
  for (let item in values) {
    //  將所有 {{key}} 取代成 values 物件中對應的 value
    content = content.replace(`{{${item}}}`, values[item])
  }
  //  回傳將資料代入 template 後的 content
  return content
}

//  選擇模版,要填入的值,並回傳結果
function view (templateName, values, response) {
  //  讀取 Template 檔案
  var fileContents = fs.readFileSync('./views/' + templateName + '.html', {encoding: 'utf8'})

  //  將值塞入模版中
  fileContents = mergeValue(values, fileContents)

  //  將成品回傳
  response.write(fileContents)
}

module.exports.view = view

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