NodeJS專案基礎結構簡單介紹
新建的基於ejs模版的NodeJS專案.png
按照常規,去執行npm start
側邊欄左下角的npm命令.png
或者在Terminal中手動輸入命令,結果如下:
C:Subversiontest>npm start > test@0.0.0 start C:Subversiontest> node ./bin/www
可以看到是執行了test/package.json檔案中的start命令,初始packagejson.json檔案內容如下:
{ "name": "test", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { "cookie-parser": "~1.4.3", "debug": "~2.6.9", "ejs": "~2.5.7", "express": "~4.16.0", "http-errors": "~1.6.2", "morgan": "~1.9.0" } }
執行start,對應的命令為node ./bin/www並在命令列執行。現在專案已經啟動成功了,可以開啟瀏覽器輸入localhost:3000檢視一下,但是本次側重點在於專案啟動時候發生的完整的過程。所以……
那麼我們需要看一下 ./bin/www 檔案
#!/usr/bin/env node/** * Module dependencies. */var app = require('../app');var debug = require('debug')('test:server');var http = require('http');/** * Get port from environment and store in Express. */var port = normalizePort(process.env.PORT || '3000'); app.set('port', port);/** * Create HTTP server. */var server = http.createServer(app);/** * Listen on provided port, on all network interfaces. */server.listen(port); server.on('error', onError); server.on('listening', onListening);/** * Normalize a port into a number, string, or false. */function normalizePort(val) { var port = parseInt(val, 10); if (isNaN(port)) { // named pipe return val; } if (port >= 0) { // port number return port; } return false; }/** * Event listener for HTTP server "error" event. */function onError(error) { if (error.syscall !== 'listen') { throw error; } var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': console.error(bind + ' is already in use'); process.exit(1); break; default: throw error; } }/** * Event listener for HTTP server "listening" event. */function onListening() { var addr = server.address(); var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; debug('Listening on ' + bind); }
透過 require() 來引入本地安裝的包,這裡載入了三個包 app、debug 、http ,主要關注一下app.js
var createError = require('http-errors');var express = require('express');var path = require('path');var cookieParser = require('cookie-parser');var logger = require('morgan');var indexRouter = require('./routes/index');var usersRouter = require('./routes/users');var app = express();// view engine setupapp.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', indexRouter); app.use('/users', usersRouter);// catch 404 and forward to error handlerapp.use(function(req, res, next) { next(createError(404)); });// error handlerapp.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app;
可以看到app載入的為該專案基礎元件,核心為 var app = express(); 看一下express.js
var bodyParser = require('body-parser')var EventEmitter = require('events').EventEmitter;var mixin = require('merge-descriptors');var proto = require('./application');var Route = require('./router/route');var Router = require('./router');var req = require('./request');var res = require('./response');/** * Expose `createApplication()`. */exports = module.exports = createApplication;/** * Create an express application. * * @return {Function} * @api public */function createApplication() { var app = function(req, res, next) { app.handle(req, res, next); }; mixin(app, EventEmitter.prototype, false); mixin(app, proto, false); // expose the prototype that will get set on requests app.request = Object.create(req, { app: { configurable: true, enumerable: true, writable: true, value: app } }) // expose the prototype that will get set on responses app.response = Object.create(res, { app: { configurable: true, enumerable: true, writable: true, value: app } }) app.init(); return app; }/** * Expose the prototypes. */exports.application = proto; exports.request = req; exports.response = res;/** * Expose constructors. */exports.Route = Route; exports.Router = Router;/** * Expose middleware */exports.json = bodyParser.json exports.query = require('./middleware/query'); exports.static = require('serve-static'); exports.urlencoded = bodyParser.urlencoded
將app用到的中介軟體等暴露出來,所以 app = express() 實際上就是載入應用基礎元件,生成專案的根節點(當然這個節點是複合的)。所以在app.js中,進行的是載入應用基礎元件並進行應用設定初始化(包含了檢視目錄設定、頁面模板引擎設定、中介軟體的設定、靜態資源目錄設定以及錯誤捕捉相關內容)。
繼續回到 ,同樣將debug配置、http相關元件進行載入。繼而是預設埠號的設定。透過http.createServer(app),建立應用服務相關資訊,並對埠進行監聽。
瀏覽器輸入localhost:3000
express框架專案跑起來了.png
控制檯顯示:
GET / 304 3.389 ms - - GET /stylesheets/style.css 304 0.680 ms - -
說明在以GET方式請求URI為"/"的資源,並以GET方式請求/stylesheets/style.css資源,這個發生在app.js中我們設定的資源請求。
var indexRouter = require('./routes/index');var usersRouter = require('./routes/users'); app.use('/', indexRouter); app.use('/users', usersRouter);
我們來看下 ./routes/index 檔案
var express = require('express');var router = express.Router();/* GET home page. */router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); });module.exports = router;
即定義網站主頁的路由
使用 express.Router 類建立模組化、可掛載的路由控制程式碼(簡稱:路由模組)。Router 例項是一個完整的中介軟體和路由系統。最終,在應用中載入路由模組app.use('/', indexRouter);
透過 res.render 對檢視進行渲染,上述為對index.ejs的渲染。ps:在app.js中已經設定了views的所在目錄。語法:res.render(view [,locals] [,callback])
locals 定義檢視的區域性變數。區域性變數cache啟用檢視快取。將其設定為true,以在開發期間快取檢視; 預設情況下,生產中啟用了檢視快取。
callback 定義回撥函式。如果存在,則該方法返回可能的錯誤和異常資訊,將不執行自動相應。發生錯誤時,該方法在next(err)內部呼叫
示例:
// send the rendered view to the clientres.render('index');// if a callback is specified, the rendered HTML string has to be sent explicitlyres.render('index', function(err, html) { res.send(html); });// pass a local variable to the viewres.render('user', { name: 'Tobi' }, function(err, html) { // ...});
res響應方法.png
區別:路由控制程式碼
為請求處理提供多個回撥函式,其行為類似 。唯一的區別是這些回撥函式有可能呼叫 next('route') 方法跳至下一個同路由的回撥函式而略過其他路由回撥函式。路由控制程式碼有多種形式,可以是一個函式、一個函式陣列,或者是兩者混合。
使用一個回撥函式處理路由:
app.get('/example/a', function (req, res) { res.send('Hello from A!'); });
使用多個回撥函式處理路由(記得指定 next 物件):
app.get('/example/b', function (req, res, next) { console.log('response will be sent by the next function ...'); next(); }, function (req, res) { res.send('Hello from B!'); });
使用回撥函式陣列處理路由:
var cb0 = function (req, res, next) { console.log('CB0'); next(); }var cb1 = function (req, res, next) { console.log('CB1'); next(); }var cb2 = function (req, res) { res.send('Hello from C!'); } app.get('/example/c', [cb0, cb1, cb2]);
混合使用函式和函式陣列處理路由:
var cb0 = function (req, res, next) { console.log('CB0'); next(); }var cb1 = function (req, res, next) { console.log('CB1'); next(); } app.get('/example/d', [cb0, cb1], function (req, res, next) { console.log('response will be sent by the next function ...'); next(); }, function (req, res) { res.send('Hello from D!'); });
區別:路由方法
一個路由示例:
var express = require('express');var app = express();// respond with "hello world" when a GET request is made to the homepageapp.get('/', function(req, res) { res.send('hello world'); });
作者:miku設定
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1795/viewspace-2817342/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Vue3專案的簡單搭建與專案結構的簡單介紹Vue
- 簡單介紹 Vue 3.0 專案建立Vue
- 簡單介紹一下Component基礎佈局
- 檔案管理簡單介紹
- 簡單介紹VBS 批次Ping的專案實現
- .NET CLI簡單教程和專案結構
- SVG程式碼構成簡單介紹SVG
- 【資料結構基礎】棧簡介(使用ES6)資料結構
- 軟體開發常用結構以及SSM框架的簡單介紹SSM框架
- 簡單介紹Golang列印複雜結構體的兩種方法Golang結構體
- 【資料結構基礎】佇列簡介(使用ES6)資料結構佇列
- RPC簡單介紹RPC
- Python簡單介紹Python
- KVM簡單介紹
- RMI簡單介紹
- HTML簡單介紹HTML
- HTML 簡單介紹HTML
- JavaScript 簡單介紹JavaScript
- CSS 簡單介紹CSS
- ajax簡單介紹
- SVG簡單介紹SVG
- Clickjacking簡單介紹
- 【Pandas】簡單介紹
- Map簡單介紹
- JSON簡單介紹JSON
- ActiveMQ簡單介紹MQ
- Pandas基礎介紹
- Elasticsearch 基礎介紹Elasticsearch
- C++基礎簡單總結C++
- Java基礎集合簡單總結Java
- Android Studio專案目錄結構簡介Android
- 面試時如何不簡單de介紹自己的專案經驗?面試
- 簡單介紹如何使用Bazel構建Golang程式Golang
- 簡單介紹架構設計的原則!架構
- 前端學習(2375):專案介紹結束前端
- Web專案開發介紹及實戰專案介紹Web
- Xamarin.FormsShell基礎教程(7)Shell專案關於頁面的介紹ORM
- 簡單介紹Linux環境變數檔案Linux變數