二、准备开发环境

在使用 MERN 堆栈构建应用之前,我们首先需要准备各种技术的开发环境,以及辅助开发和调试的工具。本章指导您了解工作区选项、基本开发工具、如何在工作区中设置 MERN 技术,以及使用实际代码检查此设置的步骤。

我们将讨论以下主题:

  • 工作区选项
  • 代码编辑器
  • Chrome 开发工具
  • Git 设置
  • MongoDB 设置
  • 节点设置
  • 完成 MERN 堆栈的 npm 模块
  • 检查 MERN 设置的代码

选择开发工具

在选择基本开发工具(如文本编辑器或 IDE、版本控制软件,甚至开发工作区本身)时,有很多选项可用。在本节中,我们将介绍与 MERN web 开发相关的选项和建议,以便您在根据个人偏好选择这些工具时做出明智的决策。

工作区选项

在本地计算机上开发是程序员最常见的做法,但是随着良好的云开发服务的出现,例如 Cloud9(https://aws.amazon.com/cloud9/?origin=c9io ),现在可以使用其中一个或两个。您可以使用 MERN 技术设置您的本地工作区,本书的其余部分将假设这种情况,但您也可以选择在为节点开发配备的云服务中运行和开发代码

本地和云开发

您可以选择使用这两种类型的工作区来享受在本地工作的好处,而不必担心带宽/互联网问题,也可以选择在没有自己喜欢的本地机器的情况下远程工作。为此,您可以使用 Git 对代码进行版本控制,将最新代码存储在远程 Git 托管服务(如 GitHub 或 BitBucket)上,然后在所有工作区共享相同的代码。

IDE 或文本编辑器

大多数云开发环境将与源代码编辑器集成。但是对于您的本地工作区,您可以根据自己作为程序员的喜好选择任何工作区,然后为 MERN 开发定制它。例如,可以根据需要自定义以下常用选项:

  • 原子https://atom.io/ :GitHub 的免费开源文本编辑器,有许多其他开发人员提供的 MERN stack 相关软件包
  • 升华文本https://www.sublimetext.com/ :一个专有的跨平台文本编辑器,也有许多与 MERN 堆栈相关的软件包,以及对 JavaScript 开发的支持
  • Visual Studio 代码https://code.visualstudio.com/ :由 Microsoft 提供的功能丰富的源代码编辑器,广泛支持现代 web 应用开发工作流,包括对 MERN stack 技术的支持
  • 网络风暴https://www.jetbrains.com/webstorm/ :JetBrains 提供的一个成熟的 JavaScript IDE,支持基于 MERN 堆栈的开发

Chrome 开发工具

加载、查看和调试前端是 web 开发过程中非常关键的一部分。Chrome 开发者工具是 Chrome 浏览器的一部分,它有许多强大的功能,可以调试、测试和试验前端代码,以及 UI 的外观、感觉、响应能力和性能。此外,React Developer Tools 扩展作为一个 Chrome 插件提供,它将 React 调试工具添加到 Chrome Developer 工具中

吉特

如果没有能够跟踪代码更改、代码共享和协作的版本控制系统,任何开发工作流都是不完整的。多年来,Git 已经成为许多开发人员事实上的版本控制系统,并且是使用最广泛的分布式源代码管理工具。对于本书中的代码开发,Git 将主要帮助我们在构建每个应用的过程中跟踪进度。

安装

要开始使用 Git,首先根据系统规范在本地计算机或云开发环境中安装它。下载和安装最新 Git 的相关说明,以及使用 Git 命令的文档,请访问:https://git-scm.com/downloads

远程 Git 托管服务

基于云的 Git 存储库托管服务(如 GitHub 和 BitBucket)可帮助您在工作区和部署环境中共享最新代码,并备份代码。这些服务包含许多有用的特性,以帮助代码管理和开发工作流。首先,您可以创建一个帐户并为代码库设置远程存储库

一旦您在工作区中完成必要的设置并开始构建 MERN 应用,所有这些基本工具将丰富您的 web 开发工作流程并提高生产率。

建立 MERN 堆栈技术

随着本书的编写,MERN stack 技术正在开发和升级,因此对于本书中演示的工作,我们使用了编写时最新的稳定版本。大多数这些技术的安装指南取决于工作区的系统环境,因此本节指向所有相关的安装资源,并作为设置功能齐全的 MERN 堆栈的指南。

蒙哥达

在将任何数据库功能添加到 MERN 应用之前,必须在开发环境中设置并运行 MongoDB。在撰写本文时,MongoDB 的当前稳定版本是 3.6.3,本版本的 MongoDB 社区版用于开发本书中的应用。本节其余部分提供了有关如何安装和运行 MongoDB 的资源。

安装

您需要在工作区上安装并启动 MongoDB,以便能够将其用于开发。MongoDB 的安装和启动过程取决于工作区规范:

运行 mongo shell

mongoshell 是 MongoDB 的交互式工具,也是熟悉 MongoDB 操作的好地方。安装并运行 MongoDB 后,您可以在命令行上运行mongoshell。在mongoshell 中,您可以尝试使用命令查询和更新数据以及执行管理操作。

节点

MERN 应用的后端服务器实现依赖于节点和 npm。在撰写本文时,8.11.1 是可用的最新稳定节点版本,它与 npm 版本 5.6.0 捆绑在一起。但是,npm 可用的最新版本是 5.8.0,因此在安装 Node 之后,npm 将需要升级,如下节所述。

安装

可以通过直接下载、安装程序或节点版本管理器安装节点:

  • 您可以通过直接下载源代码或特定于您的工作区平台的预构建安装程序来安装 Node。可从nodejs.org/en/download下载。
  • 云开发服务可能预装了节点,比如在 Cloud9 中,或者会有添加和更新节点的具体说明。

要测试安装是否成功,您可以打开命令行并运行node -v查看它是否正确返回版本号。

升级 npm 版本

要安装 npm 版本 5.8.0,请从命令行运行以下安装命令,并使用npm -v检查版本:

npm install -g npm@5.8.0 
npm -v

使用 nvm 进行节点版本管理

如果需要为不同的项目维护多个版本的 Node 和 npm,nvm 是一个有用的命令行工具,可以在同一个工作区上安装和管理不同的版本。您必须单独安装 nvm。有关设置说明,请访问:github.com/creationix/nvm

MERN 的 npm 模块

其余的 MERN stack 技术都可以作为 npm 模块使用,并且可以使用npm install添加到每个项目中。其中包括运行每个 MERN 应用所需的关键模块,如 React 和 Express,以及开发过程中所需的模块。在本节中,我们列出并讨论这些模块,然后在下一节中了解如何在工作项目中使用这些模块。

关键模块

要集成 MERN 堆栈技术并运行您的应用,我们需要以下 npm 模块:

  • React:要开始使用 React,我们需要两个模块:
    • react
    • react-dom
  • Express:要在代码中使用 Express,您需要express模块
  • MongoDB:要在节点应用中使用 MongoDB,还需要添加驱动程序,驱动程序可以作为名为mongodb的 npm 模块提供

依赖模块

为了在 MERN 应用的整个开发过程中保持一致性,我们将在整个堆栈中使用 JavaScript ES6。因此,为了帮助开发过程,我们将使用以下附加 npm 模块编译和捆绑代码,并在开发过程中更新代码时自动重新加载服务器和浏览器应用:

  • 将 ES6 和 JSX 转换为适用于所有浏览器的 JavaScript 需要 Babel 模块。让巴贝尔工作所需的模块包括:

    • babel-core
    • babel-loader用于使用网页包传输 JavaScript 文件
    • babel-preset-envbabel-preset-reactbabel-preset-stage-2提供对 React、最新 JS 功能以及一些 stage-x 功能的支持,例如声明babel-preset-env当前未涵盖的类字段
  • Webpack 模块将有助于为客户端和服务器端代码绑定已编译的 JavaScript。使 Web 包正常工作所需的模块包括:

    • webpack
    • webpack-cli运行网页包命令
    • webpack-node-externals捆绑到网页包时忽略外部节点模块文件
    • webpack-dev-middleware在代码开发过程中,通过连接的服务器为 Web 包发出的文件提供服务
    • webpack-hot-middleware通过将浏览器客户端连接到网页包服务器并在开发过程中接收代码更改时的更新,将热模块重新加载到现有服务器中
  • nodemon在开发过程中观察服务器端的变化,因此可以重新加载服务器以使变化生效
  • react-hot-loader在客户端进行更快的开发。每次 React 前端中的文件发生更改时,react-hot-loader都会启用浏览器应用进行更新,而无需重新绑定整个前端代码。

Although react-hot-loader is meant for aiding development flow, it is safe to install this module as a regular dependency rather than a devDependency. It automatically ensures hot reloading is disabled in production and the footprint is minimal.

检查开发设置

在本节中,我们将逐步介绍开发工作流程并编写代码,以确保正确设置环境以开始开发和运行 MERN 应用。

我们将在以下文件夹结构中生成这些项目文件,以运行简单的安装项目:

| mern-simplesetup/
  | -- client/
    | --- HelloWorld.js
    | --- main.js
  | -- server/
    | --- devBundle.js
    | --- server.js
  | -- .babelrc
  | -- nodemon.json
  | -- package.json
  | -- template.js
  | -- webpack.config.client.js
  | -- webpack.config.client.production.js
  | -- webpack.config.server.js

The code discussed in this section is available on GitHub in the repository at: github.com/shamahoque/mern-simplesetup. You can clone this code and run it as you go through the code explanations in the rest of this chapter. 

初始化 package.json 并安装 npm 模块

我们将首先使用 npm 安装所有必需的模块。最佳做法是在每个项目文件夹中添加一个package.json文件,以维护、记录和共享 MERN 应用中使用的 npm 模块。package.json文件将包含有关应用的元信息,并列出模块依赖项。

执行以下步骤生成package.json文件,对其进行修改,并使用其安装 npm 模块:

  • npm init:从命令行输入项目文件夹并运行npm init。您将被问到一系列问题,然后一个package.json文件将自动生成您的答案。
  • dependencies:在编辑器中打开package.json并修改 JSON 对象,添加关键模块和react-hot-loader作为常规dependencies

The file path mentioned before a code block indicates the location of the code in the project directory. This convention has been maintained throughout the book to provide better context and guidance as you follow along with the code.

mern-simplesetup/package.json

"dependencies": {
   "express": "^4.16.3",
    "mongodb": "^3.0.7",
    "react": "^16.3.2",
    "react-dom": "^16.3.2",
    "react-hot-loader": "^4.1.2"
}
  • devDependencies:进一步修改package.json将开发过程中需要的以下 npm 模块添加为devDependencies

mern-simplesetup/package.json

"devDependencies": {
    "babel-core": "^6.26.2",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1",
    "nodemon": "^1.17.3",
    "webpack": "^4.6.0",
    "webpack-cli": "^2.0.15",
    "webpack-dev-middleware": "^3.1.2",
    "webpack-hot-middleware": "^2.22.1",
    "webpack-node-externals": "^1.7.2"
}
  • npm install:保存package.json并从命令行运行npm install以获取所有这些模块并将其添加到您的项目中。

配置 Babel、Webpack 和 Nodemon

在开始编写 web 应用之前,我们需要配置 Babel、Webpack 和 Nodemon,以便在开发过程中编译、绑定和自动重新加载代码中的更改。

巴别塔

在项目文件夹中创建一个.babelrc文件,并添加以下指定了presetsplugins的 JSON。

mern-simplesetup/.babelrc

{
    "presets": [
      "env",
      "stage-2"
      "react"
    ],
    "plugins": [
      "react-hot-loader/babel"
    ]
}

react-hot-loader模块需要react-hot-loader/babel插件来编译React组件。

网页包

我们必须配置 Webpack,以便将客户端和服务器代码以及客户端代码分别绑定到生产代码中。在项目文件夹中创建webpack.config.client.jswebpack.config.server.jswebpack.config.client.production.js文件。所有三个文件都将具有以下代码结构:

const path = require('path')
const webpack = require('webpack')
const CURRENT_WORKING_DIR = process.cwd()

const config = { ... }

module.exports = config

configJSON 对象将因特定于客户端或服务器端代码、开发代码和生产代码的值而不同。

用于开发的客户端网页包配置

在您的webpack.config.client.js文件中用以下内容更新config对象,以便在开发期间配置用于捆绑和热加载 React 代码的 Webpack

mern-simplesetup/webpack.config.client.js

const config = {
    name: "browser",
    mode: "development",
    devtool: 'eval-source-map',
    entry: [
        'react-hot-loader/patch',
        'webpack-hot-middleware/client?reload=true',
        path.join(CURRENT_WORKING_DIR, 'client/main.js')
    ],
    output: {
        path: path.join(CURRENT_WORKING_DIR , '/dist'),
        filename: 'bundle.js',
        publicPath: '/dist/'
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: [
                    'babel-loader'
                ]
            }
        ]
    }, plugins: [
          new webpack.HotModuleReplacementPlugin(),
          new webpack.NoEmitOnErrorsPlugin()
      ]
}
  • modeprocess.env.NODE_ENV设置为给定值,并告知 Webpack 相应地使用其内置优化。如果未明确设置,则默认为值'production'。也可以通过命令行将该值作为 CLI 参数传递来进行设置。
  • devtool指定如何生成源映射(如果有)。通常,源映射提供了一种将压缩文件中的代码映射回其在源文件中的原始位置的方法,以帮助调试。
  • entry指定 Webpack 开始绑定的入口文件,在本例中是与client文件夹中的main.js文件绑定
  • output指定捆绑代码的输出路径,在本例中设置为dist/bundle.js
  • publicPath允许指定应用中所有资产的基本路径。
  • module设置用于传输的文件扩展名的正则表达式规则,以及要排除的文件夹。此处使用的发丝工具为babel-loader
  • HotModuleReplacementPlugin启用react-hot-loader的热模块更换。
  • NoEmitOnErrorsPlugin允许在出现编译错误时跳过发射。

