二、为您的项目安装强大的工具

以下是查尔斯·F·凯特林的一句名言:

“我对未来感兴趣,因为我将在那里度过余生。”

这位杰出的发明家在我们开始思考如何编写软件之前就给软件工程师留下了一条最重要的建议。然而,半个世纪后,我们仍然在弄清楚为什么我们最终会得到意大利面条代码或“意大利面条心智模型”

您是否曾经遇到过这样的情况:您从以前的开发人员那里继承了代码,并花费数周时间试图了解一切是如何工作的,因为没有可用的蓝图,并且伪自解释代码变得难以调试?更好的是,该项目不断增长,其复杂性也在不断增长。做出或破坏更改是危险的,没有人愿意触碰“丑陋”的遗留代码。重写整个代码库的成本太高,因此当前的代码库每天都会引入新的 bug 修复和补丁。维护软件的成本远远高于开发软件的原始成本。

为今天的未来编写软件意味着什么?我认为这可以归结为创建一个简单的心智模型,它不会改变,不管你的项目随着时间的推移变得有多大。当项目规模增大时,复杂性始终保持不变。这个心智模型就是你的蓝图,一旦你理解了它,你就会明白你的软件是如何工作的。

如果你看看现代网络开发,特别是前端开发,你会发现我们生活在一个激动人心的时代。互联网公司和个人开发者正在解决开发速度和成本与代码和用户体验质量之间的问题。

2013 年,Facebook 发布了一个用于构建用户界面的开源 JavaScript 库。您可以在上阅读更多相关信息 http://facebook.github.io/react/ 。2015 年初,Facebook 的 Tom Occhino 总结了 React 如此强大的原因:

“React 将命令式 API 包装为声明式 API。React 的真正威力在于它如何让您编写代码。”

声明式编程可以减少代码。它告诉计算机做什么而不指定如何做,而命令式编程风格描述如何做。调用 domapi 的 JavaScript 就是命令式编程的一个例子。jQuery 就是另一个这样的例子。

Facebook 与 Instagram 和其他公司一起,多年来一直在生产中使用 React。它也适用于小项目;下面是使用 React:构建的购物列表示例 http://fedosejev.github.io/shopping-list-react 。我认为 React 是用于构建用户界面的最好的 JavaScript 库之一,目前可供开发人员使用。

我的目标是让你了解 React 的基本原理。为了实现这一点,我将一次向您介绍一个 React 概念,解释它,并展示如何应用它。我们将一步一步地构建一个实时 web 应用,在此过程中提出重要问题,并讨论 React 为我们提供的解决方案。

您将了解 Flux/Redux 和单向数据流。与 Flux/Redux 和 React 一起,我们将创建一个可预测和可管理的代码库,您可以通过添加新特性来扩展它,而无需扩展其复杂性。无论您以后添加了多少新功能,web 应用工作方式的心智模型都将保持不变。

与任何新技术一样,有些东西的工作方式与您习惯的方式非常不同。React 也不例外。事实上,React 的一些核心概念看起来可能违反直觉、发人深省,甚至像是倒退。不要急于下结论。正如您所料,经验丰富的 Facebook 工程师在生产中构建并在业务关键型应用中使用 React,他们对 React 的工作原理进行了大量思考。我给你的建议是在学习反应的同时保持头脑开放,我相信在这本书的结尾,这些新概念会逐渐适应并对你有很大的意义。

请加入我的学习之旅,并听从查尔斯·F·凯特林的建议。让我们关心我们的未来!

接近我们的项目

我坚信,学习新技术的最佳动机是一个让你兴奋不已的项目,而你迫不及待地想要建立这个项目。作为一名经验丰富的开发人员,您可能已经构建了许多成功的商业项目,这些项目共享某些产品功能、设计模式,甚至目标受众。在这本书中,我希望你建立一个项目,感觉像呼吸新鲜空气。一个你在日常工作中最不可能构建的项目。这必须是一个有趣的尝试,它不仅能教育你,还能满足你的好奇心,拓展你的想象力。然而,假设你是一个忙碌的专业人士,这个项目对你来说也不应该是一个耗时的、长期的承诺。

