Node.js / Express.js-app.router는 어떻게 작동합니까?


298

질문하기 전에 app.router미들웨어로 작업 할 때 발생하는 일을 최소한 설명해야한다고 생각합니다. 미들웨어를 사용하는 기능은 app.use()입니다. 미들웨어가 실행될 때, 미들웨어를 사용하여 다음 미들웨어를 호출 next()하거나 더 이상 미들웨어가 호출되지 않도록합니다. 즉, 미들웨어 호출 순서는 중요합니다. 일부 미들웨어는 다른 미들웨어에 의존하기 때문에 끝 부분에있는 미들웨어가 호출되지 않을 수도 있기 때문입니다.

오늘 나는 내 응용 프로그램을 작업하고 있었고 백그라운드에서 서버를 실행했습니다. 변경하고 페이지를 새로 고치고 변경 내용을 즉시 확인하고 싶었습니다. 특히 레이아웃을 변경하고있었습니다. 나는이 대답을 스택 오버플로를 검색하고 찾을 수 있도록 동작하지 않습니다 수있는 이 질문을 . express.static()아래에 있는지 확인하라는 메시지 가 표시됩니다 require('stylus'). 그러나 OP의 코드를 볼 app.router때 미들웨어 호출이 끝날 때 전화를 받았으며 그 이유를 알아 내려고했습니다.

Express.js 응용 프로그램 (버전 3.0.0rc4)을 만들 때 명령을 사용했으며 express app --sessions --css stylusapp.js 파일에서 app.router위의 express.static()require('stylus')호출 모두로 코드가 설정되었습니다 . 따라서 이미 설정 한 경우 그대로 유지해야합니다.

스타일러스 변경 사항을 볼 수 있도록 코드를 다시 정렬하면 다음과 같습니다.

app.configure(function(){
  //app.set() calls
  //app.use() calls
  //...
  app.use(app.router);
  app.use(require('stylus').middleware(__dirname + '/public'));
  app.use(express.static(__dirname + '/public', {maxAge: 31557600000}));
});

app.get('/', routes.index);

app.get('/test', function(req, res){
  res.send('Test');
});

그래서 첫 번째 단계는 app.router내 코드에 포함 시키는 것이 중요한 이유를 찾는 것 입니다. 그래서 나는 그것을 주석 처리하고 내 앱을 시작하고로 이동했습니다 /. 내 색인 페이지가 잘 표시되었습니다. 흠, 아마도 내 경로 파일 (routes.index)에서 라우팅을 내보내는 중이었을 것입니다. 그래서 다음으로 이동 /test하여 화면에 테스트를 표시했습니다. 하하, 알 겠어 app.router. 코드에 포함되어 있는지 여부에 관계없이 라우팅이 좋습니다. 그래서 나는 분명히 뭔가를 놓치고 있습니다.

내 질문은 다음과 같습니다.

누군가가 무엇을 app.router, 그것의 중요성 및 미들웨어 호출에서 어디에 배치 해야하는지 설명해 주 시겠습니까? 에 대한 간단한 설명이 있으면 좋을 것 express.static()입니다. 내가 알 수 express.static()있는 한 내 정보의 캐시이며 응용 프로그램이 요청한 페이지를 찾을 수 없으면 캐시가 존재하는지 확인합니다.


18
이 질문을 해주셔서 감사합니다. 나는이 답변을 찾기 위해 인터넷 검색을 해왔다.
Hari Seldon

8
그것은 정말 잘 쓰여진 질문이었습니다. 나는 같은 것을 인터넷 검색하고있었습니다.
Kirn

답변:


329

참고 : 여기에서는 Express가 버전 2 및 3에서 작동하는 방식에 대해 설명합니다. Express 4에 대한 정보는이 게시물의 끝을 참조하십시오.


static단순히 디스크에서 파일 ( 정적 자원)을 제공합니다 . 경로 (마운트 포인트라고도 함)를 지정하면 해당 폴더의 파일을 제공합니다.

예를 들어 express.static('/var/www')해당 폴더의 파일을 제공합니다. 따라서 노드 서버에 대한 요청 http://server/file.html이 제공 /var/www/file.html됩니다.