服务器端网页包配置

修改代码要求nodeExternals,并在webpack.config.server.js文件中用以下内容更新config对象,以配置绑定服务器端代码的 Webpack。

mern-simplesetup/webpack.config.server.js

const config = {
    name: "server",
    entry: [ path.join(CURRENT_WORKING_DIR , './server/server.js') ],
    target: "node",
    output: {
        path: path.join(CURRENT_WORKING_DIR , '/dist/'),
        filename: "server.generated.js",
        publicPath: '/dist/',
        libraryTarget: "commonjs2"
    },
    externals: [nodeExternals()],
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: [ 'babel-loader' ]
            }
        ]
    }
}

此处未明确设置mode选项,但在运行 Webpack 命令时会根据需要传递mode选项,该命令涉及为开发而运行或为生产而构建。

Webpack 从服务器文件夹开始与server.js绑定,然后在dist文件夹的server.generated.js中输出绑定代码。

用于生产的客户端网页包配置

为了准备用于生产的客户端代码,请在webpack.config.client.production.js文件中使用以下代码更新config对象。

mern-simplesetup/webpack.config.client.production.js

const config = {
    mode: "production",
    entry: [
        path.join(CURRENT_WORKING_DIR, 'client/main.js')
    ],
    output: {
        path: path.join(CURRENT_WORKING_DIR , '/dist'),
        filename: 'bundle.js',
        publicPath: "/dist/"
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: [
                    'babel-loader'
                ]
            }
        ]
    }
}