输入Snapterest——一个 web 应用,允许您发现和收集 Twitter 上发布的公共照片。把想象成一个 Pinterest(www.Pinterest.com,图片的唯一来源是 Twitter。我们将实施具有以下核心功能的全功能网站:

  • 实时接收和显示推文
  • 在集合中添加和删除推文
  • 查看收集的推文
  • 将推文集合导出为可共享的 HTML 片段

当你开始一个新项目时,你要做的第一件事就是准备好你的工具。对于这个项目,我们将使用一些您可能不熟悉的工具,所以让我们讨论一下它们是什么,以及如何安装和配置它们。

如果您在安装和配置本章中的工具和模块时遇到任何问题,请转至https://github.com/PacktPublishing/React-Essentials-Second-Edition 并创建新版本;描述您正在做的事情以及您收到的错误消息。我相信我们的社区会帮助你解决你的问题。

在本书中,我假设您正在使用 Macintosh 或 Windows 计算机。如果您是 Unix 用户,那么您很可能非常了解软件包管理器,并且安装本章将介绍的工具应该非常容易。

让我们从 Node.js 的安装开始。

安装 Node.js 和 npm

Node.js是一个允许我们使用客户端语言编写服务器端应用的平台,我们都熟悉 JavaScript。然而,Node.js 的真正好处在于它使用了事件驱动的非阻塞 I/O 模型,这非常适合构建数据密集型实时应用。这意味着使用 Node.js,我们应该能够处理推文的传入流,并在推文到达后立即进行处理;这正是我们的项目所需要的。

让我们安装 Node.js。我们将使用 8.7.0 版,因为在编写本书时,这是 Node.js 的最新版本。Jest 是一个来自 Facebook 的测试框架,您将在第 9 章中学习,使用 Jest测试 React 应用。

从以下链接之一下载操作系统的安装包:

运行下载的包并按照 Node.js 将提示您的安装步骤进行操作。完成后,检查是否已成功安装 Node.js。打开终端/命令提示符,然后键入以下命令:

node -v

输出如下(如果您的版本不完全匹配,请不要担心):

V8.7.0

Node.js 有一个非常丰富的模块生态系统,可供我们使用。模块是一个 Node.js 应用,可以在自己的 Node.js 应用中重用。在撰写本文时,共有 50 多万个模块。如何管理如此丰富多样的 Node.js 模块?认识npm,一个管理 Node.js 模块的包管理器。事实上,npm 是与 Node.js 一起提供的,所以您已经安装了它。在终端/命令提示符中键入以下内容:

npm -v

您应该看到以下输出(如果您的版本不完全匹配,请不要担心):

5.5.1

您可以在www.npmjs.com了解更多关于 npm 的信息。现在我们准备开始安装 Node.js 应用。

安装 Git

在本书中,我们将使用 Git 安装 Node.js 模块。如果您尚未安装 Git,请访问https://git-scm.com/book/en/v2/Getting-Started-Installing-Git 并按照操作系统的安装说明进行操作。

从推特流媒体 API 获取数据

React 应用的数据将来自 Twitter。Twitter 有一个流式 API,任何人都可以插入并开始接收 JSON 格式的无限公共推文流。

要开始使用 Twitter 流媒体 API,您需要执行以下步骤:

  1. 创建一个 Twitter 帐户。为此,请转至https://twitter.com 注册;或者,如果您已经拥有帐户,请登录。
  2. 导航到创建新的 Twitter 应用 https://apps.twitter.com ,点击新建 App。您需要填写应用详细信息表格,同意开发者协议,然后点击创建您的 Twitter 应用。现在您应该看到应用的页面。切换到键和访问令牌选项卡。

在本页面的应用设置部分,您将发现两条重要信息:

  • 消费者密钥(API 密钥),例如jqRDrAlKQCbCbu2o4iclpnvem
  • 消费者机密(API 机密),例如wJcdogJih7uLpjzcs2JtAvdSyCVlqHIRUWI70aHOAf7E3wWIgD

记下这些;我们将在本章后面需要它们。

现在我们需要生成一个访问令牌。在同一页上,您将看到您的访问令牌部分为空。点击创建我的访问令牌按钮。它创建两条信息:

  • 接入令牌,例如12736172-R017ah2pE2OCtmi46IAE2n0z3u2DV6IqsEcPa0THR
  • 接入令牌秘密,例如4RTJJWIezIDcs5VX1PMVZolXGZG7L3Ez7Iz1gMdZucDaM

也要记下这些。访问令牌是您独有的,您不应与任何人共享。保密。

现在我们已经具备了开始使用 Twitter 流媒体 API 所需的一切。

使用 Snapkite 引擎过滤数据

您通过推特流 API 接收的推文数量超出了您的消费量,因此我们需要找到一种方法,将该数据流过滤成一组有意义的推文,我们可以显示并与之交互。我建议您快速浏览上的推特流媒体 API 文档 https://dev.twitter.com/streaming/overview ,特别是,请看本页面,该页面描述了如何在处过滤传入流 https://dev.twitter.com/streaming/reference/post/statuses/filter 。你会注意到,Twitter 提供的过滤器很少,我们可以应用,所以我们需要找到一种方法来进一步过滤数据流。

幸运的是,有一个 Node.js 应用就是为了这个。它叫斯内普凯特发动机。它连接到 Twitter 流 API,使用可用的过滤器并根据您定义的规则对其进行过滤,并将过滤后的推文输出到 web 套接字连接。我们建议的 React 应用可以侦听套接字连接上的事件,并在推文到达时处理推文。

让我们安装 Snapkite 引擎。首先,您需要克隆 Snapkite 引擎存储库。克隆意味着您正在将源代码从 GitHub 服务器复制到本地目录。在本书中,我将假设您的本地目录是您的主目录。打开终端/命令提示符并键入以下命令:

cd ~
git clone https://github.com/snapkite/snapkite-engine.git

这将创建~/snapkite-engine/文件夹。我们现在将安装snapkite-engine所依赖的所有其他节点模块。其中一个是node-gyp模块。根据您使用的平台(Unix 或 Windows),您需要安装此网页上列出的其他工具:https://github.com/TooTallNate/node-gyp#installation

一旦您安装了它们,您就可以安装node-gyp模块了:

npm install -g node-gyp

现在导航到~/snapkite-engine目录:

cd snapkite-engine/

然后运行以下命令:

npm install

此命令将安装 Snapkite 引擎所依赖的 Node.js 模块。现在让我们配置 Snapkite 引擎。假设您在~/snapkite-engine/目录中,通过运行以下命令将./example.config.json文件复制到./config.json

cp example.config.json config.json

或者,如果您使用的是 Windows,请运行以下命令:

copy example.config.json config.json

在您喜爱的文本编辑器中打开config.json。现在我们将编辑配置属性。让我们从trackKeywords开始。这是我们将告诉什么关键字,我们要跟踪。如果我们想跟踪"my"关键字,那么设置如下:

"trackKeywords": "my"

接下来,我们需要设置 Twitter 流 API 密钥。将consumerKeyconsumerSecretaccessTokenKeyaccessTokenSecret设置为创建推特应用时保存的键。其他属性可以设置为默认值。如果您想了解它们是什么,请查看位于的 Snapkite 引擎文档 https://github.com/snapkite/snapkite-engine

我们的下一步是安装 Snapkite 过滤器。Snapkite Filter是一个 Node.js 模块,根据一组规则验证推文。有很多 Snapkite 过滤器,我们可以使用它们的任意组合来过滤我们喜欢的推特流。您可以在找到所有可用 Snapkite 过滤器的列表 https://github.com/snapkite/snapkite-filters

在我们的应用中,我们将使用以下 Snapkite 过滤器:

让我们安装它们。导航到~/snapkite-engine/filters/目录:

cd ~/snapkite-engine/filters/

然后通过运行以下命令克隆所有 Snapkite 筛选器:

git clone https://github.com/snapkite/snapkite-filter-is-possibly-sensitive.git
git clone https://github.com/snapkite/snapkite-filter-has-mobile-photo.git
git clone https://github.com/snapkite/snapkite-filter-is-retweet.git
git clone https://github.com/snapkite/snapkite-filter-has-text.git

下一步是配置它们。为此,您需要为每个 Snapkite 过滤器创建一个配置文件,格式为JSON格式,并在其中定义一些属性。幸运的是,每个 Snapkite 过滤器都附带一个示例配置文件,我们可以根据需要复制和编辑该文件。假设您在~/snapkite-engine/filters/目录中,运行以下命令(在 Windows 上使用copy并将正向斜杠替换为反向斜杠):

cp snapkite-filter-is-possibly-sensitive/example.config.json snapkite-filter-is-possibly-sensitive/config.json
cp snapkite-filter-has-mobile-photo/example.config.json snapkite-filter-has-mobile-photo/config.json
cp snapkite-filter-is-retweet/example.config.json snapkite-filter-is-retweet/config.json
cp snapkite-filter-has-text/example.config.json snapkite-filter-has-text/config.json

我们不需要更改这些config.json文件中的任何默认设置,因为它们已经配置为适合我们的用途。

最后,我们需要告诉 Snapkite 引擎它应该使用哪些 Snapkite 过滤器。在文本编辑器中打开~/snapkite-engine/config.json文件并查找:

"filters": []

现在将其替换为以下内容:

"filters": [
  "snapkite-filter-is-possibly-sensitive",
  "snapkite-filter-has-mobile-photo",
  "snapkite-filter-is-retweet",
  "snapkite-filter-has-text"
]

做得好!您已成功安装带有多个 Snapkite 筛选器的 Snapkite 引擎。现在让我们检查一下是否可以运行它。导航到~/snapkite-engine/并运行以下命令:

npm start

您应该不会看到错误消息,但如果您看到了错误消息,并且不确定如何修复它们,请转到https://github.com/fedosejev/react-essentials/issues ,创建一个新问题,复制并粘贴您收到的错误消息。

接下来,让我们设置项目的结构。

创建项目结构

现在是创建我们的项目结构的时候了。组织源文件听起来可能很简单,但是经过深思熟虑的项目结构组织可以帮助我们理解应用的底层架构。在本书后面的部分,当我们讨论 Flux 应用体系结构时,您将看到一个这样的示例。让我们首先在主目录~/snapterest/中创建名为snapterest的根项目目录。

然后,我们将在其中创建另外两个目录:

  • ~/snapterest/source/:在这里,我们将存储我们的源 JavaScript 文件
  • ~/snapterest/build/:在这里,我们将放置编译好的 JavaScript 文件和一个 HTML 文件

现在,在~/snapterest/source/内,创建components/文件夹,使您的项目结构如下所示:

  • ~/snapterest/source/components/
  • ~/snapterest/build/

现在,当我们准备好基本的项目结构后,让我们开始用应用文件填充它。首先,我们需要在~/snapterest/source/目录中创建我们的主应用文件app.js。此文件将成为我们的应用~/snapterest/source/app.js的入口点。

暂时让它空着,因为我们有更紧迫的事情要讨论。

创建 package.json

你以前听说过 D.R.Y.吗?它代表着不要重复自己,它促进了软件开发代码重用的核心原则之一。最好的代码是您不需要编写的代码。事实上,我们在这个项目中的目标之一就是尽可能少地编写代码。您可能还没有意识到这一点,但 React 有助于我们实现这一目标。这不仅节省了我们的时间,而且如果我们还决定在将来维护和改进我们的项目,从长远来看,这将为我们节省更多的时间。

在不编写代码时,我们可以采用以下策略:

  • 以声明式编程风格编写代码
  • 重用他人编写的代码

在这个项目中,我们将使用这两种技术。第一个由 React 本身覆盖。React 让我们别无选择,只能以声明式风格编写 JavaScript 代码。这意味着,我们不需要告诉我们的 web 浏览器如何做我们想做的事情(就像我们用 jQuery 做的那样),而只需要告诉它我们想让它做什么,然后用 React 解释如何做。这是我们的胜利。

js 和 npm 涵盖了第二种技术。我在本章前面提到过,我们可以使用数十万个不同的 Node.js 应用。这意味着很可能有人已经实现了我们的应用所依赖的功能。

问题是,从哪里获得我们想要重用的所有 Node.js 应用?我们可以通过npm install <package-name>命令安装它们。在 npm 上下文中,Node.js 应用称为,每个npm 包都有一个package.json文件,该文件描述了与该包关联的元数据。您可以通过了解更多关于package.json中存储的字段的信息 https://docs.npmjs.com/files/package.json

在我们安装依赖项包之前,我们将为我们自己的项目初始化一个包。通常,只有当您想将包提交到 npm 注册表,以便其他人可以重用您的 Node.js 应用时,才需要package.json。我们不会构建 Node.js 应用,也不会将项目提交给 npm。请记住,package.json在技术上只是一个npm命令可以理解的元数据文件,因此,我们可以使用它来存储应用所需的依赖项列表。一旦我们在package.json中存储了依赖项列表,我们就可以随时使用npm install命令轻松安装它们;npm 将自动确定从何处获取它们。

我们如何为自己的应用创建package.json文件?幸运的是,npm 附带了一个交互式工具,它会问我们一些问题,然后根据我们的答案,为我们的项目创建package.json

确保您位于~/snapterest/目录中。在终端/命令提示符下,运行以下命令:

npm init

它会问你的第一件事是你的包名。它将建议一个默认名称,即您所在目录的名称。在我们的情况下,它应该是name: (snapterest)。按输入接受建议的默认名称(snapterest。下一个问题是您的包的版本,即version: (1.0.0)。按进入。如果我们计划将我们的包提交给 npm 供其他人重用,这两个字段将是最重要的字段。因为我们不会将其提交给 npm,所以我们可以自信地接受所有问题的默认设置。继续按回车直到npm init完成执行并退出。然后,如果你转到你的~/snapterest/目录,你会在那里找到一个新文件—package.json

现在,我们已经准备好安装其他要重用的 Node.js 应用。由多个单个应用构建的应用称为模块化,而单个应用称为模块化。这就是我们将从现在起称为 Node.js 依赖项的 on-Node.js 模块。

重用 Node.js 模块

正如我前面提到的,在我们的开发过程中会有一个叫做大楼的步骤。在这一步中,我们的 build 脚本将获取我们的源文件和所有 Node.js 依赖项包,并将它们转换为 web 浏览器可以成功执行的单个文件。这个构建过程中最重要的部分被称为包装。但我们需要包装什么?为什么?让我们考虑一下。我在前面简要地提到,我们并没有创建 Node.js 应用,但我们讨论的是重用 Node.js 模块。这是否意味着我们将在 nonNode.js 应用中重用 Node.js 模块?这可能吗?事实证明,有一种方法可以做到这一点。

Webpack是一种用于将所有依赖项文件捆绑在一起的工具,您可以在客户端 JavaScript 应用中重用 Node.js 模块。您可以在了解更多关于网页的信息 http://webpack.js.org 。要安装 Webpack,请从~/snapterest/目录中运行以下命令:

npm install --save-dev webpack

注意--save-dev标志。它告诉 npm 将 Webpack 作为开发依赖项添加到我们的package.json文件中。将模块名作为依赖项添加到我们的package.json文件中可以记录我们正在使用的依赖项,如果需要,我们可以稍后使用npm install命令轻松地安装它们。运行应用所需的依赖项与开发应用所需的依赖项之间存在区别。Webpack 在构建时使用,而不是在运行时使用,因此它是一个开发依赖项。因此,使用--save-dev标志。如果您现在检查package.json文件的内容,您将看到以下内容(如果您的网页版本不完全匹配,请不要担心):

"devDependencies": {
  "webpack": "^2.2.1"
}

请注意,npm 在您的~/snapterest/目录中创建了一个名为node_modules的新文件夹。这是它放置所有本地依赖模块的地方。

祝贺您安装了第一个 Node.js 模块!Webpack 将允许我们在客户端 JavaScript 应用中使用 Node.js 模块。这将是我们构建过程的一部分。现在让我们仔细看看我们的构建过程。

带网页的大楼

今天,任何现代的客户端应用都代表了由各种技术单独解决的许多问题的混合体。单独解决每个问题简化了管理项目复杂性的整个过程。这种方法的缺点是,在项目的某个时候,您需要将所有单独的部分组合到一个连贯的应用中。就像汽车工厂中的机器人用单个零件组装汽车一样,开发人员有一种称为构建工具的东西,可以用单个模块组装他们的项目。这个过程被称为构建过程,根据项目的规模和复杂性,构建过程可能需要几毫秒到几小时。

Webpack 将帮助我们自动化构建过程。首先,我们需要配置 Webpack。假设您在~/snapterest/目录中,创建一个新的webpack.config.js文件。

现在让我们在webpack.config.js文件中描述我们的构建过程。在这个文件中,我们将创建一个 JavaScript 对象,描述如何绑定源文件。我们希望将该配置对象导出为 Node.js 模块。是的,我们将把我们的webpack.config.js文件视为 Node.js 模块。为此,我们将空配置对象分配给一个特殊的module.exports属性:

const path = require('path'); 
module.exports = {};

module.exports属性是 Node.js API 的一部分。这是一种告诉 Node.js,无论何时有人导入我们的模块,他们都可以访问该对象的方式。那么这个物体应该是什么样子呢?在这里,我建议您查看一下 Webpack 的文档,并从以下链接阅读关于 Webpack 的核心概念:https://webpack.js.org/concepts/

配置对象的第一个属性是entry属性:

module.exports = {
  entry: './source/app.js',
};

顾名思义,entry属性描述了 web 应用的入口点。在我们的例子中,这个属性的值是./source/app.js——这是启动应用的第一个文件。

配置对象的第二个属性是output属性:

output: {
  path: path.resolve(__dirname, 'build'),
  filename: 'snapterest.js'
},

output属性告诉 Webpack 在哪里输出生成的捆绑文件。在我们的例子中,我们要说的是,我们希望生成的 bundle 文件被称为snapterest.js,并且应该保存到./build目录中。

Webpack 将每个源文件视为一个模块,这意味着我们所有的 JavaScript 源文件都将被视为 Webpack 需要捆绑在一起的模块。我们如何向 Webpack 解释这一点?

我们通过配置对象的第三个属性module来实现这一点:

module: {
  rules: [
    {
      test: /\.js$/,
      use: [
        {
          loader: 'babel-loader',
          options: {
            presets: ['react', 'latest'],
            plugins: ['transform-class-properties']
          }
        }
      ],
      exclude: path.resolve(__dirname, 'node_modules')
    }
  ]
}

如您所见,我们的module属性获取一个对象作为其值。此对象有一个名为rules的属性—一个规则数组,其中每个规则描述如何从不同的源文件创建网页包模块。让我们仔细看看我们的规则。

我们有一条规则告诉 Webpack 如何处理源 JavaScript 文件:

{
  test: /\.js$/,
  use: [
    {
      loader: 'babel-loader',
      options: {
        presets: ['react', 'latest'],
        plugins: ['transform-class-properties']
      }
    }
  ],
  exclude: path.resolve(__dirname, 'node_modules')
}

此规则有三个属性:testuseexcludetest属性告诉 Webpack 此规则适用于哪些文件。它通过将源文件名与我们指定为test属性/\.js$/值的正则表达式匹配来实现这一点。如果您熟悉 RegEx,那么您会发现/\.js$/将匹配所有以.js结尾的文件名。这正是我们想要的:捆绑所有 JavaScript 文件。

当 Webpack 查找并加载所有源 JavaScript 文件时,它会尝试将它们解释为普通 JavaScript 文件。但是,我们的 JavaScript 文件不是普通的 JavaScript 文件,而是具有 ECMAScript 2016 语法以及特定于 React 的语法。

Webpack 如何理解所有非编程 JavaScript 语法?在 Webpack 加载器的帮助下,我们可以将非编程 JavaScript 语法转换为普通 JavaScript。网页包加载器是应用于源文件的转换。我们的use属性描述了我们想要应用的转换列表:

use: [
  {
    loader: 'babel-loader',
    options: {
      presets: ['react', 'latest'],
      plugins: ['transform-class-properties']
    }
  }
],

我们有一个转换负责将 React 特定语法和 ECMAScript 2016 语法转换为纯 JavaScript:

{
  loader: 'babel-loader',
  options: {
    presets: ['react', 'latest'],
    plugins: ['transform-class-properties']
  }
}

网页包转换使用具有loaderoptions属性的对象进行描述。loader属性告诉 Webpack 哪个加载程序执行转换,options属性告诉它哪些选项应该传递给该加载程序。将转换 ECMAScript 2016 并将特定语法转换为纯 JavaScript 的加载程序称为babel-loader。这种特定的转换过程称为transfilation源代码到源代码编译——它将以一种语法编写的源代码转换为以另一种语法编写的源代码。我们正在使用当今最流行的 JavaScript 传输工具之一,称为巴贝尔https://babeljs.io 。Webpack 有一个 Babel 加载程序,它使用 Babel transpiler 来转换我们的源代码。Babel loader 作为一个单独的 Node.js 模块提供。让我们安装此模块并将其添加到开发依赖项列表中。假设您在~/snapterest/目录中,运行以下命令:

npm install babel-core babel-loader --save-dev

我们的网页包加载器的options属性有两个巴贝尔礼物:latestreact以及一个巴贝尔transform-class-properties插件:

options: {
  presets: ['react', 'latest'],
  plugins: ['transform-class-properties']
}

这些是传输不同语法的 Babel 插件:latest插件将 ECMAScript 2015、ECMAScript 2016 和 ECMAScript 2017 的语法传输到旧 JavaScript 语法,react插件传输文件将特定语法转换为普通 JavaScript 语法,transform-class-properties插件传输文件类属性。

这些 Babel 插件作为独立的 Node.js 模块分发,我们需要单独安装。假设您在~/snapterest/目录中,运行以下命令:

npm install babel-preset-latest babel-preset-react babel-plugin-transform-class-properties --save-dev

最后,我们的网页包规则中有第三个属性,名为exclude

exclude: path.resolve(__dirname, 'node_modules')

此属性告诉 Webpack 从转换过程中排除node_modules目录。

现在我们的webpack.config.js文件准备好了。在我们第一次运行捆绑过程之前,让我们在我们的package.json文件中添加一个名为start的新脚本:

"scripts": {
  "start": "webpack -p --config webpack.config.js",
  "test": "echo \"Error: no test specified\" && exit 1"
},

现在,如果您运行npm run startnpm start,npm 将运行webpack -p --config webpack.config.js命令。此命令运行 Webpack,该 Webpack 使用webpack.config.js文件将源文件打包用于生产。

我们已经准备好打包源文件了!导航到您的~/snapterest/目录并运行以下命令:

npm start

在输出中,您应该看到以下内容:

Version: webpack 2.2.1
Time: 1151ms
 Asset       Size  Chunks             Chunk Names
app.js  519 bytes       0  [emitted]  main
 [0] ./source/app.js 24 bytes {0} [built]

更重要的是,如果你检查你的项目的~/snapterest/build/目录,你会注意到它现在有snapterest.js文件,里面已经有一些代码,这是我们的(空的)JavaScript 应用,其中有一些 Node.js 模块,可以在 web 浏览器中运行!

创建网页

如果你渴望得到一些好东西,那么我有好消息要告诉你!我们快到了。剩下要做的就是创建一个链接到我们的snapterest.js脚本的index.html

~/snapterest/build/目录中创建index.html文件。向其中添加以下 HTML 标记:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge, chrome=1" />
    <title>Snapterest</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  </head>
  <body>
    <div id="react-application">
      I am about to learn the essentials of React.js.
    </div>
    <script src="./snapterest.js"></script>
  </body>
</html>

在 web 浏览器中打开~/snapterest/build/index.html。您应该看到以下文字:我将学习 React.js的要点。没错,我们已经完成了项目的设置,是时候了解一下了!

总结

在本章中,您了解了为什么我们应该使用 React 为现代 web 应用构建用户界面。然后,我们讨论了我们将在本书中构建的项目。最后,我们安装了所有正确的工具并创建了项目的结构。

在下一章中,我们将安装 React,仔细了解 React 的工作原理,并创建第一个 React 元素。