router경로를 실행하는 코드입니다. 당신이 할 때 app.get('/user', function(req, res) { ... });, 그것은이다 router실제로 요청을 처리하는 콜백 함수를 호출하는.

전달 app.use하는 순서에 따라 각 미들웨어에 요청을 처리 할 수있는 기회가 결정됩니다. 예를 들어 test.html정적 폴더에 파일이 있고 경로가있는 경우 :

app.get('/test.html', function(req, res) {
    res.send('Hello from route handler');
});

어느 쪽이 요청한 클라이언트에게 보내 http://server/test.html집니까? use먼저 미들웨어가 제공됩니다 .

이렇게하면 :

app.use(express.static(__dirname + '/public'));
app.use(app.router);

그런 다음 디스크의 파일이 제공됩니다.

다른 방법으로하면

app.use(app.router);
app.use(express.static(__dirname + '/public'));

그런 다음 경로 처리기가 요청을 받고 "Hello from route handler"가 브라우저로 전송됩니다.

일반적으로 실수로 이름이 지정된 파일이 경로 중 하나를 재정의 할 수 없도록 라우터를 정적 미들웨어 위에 배치하려고합니다 .

명시 적으로하지 않으면주의 ,이 암시 적으로 (당신의 경로는 여전히 주석에도 불구하고 일 이유입니다 당신이 경로를 정의하는 시점에서 Express에서 추가됩니다 ).userouterapp.use(app.router)


주석 기이있다 양육 의 순서에 대한 또 다른 지점을 static하고 router내가 가진 것을 해결되지 : 앱의 전반적인 성능에 미치는 영향을.

use router위의 또 다른 이유 static는 성능을 최적화하는 것입니다. 먼저 넣으면 static매 요청마다 하드 드라이브를 쳐서 파일이 있는지 여부를 확인합니다. A의 빠른 테스트 ,이 오버 헤드가 언로드 서버에서 ~ 1ms의에 달했다 것을 발견했다. (이 수치는 요청이 디스크 액세스를 위해 경쟁하는 부하에서 더 높을 가능성이 높습니다.)

router첫째, 경로 와 일치하는 요청이 디스크에 도달 할 필요가 없으므로 소중한 밀리 초가 절약됩니다.

물론 static오버 헤드 를 완화 할 수있는 방법이 있습니다 .

가장 좋은 방법은 모든 정적 리소스를 특정 폴더에 두는 것입니다. (IE /static) static경로가 다음과 /static같이 시작될 때만 실행되도록 해당 경로에 마운트 할 수 있습니다 .

app.use('/static', express.static(__dirname + '/static'));

이 상황에서는 이것을 위에 배치하십시오 router. 파일이 있으면 다른 미들웨어 / 라우터를 처리하지 않아도되지만 솔직히 말하면 많은 것을 얻을 수 있을지 의심됩니다.

staticCache정적 리소스를 메모리에 캐시하는 을 사용 하여 일반적으로 요청되는 파일을 디스크에 사용할 필요가 없습니다. ( 경고 : 향후에는 staticCache 제거 될 것입니다.)

그러나 staticCache파일이 존재하지 않을 때 부정적인 대답을 캐시 한다고 생각 하지 않으므로 경로에 마운트하지 않고 staticCache위에 놓으면 도움이되지 않습니다 router.

성능에 대한 모든 질문과 마찬가지로 실제 앱 (로드 상태)을 측정하고 벤치 마크하여 병목 현상이 실제로 발생하는 위치를 확인하십시오.


익스프레스 4

Express 4.0이 제거합니다 app.router . 모든 미들웨어 ( app.use) 및 경로 ( app.get등)는 이제 추가 된 순서대로 정확하게 처리됩니다.

다시 말해:

모든 라우팅 방법은 순서대로 추가됩니다. 당신은해야 하지 합니까 app.use(app.router). 이것은 Express에서 가장 일반적인 문제를 제거합니다.

즉, 혼합 app.use()app[VERB]()작동 을 정확하게 가 호출되는 순서대로.

app.get('/', home);
app.use('/public', require('st')(process.cwd()));
app.get('/users', users.list);
app.post('/users', users.create);

Express 4의 변경 사항에 대해 자세히 알아보십시오.


2
router한 장소에 간다. 처음 app.get(또는 post다른 사람) 에게 전화를 걸었을 때 아직 used를 입력 하지 않은 app.router경우 Express가 자동으로 추가합니다.
josh3736

4
@MikeCauser : 아니요. 디스크 액세스 오버 헤드 (파일이 있는지 여부를 확인하기위한 오버 헤드)가 함수 호출 오버 헤드보다 크기 때문에. 내 테스트 에서 언로드 된 서버의 오버 헤드는 1ms였습니다. 요청이 디스크 액세스를 위해 경쟁하는로드에서 더 높을 가능성이 높습니다. staticafter를 사용하면 router다른 미들웨어에 대한 질문은 라우터 위에 있어야 하므로 관련이 없습니다 .
josh3736

2
멋진 설명! 정말 고맙습니다!
Kirn

3
app.router는 현재 마스터 브랜치에서 제거 되며 express-4.0 입니다. 각 경로는 별도의 미들웨어가됩니다.
yanychar

3
내가이 작업을 할 때 한 번 더 설명합니다. Express 4에서는 라우터에 여러 경로를 할당 한 다음 라우터를 사용하기 위해 라우터에 루트 경로가 지정되고 app.use (path, router)를 통해 "미들웨어"스택에 배치됩니다. 이를 통해 관련 경로는 각각 고유의 라우터를 사용하고 기본 경로를 단위로 할당 할 수 있습니다. 더 잘 이해하면 다른 답변을 게시 할 것을 제안합니다. 다시, 나는 이것을 scotch.io/tutorials/javascript/…
Joe Lapp

2

라우팅이란 응용 프로그램이 URI (또는 경로) 및 특정 HTTP 요청 방법 (GET, POST 등) 인 특정 엔드 포인트에 대한 클라이언트 요청에 응답하는 방법을 결정하는 것을 의미합니다. 각 라우트에는 라우트가 일치 할 때 실행되는 하나 이상의 핸들러 함수가있을 수 있습니다.

Express 4.0 라우터에서는 경로를 정의 할 때 그 어느 때보 다 유연성이 향상되었습니다.

express.Router ()는 여러 번 사용하여 경로 그룹을 정의합니다.

요청을 처리하기 위해 미들웨어로 사용되는 경로.

".param ()"을 사용하여 매개 변수의 유효성을 검증하기 위해 미들웨어로 사용되는 경로.

라우터에 대한 바로 가기로 사용되는 app.route ()는 경로에서 여러 요청을 정의합니다.

app.route ()를 사용할 때 앱을 해당 라우터에 연결합니다.

var express = require('express'); //used as middleware
var app = express(); //instance of express.
app.use(app.router);
app.use(express.static(__dirname + '/public')); //All Static like [css,js,images] files are coming from public folder
app.set('views',__dirname + '/views'); //To set Views
app.set('view engine', 'ejs'); //sets View-Engine as ejs
app.engine('html', require('ejs').renderFile); //actually rendering HTML files through EJS. 
app.get('/', function (req, res) {
  res.render('index');  
})
app.get('/test', function (req, res) {
  res.send('test')
})

0

Express 버전 4에서는 다음과 같은 방식으로 경로를 쉽게 정의 할 수 있습니다.

server.js :

const express = require('express');
const app = express();
const route = require('./route');

app.use('/route', route);
// here we pass in the imported route object

app.listen(3000, () => console.log('Example app listening on port 3000!'));

route.js :

const express = require('express');
const router = express.Router();

router.get('/specialRoute', function (req, res, next) {
     // route is now http://localhost:3000/route/specialRoute
});

router.get('/', function (req, res, next) {
    // route is now http://localhost:3000/route
});

module.exports = router;

에서 server.js우리의 라우터 개체 가져 오기 route.js파일을 다음과 같은 방식으로 적용 server.js:

app.use('/route', route);

이제의 모든 경로 route.js에는 다음과 같은 기본 URL이 있습니다.

http : // localhost : 3000 / route

왜 이런 접근 방식 :

이 접근 방식의 가장 큰 장점은 이제 앱이 더 모듈화되어 있다는 것 입니다. 특정 경로에 대한 모든 경로 처리기를 이제 다른 파일에 넣을 수있어 모든 것을보다 유지 관리하고 쉽게 찾을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.