这将配置 Webpack,以便将 React 代码捆绑在生产模式中使用,在生产模式中不再需要热重新加载插件或调试配置。

诺德蒙

在项目文件夹中创建一个nodemon.js文件,并添加以下配置

mern-simplesetup/nodemon.js

{
    "verbose": false,
    "watch": [ "./server" ],
    "exec": "webpack --mode=development --config 
    webpack.config.server.js 
                && node ./dist/server.generated.js"
}

此配置将设置nodemon以在开发期间监视服务器文件中的更改,然后根据需要执行编译和构建命令。

带有 React 的前端视图

为了开始开发前端,首先在项目文件夹中创建一个名为template.js的根模板文件,该文件将呈现包含React组件的 HTML。

mern-simplesetup/template.js

export default () => {
    return `<!doctype html>
      <html lang="en">
        <head>
          <meta charset="utf-8">
          <title>MERN Kickstart</title>
        </head>
        <body>
          <div id="root"></div>
          <script type="text/javascript" src="/dist/bundle.js"> 
       </script>
        </body>
      </html>` 
} 

当服务器收到对根 URL 的请求时,该 HTML 模板将在浏览器中呈现,ID 为"root"div元素将包含我们的React组件。

接下来,创建一个client文件夹,我们将在其中添加两个 React 文件main.jsHelloWorld.js

