찾다
웹 프론트엔드HTML 튜토리얼用Express 框架创建草地鹨旅行社网站_html/css_WEB-ITnose

脚手架

脚手架并不是一个新想法,但很多人(包括我自己)都是通过Ruby才接触到这个概念的。这个想法很简单:大多数项目都需要一定数量的“套路化”代码,谁会想每次开始新项目时都重新写一次这些代码呢?对此有个简单的方法,那就是创建一个通用的项目骨架,每次开始新项目时,只需复制这个骨架,或者说是模板。

RoR把这个概念向前推进了一步,它提供了一个可以自动生成脚手架的程序。相对于从一堆模板中作出选择,这种方式的优点是可以生成更复杂的框架。

Express借鉴了RoR的这一做法,提供了一个生成脚手架的工具,从而可以让你开始一个新的Express项目。

尽管Express有可用的脚手架工具,但它目前并不能生成我推荐使用的框架。特别是它不支持我所选择的模板语言(Handlebars),也没有遵循我所偏好的命名规则(尽管这很容易解决)。

尽管我们不用这个脚手架工具,但我还是建议你看一下它:到那时,你就能够充分了解它生成的脚手架是否对你有用了。

套路化对最终发送到客户端的真正HTML也是有用的。我推荐非常出色的HTML5 Boilerplate( http://html5boilerplate.com/),它能生成一个很不错的空白HTML5网站。最近HTML5 Boilerplate又新增加了可定制的功能,其中一个定制选项包含Twitter Bootstrap,这个是我高度推荐的前端框架。

草地鹨旅行社网站

本文以一个可运行的网站为例:假想的草地鹨旅行社网站,该旅行社是一家为到俄勒冈州旅游的人提供服务的公司。如果你对创建REST应用程序更感兴趣,不用担心,因为草地鹨旅行社网站除了作为功能性网站外,也提供REST服务。

初始步骤

先给你的项目创建一个新目录,这将作为项目的根目录。本文中,凡提到“项目目录”“程序目录”或“项目根路径”,指的都是这个目录。

提示:或许你会把Web程序文件跟项目相关的其他文件全都分开存放,比如会议纪要、文档等。因此,我建议你把项目根路径作为项目目录的子目录。比如,对于草地鹨旅行社网站而言,我会把项目放在~/projects/meadowlark,而项目根路径放在~/projects/meadowlark/site。

npm在package.json文件中管理项目的依赖项以及项目的元数据。要创建这个文件,最简单的办法是运行 npm init:它会问一系列的问题,然后为你生成一个package.json文件帮你起步(对于“入口点”的问题,用meadowlark.js或项目的名字作为答案)。

提示:如果你的package.json文件中没有指定一个存储库的URL,以及一个非空的README.md文件,那么你每次运行npm时都会看到警告信息。package.json文件中的元数据只有在发布到npm存储库时才是真正必要的,但为了消除npm的警告信息,做这些工作依然是值得的。

第一步是安装Express。运行下面这条npm命令:

npm install --save express

运行 npm install会把指定名称的包安装到node_modules目录下。如果你用了 --save选项,它还会更新package.json文件。因为node_modules随时都可以用npm重新生成,所以我们不会把这个目录保存在我们的代码库中。为了确保不把它添加到代码库中, 我们可以创建一个.gitignore文件:

# ignore packages installed by npmnode_modules# put any other files you don't want to check in here,# such as .DS_Store (OSX), *.bak, etc.

接下来创建meadowlark.js文件,这是我们项目的入口。本文中将这个文件简单称为“程序文件”:

var express = require('express');var app = express();app.set('port', process.env.PORT || 3000);// 定制404页面app.use(function(req, res){ res.type('text/plain'); res.status(404); res.send('404 - Not Found');});//定制500页面app.use(function(err, req, res, next){ console.error(err.stack); res.type('text/plain'); res.status(500); res.send('500 - Server Error');});app.listen(app.get('port'), function(){ console.log( 'Express started on http://localhost:' + app.get('port') + '; press Ctrl-C to terminate.' );});

提示:很多教程,甚至是Express的脚手架生成器会建议你把主文件命名为app.js(或者有时是index.js或server.js)。除非你用的托管服务或部署系统对程序主文件的名称有特定的要求,否则我认为这么做是没有道理的,我更倾向于按照项目命名主文件。凡是曾在编辑器里见过一堆index.html标签的人都会立刻明白这样做的好处。 npm init默认是用index.js,如果要使用其他的主文件名,要记得修改package.json文件中的 main属性。

现在你有了一个非常精简的Express服务器。你可以启动这个服务器(node meadowlark.js),然后访问http://localhost:3000。结果可能会让你失望,因为你还没给Express任何路由信息,所以它会返回一个404页面,表示你访问的页面不存在。

注释:注意我们指定程序端口的方式: app.set(port, process.env.PORT || 3000)。这样我们可以在启动服务器前通过设置环境变量覆盖端口。如果你在运行这个案例时发现它监听的不是3000端口,检查一下是否设置了环境变量 PORT。

提示:我高度推荐你安装一个能显示HTTP请求状态码和所有重定向的浏览器插件。这样在解决重定向问题或者不正确的状态码时会更加容易,它们经常被忽视。对于Chrome来说,Ayima的Redirect Path特别好用。在大多数浏览器中, 都能在开发者工具的网络部分看到状态码。

我们来给首页和关于页面加上路由。在404处理器之前加上两个新路由:

app.get('/', function(req, res){ res.type('text/plain'); res.send('Meadowlark Travel');});app.get('/about', function(req, res){ res.type('text/plain'); res.send('About Meadowlark Travel');});// 定制404页面app.use(function(req, res, next){ res.type('text/plain'); res.status(404); res.send('404 - Not Found');});

app.get是我们添加路由的方法。在Express文档中写的是 app.VERB。这并不意味着存在一个叫 VERB的方法,它是用来指代HTTP动词的(最常见的是“get” 和“post”)。这个方法有两个参数:一个路径和一个函数。

路由就是由这个路径定义的。 app.VERB帮我们做了很多工作:它默认忽略了大小写或反斜杠,并且在进行匹配时也不考虑查询字符串。所以针对关于页面的路由对于/about、/About、/about/、/about?foo=bar、/about/?foo=bar等路径都适用。

路由匹配上之后就会调用你提供的函数,并把请求和响应对象作为参数传给这个函数。现在我们只是返回了状态码为200的普通文本(Express默认的状态码是200,不用显式指定)。

我们这次使用的不是Node的 res.end,而是换成了Express的扩展 res.send。我们还用 res.set和 res.status替换了Node的 res.writeHead。Express还提供了一个 res.type方法,可以方便地设置响应头 Content-Type。尽管仍然可以使用 res.writeHead和 res.end,但没有必要也不作推荐。

注意,我们对定制的404和500页面的处理与对普通页面的处理应有所区别:用的不是 app.get,而是 app.use。 app.use是Express添加 中间件的一种方法。你可以把它看作处理所有没有路由匹配路径的处理器。这里涉及一个非常重要的知识点:在Express中,路由和中间件的添加顺序至关重要。如果我们把404处理器放在所有路由上面,那首页和关于页面就不能用了,访问这些URL得到的都是404。现在我们的路由相当简单,但其实它们还能支持通配符,这会导致顺序上的问题。比如说,如果要给关于页面添加子页面,比如/about/contact和/about/directions会怎么样呢?下面这段代码是达不到预期效果的:

app.get('/about*',function(req,res){            // 发送内容....})app.get('/about/contact',function(req,res){            // 发送内容....})app.get('/about/directions',function(req,res){            // 发送内容....})

本例中的 /about/contact和 /about/directions处理器永远无法匹配到这些路径,因为第一个处理器的路径中用了通配符: /about*。

Express能根据回调函数中参数的个数区分404和500处理器。

你可以再次启动服务器,现在首页和关于页面都可以运行了。

截至目前我们所做的事情,即使不用Express也很容易完成,但Express所提供的一些功能并非那么显而易见。还记得如何规范化 req.url来确定所请求的资源吗?我们必须手动剥离查询字符串和反斜杠,并转化为小写。而Express的路由器会自动帮我们处理好这些细节。尽管目前看起来这并非什么大不了的事情,但这只是Express路由器能力的冰山一角。

视图和布局

如果你熟知“模型-视图-控制器”模式,那你对视图这个概念应该不会感到陌生。视图本质上是要发送给用户的东西。对网站而言,视图通常就是HTML,尽管也会发送PNG或PDF,或者其他任何能被客户端渲染的东西。

视图与静态资源(比如图片或CSS文件)的区别是它不一定是静态的:HTML可以动态构建,为每个请求提供定制的页面。

Express支持多种不同的视图引擎,它们有不同层次的抽象。Express比较偏好的视图引擎是Jade(因为它也是TJ Holowaychuk开发的) 。Jade所采用的方式非常精简:你写的根本不像是HTML,因为没有尖括号和结束标签,这样可以少敲好多次键盘。然后,Jade引擎会将其转换成HTML。

Jade是非常吸引人的,但这种程度的抽象也是有代价的。如果你是一名前端开发人员,即便你实际上是用Jade编写视图,也必须理解HTML,并且有足够深入的认识。我认识的大多数前端开发人员都不喜欢他们主要的标记语言被抽象化处理。因此我推荐使用另外一个抽象程度较低的模板框架Handlebars。Handlebars(基于与语言无关的流行模板语言Mustache)不会试图对HTML进行抽象:你编写的是带特殊标签的HTML,Handlebars可以借此插入内容。

为了支持Handlebars,我们要用到Eric Ferraiuolo的 express3-handlebars包(尽管名字中是express3,但这个包在Express 4.0中也可以使用)。在你的项目目录下执行:

npm install --save express3-handlebars

然后在创建app之后,把下面的代码加到meadowlark.js中:

var app = express();// 设置handlebars视图引擎var handlebars = require('express3-handlebars')            .create({ defaultLayout:'main' });app.engine('handlebars', handlebars.engine);app.set('view engine', 'handlebars');

这段代码创建了一个视图引擎,并对Express进行了配置,将其作为默认的视图引擎。接下来创建views目录,在其中创建一个子目录layouts。如果你是一位经验丰富的Web开发人员,可能已经熟悉 布局的概念了(有时也被称为“母版页”)。在开发网站时,每个页面上肯定有一定数量的HTML是相同的,或者非常相近。在每个页面上重复写这些代码不仅非常繁琐,还会导致潜在的维护困境:如果你想在每个页面上做一些修改,那就要修改所有文件。布局可以解决这个问题,它为网站上的所有页面提供了一个通用的框架。

所以我们要给网站创建一个模板。接下来我们创建一个views/layouts/main.handlebars文件:

<!doctype html><html><head>      <title>Meadowlark Travel</title></head><body> {{{body}}}</body></html>

以上内容你未曾见过的可能只有 {{{body}}}。这个表达式会被每个视图自己的HTML取代。在创建Handlebars实例时,我们指明了默认布局( defaultLayout:'main')。这就意味着除非你特别指明,否则所有视图用的都是这个布局。

接下来我们给首页创建视图页面,views/home.handlebars:

<h1 id="Welcome-to-Meadowlark-Travel">Welcome to Meadowlark Travel</h1>

关于页面,views/about.handlebars:

<h1 id="About-Meadowlark-Travel">About Meadowlark Travel</h1>

未找到页面,views/404.handlebars:

<h1 id="Not-Found">404 - Not Found</h1>

最后是服务器错误页面,views/500.handlebars:

<h1 id="Server-Error">500 - Server Error</h1>

提示:你或许想在编辑器中把.handlebars和.hbs (另外一种常见的Handlebars文件扩展名)跟HTML相关联,以便启用语法高亮和其他编辑器特性。如果是vim,你可以在~/.vimrc文件中加上一行 au BufNewFile,BufRead *.handlebars set file type=html。其他编辑器请参考相关文档。

现在视图已经设置好了,接下来我们必须将使用这些视图的新路由替换旧路由:

app.get('/', function(req, res) { res.render('home');});app.get('/about', function(req, res) { res.render('about');});// 404 catch-all处理器(中间件)app.use(function(req, res, next){ res.status(404); res.render('404');});// 500错误处理器(中间件)app.use(function(err, req, res, next){ console.error(err.stack); res.status(500); res.render('500');});

需要注意,我们已经不再指定内容类型和状态码了:视图引擎默认会返回 text/html的内容类型和200的状态码。在catch-all处理器(提供定制的404页面)以及500处理器中,我们必须明确设定状态码。

如果你再次启动服务器检查首页和关于页面,将会看到那些视图已呈现出来。如果你检查源码,将会看到views/layouts/main.handlebars中的套路化HTML。

视图和静态文件

Express靠中间件处理静态文件和视图。只需了解中间件是一种模块化手段,它使得请求的处理更加容易。

static中间件可以将一个或多个目录指派为包含静态资源的目录,其中的资源不经过任何特殊处理直接发送到客户端。你可以在其中放图片、CSS文件、客户端JavaScript文件之类的资源。

在项目目录下创建名为public的子目录 (因为这个目录中的所有文件都会直接对外开放,所以我们称这个目录为public)。接下来,你应该把 static中间件加在所有路由之前:

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

static中间件相当于给你想要发送的所有静态文件创建了一个路由,渲染文件并发送给客户端。接下来我们在public下面创建一个子目录img,并把logo.png文件放在其中。

现在我们可以直接指向/img/logo.png (注意:路径中没有public,这个目录对客户端来说是隐形的), static中间件会返回这个文件,并正确设定内容类型。接下来我们修改一下布局文件,以便让我们的logo出现在所有页面上:

<body>    <header>    <img src="/static/imghwm/default1.png"  data-src="/img/logo.png"  class="lazy" alt="Meadowlark Travel Logo">    </header> {{{body}}}</body>

注释:`是HTML5中引入的元素,它出现在页面顶部,提供一些与内容有关的额外语义信息,比如logo、标题文本或导航等。

视图中的动态内容

视图并不只是一种传递静态HTML的复杂方式(尽管它们当然能做到)。视图真正的强大之处在于它可以包含动态信息。

比如在关于页面上发送“虚拟幸运饼干”。我们在meadowlark.js中定义一个幸运饼干数组:

var fortunes = [  "Conquer your fears or they will conquer you.",  "Rivers need springs.",  "Do not fear what you don't know.",  "You will have a pleasant surprise.", "Whenever possible, keep it simple.",];

修改视图(/views/about.handlebars)以显示幸运饼干:

<h1 id="About-Meadowlark-Travel">About Meadowlark Travel</h1>

Your fortune for the day:

{{fortune}}

接下来修改路由/about,随机发送幸运饼干:

app.get('/about', function(req, res){  var randomFortune = fortunes[Math.floor(Math.random() * fortunes.length)]; res.render('about', { fortune: randomFortune });  );

重启服务器,加载/about页面,你会看到一个随机发放的幸运饼干。模板真的是非常有用。

小结

我们刚用Express创建了一个非常基本的网站。尽管简单,但这个网站包含了功能完备的网站所需的一切。

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
공식 계정 웹 페이지의 캐싱 업데이트에 어려움 : 버전 업데이트 후 사용자 경험에 영향을 미치는 이전 캐시를 피하는 방법은 무엇입니까?공식 계정 웹 페이지의 캐싱 업데이트에 어려움 : 버전 업데이트 후 사용자 경험에 영향을 미치는 이전 캐시를 피하는 방법은 무엇입니까?Mar 04, 2025 pm 12:32 PM

공식 계정 웹 페이지 업데이트 캐시, 이것은 간단하고 간단하며 냄비를 마시기에 충분히 복잡합니다. 공식 계정 기사를 업데이트하기 위해 열심히 노력했지만 사용자는 여전히 기존 버전을 열었습니까? 이 기사에서는이 뒤에있는 비틀기와 회전을 살펴 보고이 문제를 우아하게 해결하는 방법을 살펴 보겠습니다. 읽은 후에는 다양한 캐싱 문제를 쉽게 처리 할 수있어 사용자가 항상 가장 신선한 콘텐츠를 경험할 수 있습니다. 기본 사항에 대해 먼저 이야기 해 봅시다. 액세스 속도를 향상시키기 위해 브라우저 또는 서버는 일부 정적 리소스 (예 : 그림, CSS, JS) 또는 페이지 컨텐츠를 저장합니다. 다음에 액세스 할 때 다시 다운로드하지 않고도 캐시에서 직접 검색 할 수 있으며 자연스럽게 빠릅니다. 그러나 이것은 또한 양날의 검입니다. 새 버전은 온라인입니다.

HTML5 양식 유효성 검사 속성을 사용하여 사용자 입력을 유효성있게하려면 어떻게합니까?HTML5 양식 유효성 검사 속성을 사용하여 사용자 입력을 유효성있게하려면 어떻게합니까?Mar 17, 2025 pm 12:27 PM

이 기사에서는 브라우저에서 직접 사용자 입력을 검증하기 위해 필요한, Pattern, Min, Max 및 Length 한계와 같은 HTML5 양식 검증 속성을 사용하는 것에 대해 설명합니다.

웹 페이지의 PNG 이미지에 뇌졸중 효과를 효율적으로 추가하는 방법은 무엇입니까?웹 페이지의 PNG 이미지에 뇌졸중 효과를 효율적으로 추가하는 방법은 무엇입니까?Mar 04, 2025 pm 02:39 PM

이 기사는 CSS를 사용한 웹 페이지에 효율적인 PNG 테두리 추가를 보여줍니다. CSS는 JavaScript 또는 라이브러리에 비해 우수한 성능을 제공하며, 미묘하거나 눈에 띄는 효과를 위해 테두리 너비, 스타일 및 색상 조정 방법을 자세히 설명합니다.

HTML5의 크로스 브라우저 호환성에 대한 모범 사례는 무엇입니까?HTML5의 크로스 브라우저 호환성에 대한 모범 사례는 무엇입니까?Mar 17, 2025 pm 12:20 PM

기사는 HTML5 크로스 브라우저 호환성을 보장하기위한 모범 사례에 대해 논의하고 기능 감지, 점진적 향상 및 테스트 방법에 중점을 둡니다.

& lt; datalist & gt의 목적은 무엇입니까? 요소?& lt; datalist & gt의 목적은 무엇입니까? 요소?Mar 21, 2025 pm 12:33 PM

이 기사는 HTML & LT; Datalist & GT에 대해 논의합니다. 자동 완성 제안을 제공하고, 사용자 경험을 향상시키고, 오류를 줄임으로써 양식을 향상시키는 요소. 문자 수 : 159

& lt; Progress & Gt의 목적은 무엇입니까? 요소?& lt; Progress & Gt의 목적은 무엇입니까? 요소?Mar 21, 2025 pm 12:34 PM

이 기사는 HTML & lt; Progress & Gt에 대해 설명합니다. 요소, 그 목적, 스타일 및 & lt; meter & gt의 차이; 요소. 주요 초점은 & lt; progress & gt; 작업 완료 및 & lt; meter & gt; Stati의 경우

html5 & lt; time & gt; 의미 적으로 날짜와 시간을 나타내는 요소?html5 & lt; time & gt; 의미 적으로 날짜와 시간을 나타내는 요소?Mar 12, 2025 pm 04:05 PM

이 기사는 html5 & lt; time & gt; 시맨틱 날짜/시간 표현 요소. 인간이 읽을 수있는 텍스트와 함께 기계 가독성 (ISO 8601 형식)에 대한 DateTime 속성의 중요성을 강조하여 Accessibilit를 향상시킵니다.

& lt; meter & gt의 목적은 무엇입니까? 요소?& lt; meter & gt의 목적은 무엇입니까? 요소?Mar 21, 2025 pm 12:35 PM

이 기사는 HTML & lt; meter & gt에 대해 설명합니다. 범위 내에 스칼라 또는 분수 값을 표시하는 데 사용되는 요소 및 웹 개발의 일반적인 응용 프로그램. & lt; meter & gt; & lt; Progress & Gt; 그리고 Ex

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구