Express,流行的Node.js框架

吕扬
2023-12-01

Express简介 (Introduction to Express)

Express is a Node.js Web Framework.

Express是一个Node.js Web框架。

Node.js is an amazing tool for building networking services and applications.

Node.js是用于构建网络服务和应用程序的出色工具。

Express builds on top of its features to provide easy to use functionality that satisfies the needs of the Web Server use-case. It’s Open Source, free, easy to extend and very performant. There are also lots and lots of pre-built packages you can just drop in and use to perform all kinds of things.

Express在其功能的基础上提供了易于使用的功能,可满足Web Server用例的需求。 它是开源的,免费,易于扩展且性能非常好。 还有很多预构建的软件包,您可以直接使用它们来执行各种操作。

安装 (Installation)

You can install Express into any project with npm:

您可以使用npm将Express安装到任何项目中:

npm install express

or Yarn:

纱线

yarn add express

Both commands will also work in an empty directory, when starting your project from scratch (although npm does not create a package.json file at all, and Yarn creates a basic one).

从头启动项目时,这两个命令也将在空目录中工作(尽管npm根本不会创建package.json文件,而Yarn会创建一个基本的文件)。

Just run npm init or yarn init if you’re starting a new project from scratch.

如果要从头开始一个新项目,只需运行npm inityarn init

你好,世界 (Hello World)

We’re ready to create our first Express Web Server.

我们准备创建我们的第一个Express Web Server。

Here is some code:

这是一些代码:

const express = require('express')
const app = express()

app.get('/', (req, res) => res.send('Hello World!'))
app.listen(3000, () => console.log('Server ready'))

Save this to an index.js file in your project root folder, and start the server using

将其保存到项目根文件夹中的index.js文件中,然后使用启动服务器

node index.js

You can open the browser to port 3000 on localhost and you should see the Hello World! message.

您可以将浏览器打开到本地主机上的端口3000,并且应该看到Hello World! 信息。

通过了解Hello World代码来学习Express的基础知识 (Learn the basics of Express by understanding the Hello World code)

Those 4 lines of code do a lot behind the scenes.

那四行代码在幕后做了很多工作。

First, we import the express package to the express value.

首先,我们将express包裹导入express价值。

We instantiate an application by calling the express() method.

我们通过调用express()方法实例化一个应用程序。

Once we have the application object, we tell it to listen for GET requests on the / path, using the get() method.

有了应用程序对象后,我们告诉它使用get()方法在/路径上侦听GET请求。

There is a method for every HTTP verb: get(), post(), put(), delete(), patch():

每个HTTP 动词都有一个方法: get()post()put()delete()patch()

app.get('/', (req, res) => { /* */ })
app.post('/', (req, res) => { /* */ })
app.put('/', (req, res) => { /* */ })
app.delete('/', (req, res) => { /* */ })
app.patch('/', (req, res) => { /* */ })

Those methods accept a callback function - which is called when a request is started - and we need to handle it.

这些方法接受回调函数-当请求开始时会被调用-我们需要处理它。

We pass in an arrow function:

我们传入一个箭头函数:

(req, res) => res.send('Hello World!')

Express sends us two objects in this callback, which we called req and res, they represent the Request and the Response objects.

Express在此回调中向我们发送了两个对象,我们称为reqres ,它们分别表示Request和Response对象。

Request is the HTTP request. It gives us all the request information, including the request parameters, the headers, the body of the request, and more.

Request是HTTP请求。 它为我们提供了所有请求信息,包括请求参数,标头,请求主体等。

Response is the HTTP response object that we’ll send to the client.

响应是我们将发送给客户端的HTTP响应对象。

What we do in this callback is to send the ‘Hello World!’ string to the client, using the Response.send() method.

在此回调中,我们要做的是发送“ Hello World!” 使用Response.send()方法将字符串传递给客户端。

This method sets that string as the body, and it closes the connection.

此方法将字符串设置为主体,并关闭连接。

The last line of the example actually starts the server, and tells it to listen on port 3000. We pass in a callback that is called when the server is ready to accept new requests.

该示例的最后一行实际上启动了服务器,并告诉它监听端口3000 。 当服务器准备好接受新请求时,我们将传递一个回调。

请求参数 (Request parameters)

I mentioned how the Request object holds all the HTTP request information.

我提到了Request对象如何保存所有HTTP请求信息。

These are the main properties you’ll likely use:

这些是您可能会使用的主要属性:

PropertyDescription
.appholds a reference to the Express app object
.baseUrlthe base path on which the app responds
.bodycontains the data submitted in the request body (must be parsed and populated manually before you can access it)
.cookiescontains the cookies sent by the request (needs the cookie-parser middleware)
.hostnamethe hostname as defined in the Host HTTP header value
.ipthe client IP
.methodthe HTTP method used
.paramsthe route named parameters
.paththe URL path
.protocolthe request protocol
.queryan object containing all the query strings used in the request
.securetrue if the request is secure (uses HTTPS)
.signedCookiescontains the signed cookies sent by the request (needs the cookie-parser middleware)
.xhrtrue if the request is an XMLHttpRequest
属性 描述
.app 持有对Express应用程序对象的引用
.baseUrl 应用程序响应的基本路径
。身体 包含在请求正文中提交的数据(必须先对其进行解析和填充,然后才能访问它)
。饼干 包含请求发送的cookie-parser (需要cookie-parser中间件)
。主机名 主机HTTP标头值中定义的主机
.ip 客户端IP
。方法 使用的HTTP方法
.params 路线命名参数
。路径 URL路径
。协议 请求协议
。查询 包含请求中使用的所有查询字符串的对象
。安全 如果请求是安全的(使用HTTPS),则为true
.signedCookies 包含请求发送的签名cookie(需要cookie-parser中间件)
.xhr 如果请求是XMLHttpRequest,则返回true

发送回复 (Sending a response)

In the Hello World example we used the Response.send() method to send a simple string as a response, and to close the connection:

在Hello World示例中,我们使用Response.send()方法发送一个简单字符串作为响应,并关闭连接:

(req, res) => res.send('Hello World!')

If you pass in a string, it sets the Content-Type header to text/html.

如果传入字符串,它将Content-Type标头设置为text/html

If you pass in an object or an array, it sets the application/json Content-Type header, and parses that parameter into JSON.

如果传入对象或数组,它将设置application/json Content-Type标头,并将该参数解析为JSON

send() automatically sets the Content-Length HTTP response header.

send()自动设置Content-Length HTTP响应标头。

send() also automatically closes the connection.

send()也会自动关闭连接。

发送JSON响应 (Send a JSON response)

The Response.json() method accepts an object or array, and converts it to JSON before sending it:

Response.json()方法接受一个对象或数组,并在发送之前将其转换为JSON:

res.json({ username: 'Flavio' })

使用end()发送空响应 (Use end() to send an empty response)

An alternative way to send the response, without any body, is by using the Response.end() method:

没有任何正文的发送响应的另一种方法是使用Response.end()方法:

res.end()

更改任何HTTP标头值 (Change any HTTP header value)

You can change any HTTP header value using Response.set():

您可以使用Response.set()更改任何HTTP标头值:

res.set('Content-Type', 'text/html')

There is a shortcut for the Content-Type header, however:

但是,Content-Type标头有一个快捷方式:

res.type('.html')
// => 'text/html'

res.type('html')
// => 'text/html'

res.type('json')
// => 'application/json'

res.type('application/json')
// => 'application/json'

res.type('png')
// => image/png:

设置饼干 (Set the cookies)

Use the Response.cookie() method to manipulate your cookies.

使用Response.cookie()方法来操作您的cookie。

Examples:

例子:

res.cookie('username', 'Flavio')

This method accepts a third parameter which contains various options:

此方法接受包含各种选项的第三个参数:

res.cookie('username', 'Flavio', { domain: '.flaviocopes.com', path: '/administrator', secure: true })

res.cookie('username', 'Flavio', { expires: new Date(Date.now() + 900000), httpOnly: true })

The most useful parameters you can set are:

您可以设置的最有用的参数是:

ValueDescription
domainthe cookie domain name
expiresset the cookie expiration date. If missing, or 0, the cookie is a session cookie
httpOnlyset the cookie to be accessible only by the web server. See HttpOnly
maxAgeset the expiry time relative to the current time, expressed in milliseconds
paththe cookie path. Defaults to /
secureMarks the cookie HTTPS only
signedset the cookie to be signed
sameSiteValue of SameSite
描述
domain cookie域名
expires 设置cookie的到期日期 。 如果丢失或为0,则该cookie是会话cookie
httpOnly 将cookie设置为只能由Web服务器访问。 参见HttpOnly
maxAge 设置相对于当前时间的到期时间,以毫秒为单位
path cookie路径 。 默认为/
secure Cookie标记为HTTPS
signed 设置要签名的cookie
sameSite SameSite价值

A cookie can be cleared with:

Cookie可以通过以下方式清除:

res.clearCookie('username')

设置HTTP响应状态 (Set the HTTP response status)

Use the Response.status():

使用Response.status()

res.status(404).end()

or

要么