main.js文件只是呈现 HTML 文档中div元素中的顶级条目React组件。

mern-simplesetup/client/main.js

import React from 'react'
import { render } from 'react-dom'
import HelloWorld from './HelloWorld'

render(<HelloWorld/>, document.getElementById('root'))

在这种情况下,条目React组件是从HelloWorld.js导入的HelloWorld组件。

HelloWorld.js包含一个基本的HelloWorld组件,该组件热导出以在开发过程中启用react-hot-loader的热重新加载。

mern-simplesetup/client/HelloWorld.js

import React, { Component } from 'react'
import { hot } from 'react-hot-loader'

class HelloWorld extends Component {
   render() {
     return (
         <div>
             <h1>Hello World!</h1>
         </div>
     ) 
   }
}

export default hot(module)(HelloWorld)

要在服务器收到对根 URL 的请求时查看浏览器中呈现的React组件,我们需要使用 Webpack 和 Babel 设置来编译和绑定此代码,并添加服务器端代码,用绑定的代码响应根路由请求。

带有 Express 和 Node 的服务器

在项目文件夹中,创建一个名为server的文件夹,并添加一个名为server.js的文件,用于设置服务器。然后,添加另一个名为devBundle.js的文件,该文件将帮助在开发模式下使用 Webpack 配置编译 React 代码

快速应用

server.js中,我们将首先添加代码导入express模块,以初始化 Express app。

mern-simplesetup/server/server.js

import express from 'express'

const app = express()

然后,我们将使用此 Express 应用构建节点服务器应用的其余部分。

在开发过程中捆绑应用

为了简化开发流程,我们将在服务器运行时初始化 Webpack 以编译客户端代码。在devBundle.js中,我们将设置一个编译方法,将 Express app 配置为使用 Webpack 中间件编译、捆绑和服务代码,并在开发模式下启用热重新加载。

mern-simplesetup/server/devBundle.js

import webpack from 'webpack'
import webpackMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import webpackConfig from './../webpack.config.client.js'

const compile = (app) => {
  if(process.env.NODE_ENV == "development"){
    const compiler = webpack(webpackConfig)
    const middleware = webpackMiddleware(compiler, {
      publicPath: webpackConfig.output.publicPath
    })
    app.use(middleware)
    app.use(webpackHotMiddleware(compiler))
  }
}

export default {
  compile
}

我们将在server.js中通过在开发模式下添加以下行来调用此编译方法。

mern-simplesetup/server/server.js

import devBundle from './devBundle'
const app = express()
devBundle.compile(app)

这两条突出显示的行仅用于开发模式,在为生产构建应用代码时应注释掉。在开发模式下,当这些行被执行时,Webpack 将编译并捆绑 React 代码以将其放置在dist/bundle.js中。

为 dist 文件夹中的静态文件提供服务

Webpack 将在开发和生产模式下编译客户端代码,然后将捆绑的文件放在dist文件夹中。为了使这些静态文件在客户端请求时可用,我们将在server.js中添加以下代码来服务dist/folder中的静态文件。

mern-simplesetup/server/server.js

import path from 'path'
const CURRENT_WORKING_DIR = process.cwd()
app.use('/dist', express.static(path.join(CURRENT_WORKING_DIR, 'dist')))

在根目录下呈现模板

当服务器收到根 URL/的请求时,我们将在浏览器中呈现template.js。在server.js中,将以下路线处理代码添加到 Express app,以在/接收 GET 请求。

mern-simplesetup/server/server.js

import template from './../template'
app.get('/', (req, res) => {
     res.status(200).send(template())
})

最后,添加服务器代码以在指定端口上侦听传入请求。

mern-simplesetup/server/server.js

let port = process.env.PORT || 3000
app.listen(port, function onStart(err) {
  if (err) {
    console.log(err) 
  }
  console.info('Server started on port %s.', port)
})

将服务器连接到 MongoDB

要将您的节点服务器连接到 MongoDB,请将以下代码添加到server.js,并确保您的工作区中运行了 MongoDB。

mern-simplesetup/server/server.js

import { MongoClient } from 'mongodb'
const url = process.env.MONGODB_URI || 'mongodb://localhost:27017/mernSimpleSetup'
MongoClient.connect(url, (err, db)=>{
  console.log("Connected successfully to mongodb server")
  db.close()
})

在此代码示例中,MongoClient是使用url连接到正在运行的MongoDB实例的驱动程序,允许我们在后端实现与数据库相关的代码。

npm 运行脚本

更新package.json文件,为开发和生产添加以下 npm 运行脚本。

mern-simplesetup/package.json

"scripts": {
    "development": "nodemon",
    "build": "webpack --config webpack.config.client.production.js 
                 && webpack --mode=production --config 
     webpack.config.server.js",
    "start": "NODE_ENV=production node ./dist/server.generated.js"
}
  • npm run development:此命令将获取 Nodemon、Webpack,并启动服务器进行开发
  • npm run build:这将为生产模式生成客户端和服务器代码包(在运行此脚本之前,请确保从server.js中删除devBundle.compile代码)
  • npm run start:此命令将在生产中运行捆绑代码

实时开发与调试

要运行迄今为止开发的代码,并确保一切正常,您可以执行以下步骤:

  1. 从命令行npm run development运行应用。
  2. 在浏览器中加载:在浏览器中打开根 URL,如果您使用的是本地机器设置,则为http://localhost:3000。您应该会看到一个标题为 MERN Kickstart 的页面,它只显示 Hello World!。
  3. 开发代码并现场调试:将HelloWorld.js组件文本'Hello World!'更改为'hello'。保存更改以在浏览器中查看即时更新,同时检查命令行输出以查看bundle.js是否未重新创建。类似地,您还可以在更改服务器端代码时看到即时更新,从而提高开发过程中的生产率。

如果您已经做到了这一点,恭喜您,您已经准备好开始开发激动人心的 MERN 应用了。

总结

在本章中,我们讨论了开发工具选项以及如何安装 MERN 技术,然后编写代码检查开发环境是否正确设置。

我们首先研究了适合 web 开发的推荐工作区、IDE、版本控制软件和浏览器选项。作为开发人员,您可以根据自己的偏好从这些选项中进行选择。

接下来,我们通过首先安装 MongoDB、Node 和 npm,然后使用 npm 添加其余必需的库来设置 MERN 堆栈技术。

在继续编写代码检查此设置之前,我们配置了 Webpack 和 Babel,以便在开发过程中编译和捆绑代码,并构建可用于生产的代码。我们了解到,在浏览器上打开应用之前,有必要编译用于开发 MERN 应用的 ES6 和 JSX 代码。

此外,我们通过将 React Hot Loader 用于前端开发、配置 Nodemon 用于后端开发以及在开发期间运行服务器时在一个命令中编译客户端和服务器代码,使开发流程更加高效。

在下一章中,我们将使用此设置开始构建一个框架 MERN 应用,该应用将作为全功能应用的基础。