res.status(404).send('File not found')

sendStatus() is a shortcut:

sendStatus()是一个快捷方式:

res.sendStatus(200)
// === res.status(200).send('OK')

res.sendStatus(403)
// === res.status(403).send('Forbidden')

res.sendStatus(404)
// === res.status(404).send('Not Found')

res.sendStatus(500)
// === res.status(500).send('Internal Server Error')

处理重定向 (Handling redirects)

Redirects are common in Web Development. You can create a redirect using the Response.redirect() method:

重定向在Web开发中很常见。 您可以使用Response.redirect()方法创建重定向:

res.redirect('/go-there')

This creates a 302 redirect.

这将创建302重定向。

A 301 redirect is made in this way:

301重定向是通过以下方式进行的:

res.redirect(301, '/go-there')

You can specify an absolute path (/go-there), an absolute url (https://anothersite.com), a relative path (go-there) or use the .. to go back one level:

您可以指定绝对路径( /go-there ),绝对URL( https://anothersite.com ),相对路径( go-there )或使用..返回上一级:

res.redirect('../go-there')
res.redirect('..')

You can also redirect back to the Referer HTTP header value (defaulting to / if not set) using

您还可以使用以下方法重定向回Referer HTTP标头值(默认为/如果未设置)

res.redirect('back')

发送文件进行下载 (Send a file to be downloaded)

The Response.download() method allows you to send a file attached to the request. Instead of showing the page, the browser will save the file to disk.

Response.download()方法允许您发送附加到请求的文件。 浏览器将不显示页面,而是将文件保存到磁盘。

res.download('/file.pdf')

res.download('/file.pdf', 'user-facing-filename.pdf')

支持JSONP (Support for JSONP)

JSONP is a way to consume cross-origin APIs from client-side JavaScript.

JSONP是一种使用客户端JavaScript跨域API的方法。

You can support it in your API by using the Response.jsonp() method, which is like Response.json() but handles JSONP callbacks:

您可以通过使用Response.jsonp()方法在您的API中支持它,该方法类似于Response.json()但可以处理JSONP回调:

res.jsonp({ username: 'Flavio' })

路由 (Routing)

In the Hello World example we used this code:

在Hello World示例中,我们使用了以下代码:

app.get('/', (req, res) => { /* */ })

This creates a route that maps accessing the root domain URL / to the response we want to provide.

这将创建一条路由,将访问根域URL /映射到我们要提供的响应。

命名参数 (Named parameters)

What if we want to listen for custom requests? Maybe we want to create a service that accepts a string, and returns that string in uppercase. If we don’t want the parameter to be sent as a query string, but part of the URL, we use named parameters:

如果我们想听定制请求怎么办? 也许我们想创建一个接受字符串的服务,并以大写形式返回该字符串。 如果我们不希望参数作为查询字符串发送,而是作为URL的一部分发送,则使用命名参数:

app.get('/uppercase/:theValue', (req, res) => res.send(req.params.theValue.toUpperCase()))

If we send a request to /uppercase/test, we’ll get TEST in the body of the response.

如果我们向/uppercase/test发送请求,则会在响应的正文中获得TEST

You can use multiple named parameters in the same URL, and they will all be stored in req.params.

您可以在同一URL中使用多个命名参数,它们都将存储在req.params

使用正则表达式匹配路径 (Use a regular expression to match a path)

You can use regular expressions to match multiple paths with one statement:

您可以使用正则表达式通过一条语句来匹配多个路径:

app.get(/post/, (req, res) => { /* */ })

will match /post, /post/first, /thepost, /posting/something, and so on.

将匹配/post/post/first/thepost/posting/something等。

中间件 (Middleware)

A middleware is a function that hooks into the routing process and performs an operation at some point, depending on what we want it to do.

中间件是一种功能,可以挂接到路由过程中,并在某个时候执行操作,具体取决于我们希望它做什么。

It’s commonly used to edit the request or response objects, or terminate the request before it reaches the route handler code.

通常用于编辑请求或响应对象,或在请求到达路由处理程序代码之前终止请求。

It’s added to the execution stack like this:

像这样将其添加到执行堆栈中:

app.use((req, res, next) => { /* */ })

This is similar to defining a route, but in addition to the Request and Response objects instances, we also have a reference to the next middleware function, which we assign to the variable next.

这类似于定义路由,但是除了Request和Response对象实例外,我们还引用了下一个中间件函数,该函数分配给变量next

We always call next() at the end of our middleware function, to pass the execution to the next handler, unless we want to prematurely end the response, and send it back to the client.

我们总是在中间件函数的末尾调用next() ,将执行传递给下一个处理程序,除非我们想过早地结束响应并将其发送回客户端。

You typically use pre-made middleware, in the form of npm packages. A big list of the available ones is here.

通常,您使用npm软件包形式的预制中间件。 可用的人的大名单是在这里

One example is cookie-parser, which is used to parse the cookies into the req.cookies object. You install it using npm install cookie-parser and you can use it like this:

cookie-parser是一个示例,它用于将cookie解析为req.cookies对象。 您可以使用npm install cookie-parser进行npm install cookie-parser ,您可以像这样使用它:

const express = require('express')
const app = express()
const cookieParser = require('cookie-parser')

app.get('/', (req, res) => res.send('Hello World!'))

app.use(cookieParser())
app.listen(3000, () => console.log('Server ready'))

You can also set a middleware function to run for specific routes only, by using it as the second parameter of the route definition:

您还可以通过将中间件功能用作路由定义的第二个参数,将中间件功能设置为仅针对特定路由运行:

const myMiddleware = (req, res, next) => {
  /* ... */
  next()
}

app.get('/', myMiddleware, (req, res) => res.send('Hello World!'))

If you need to store data that’s generated in a middleware to pass it down to subsequent middleware functions, or to the request handler, you can use the Request.locals object. It will attach that data to the current request:

如果您需要存储在中间件中生成的数据,以将其传递给后续的中间件功能或请求处理程序,则可以使用Request.locals对象。 它将数据附加到当前请求:

req.locals.name = 'Flavio'

服务静态资产 (Serving static assets)

It’s common to have images, CSS and more in a public subfolder, and expose them to the root level:

通常在public子文件夹中包含图像,CSS等,然后将其公开到根目录:

const express = require('express')
const app = express()

app.use(express.static('public'))

/* ... */

app.listen(3000, () => console.log('Server ready'))

If you have an index.html file in public/, that will be served if you now hit the root domain URL (http://localhost:3000)

如果您在public/有一个index.html文件,那么如果您现在访问根域URL( http://localhost:3000 ),该文件将被提供。

模板化 (Templating)

Express is capable of handling server-side templates.

Express能够处理服务器端模板。

Jade is the default template engine, but you can use many different template ones, including Pug, Mustache, EJS and more.

Jade是默认的模板引擎,但是您可以使用许多不同的模板引擎,包括Pug,Mustache,EJS等。

Say I don’t like Jade (I don’t), and I want to use Handlebars instead.

假设我不喜欢Jade(我不喜欢),而我想改用Handlebars。

I can install it using npm install hbs.

我可以使用npm install hbs进行npm install hbs

Put an about.hbs template file in the views/ folder:

about.hbs模板文件放在views/文件夹中:

Hello from {{name}}

and then use this Express configuration to serve it on /about:

然后使用此Express配置在/about上投放:

const express = require('express')
const app = express()
const hbs = require('hbs')

app.set('view engine', 'hbs')

app.get('/about', (req, res) => {
  res.render('about', { name: 'Flavio' })
})

app.listen(3000, () => console.log('Server ready'))

You can also render a React application server-side, using the express-react-views package.

您还可以使用express-react-views包在服务器端渲染React应用程序。

Start with npm install express-react-views react react-dom.

npm install express-react-views react react-dom开始, npm install express-react-views react react-dom

Now instead of requiring hbs we require express-react-views and use that as the engine, using jsx files:

现在,我们不再需要hbs而是需要express-react-views并使用jsx文件将其用作引擎:

const express = require('express')
const app = express()

app.set('view engine', 'jsx')
app.engine('jsx', require('express-react-views').createEngine())

app.get('/about', (req, res) => {
  res.render('about', { name: 'Flavio' })
})

app.listen(3000, () => console.log('Server ready'))

Just put an about.jsx file in views/, and calling /about should present you an “Hello from Flavio” string:

只需将一个about.jsx文件放在views/ ,然后调用/about您显示“来自Flavio的Hello”字符串:

const React = require('react')

class HelloMessage extends React.Component {
  render() {
    return <div>Hello from {this.props.name}</div>
  }
}

module.exports = HelloMessage

下一步是什么? (What’s next?)

Express has all the power of Node.js under the hood.

Express具有Node.js的所有强大功能。

You can do anything that you want, including connecting to a database, using any kind of caching, Redis, using sockets, and everything you can imagine doing on a server.

您可以做任何您想做的事情,包括连接到数据库,使用任何类型的缓存,Redis,使用套接字以及您在服务器上可以想到的一切。

The sky is the limit.

天空才是极限。

翻译自: https://flaviocopes.com/express/

 类似资料: