首页 前端知识 Nodejs Express.js 快速入门(详细流程)

Nodejs Express.js 快速入门(详细流程)

2025-03-10 12:03:14 前端知识 前端哥 893 492 我要收藏

一、简介

  • 安装 nodejs,推荐使用 nvm 管理安装。

二、创建项目(方式一:空项目手动创建)

  • 新建项目文件夹 express-democd 进入文件夹后,使用命令创建 package.json 文件:

    # 进入项目文件夹执行下面初始化命令,二选一即可,反正创建了可以后期调整的
    $ cd express-demo
    
    # 方式一:需要调整初始配置
    $ npm init
    
    # 方式二:直接默认初始配置不进行调整
    $ npm init -y
    
  • 安装 express

    $ npm install express --save
    
  • 创建入口文件 index.js 或 app.js 都行,package.json 中的默认入口文件叫 index.js,如果改了记得同步就行。

    在这里插入图片描述

  • 基本使用 express

    const express = require('express')
    const app = express()
    
    app.get('/', (req, res) => {
      res.send('Hello World!')
    })
    
    app.listen(3000, () => {
      console.log("启动成功!")
    })
    
  • 运行并访问 http://localhost:3000

    $ node index.js
    
  • 也可以到 package.jsonscripts 里面加个 start 指令,使用指令运行,访问结果一样:

    • package.json 添加指令

      "scripts": {
          "start": "node index.js",
          "test": "echo \"Error: no test specified\" && exit 1"
      }
      
    • 运行项目并访问 http://localhost:3000/

      $ npm run start
      

三、创建项目(方式二:Express 项目生成器)

  • 安装生成器

    $ npm install -g express-generator
    
  • 创建项目,会有一个初始的目录结构

    $ express express-demo
    
  • 进入项目安装依赖

    $ cd express-demo
    
    $ npm i
    
  • 运行项目并访问 http://localhost:3000/

    $ npm run start
    

四、支持热更新

  • nodejs 本身并不直接支持热更新(Hot Reloading),但可以通过一些工具和方法来实现热更新功能,使得代码在修改后无需重新启动服务器即可自动生效。

    $ npm install --save-dev nodemon
    
  • 在项目的 package.json 中添加一个启动脚本:

    {
      "scripts": {
        "dev": "nodemon app.js"
      }
    }
    
  • 运行项目并访问 http://localhost:3000/,然后尝试修改下代码,这样就不需要每次修改后重启项目才会生效了,只需要在开发阶段使用即可

    $ npm run dev
    

五、路由基础

  • 路由示例

    const express = require('express')
    const app = express()
    
    app.get('/', (req, res) => {
      // req: 请求对象, res:响应对象
      res.send('Hello World!')
    })
    

    这就是一个基本路由。在 Express 中,路由指的是客户端请求服务器处理函数之间的映射关系。

  • Express 中的路由由 3 部分组成,分别是请求类型请求地址处理函数

    app.METHOD(PATH, HANDLER)
    

    例如:

    app.get('/', function (req, res) {
      res.send('Hello World!')
    })
    
    app.post('/', function (req, res) {
      res.send('Got a POST request')
    })
    
    app.get('/user', function (req, res) {
      res.send('Got a GET request at /user')
    })
    
    app.post('/user', function (req, res) {
      res.send('Got a POST request at /user')
    })
    

六、路由使用

  • 最基础的用法,就是把路由挂载到 app

    const express = require('express')
    const app = express()
    
    app.get('/', (req, res) => {
      res.send('Hello World!')
    })
    
    app.listen(3000, () => {
      console.log("启动成功!")
    })
    
  • 稍微复杂一点的就是模块化路由,为了方便对路由进行管理,不建议将路由直接挂载到 app 上,而是推荐将路由抽离为单独的模块,主要有以下几个步骤:

    (1)创建路由模块对应的 .js 文件

    (2)调用 express.Router() 创建路由对象

    (3)向路由对象上挂载具体的路由

    (4)使用 module.exports 向外共享路由对象

    (5)使用 app.use() 函数注册路由模块

    • 示例

      例如:创建一个 routes 文件夹,里面根据功能模块创建不同的 .js 文件,每个文件里存放对应处理的路由。

      在这里插入图片描述

      // routes/index.js
      
      var express = require('express');
      var router = express.Router();
      
      // 该模块的 默认 路由
      router.get('/', function(req, res, next) {
        res.send('respond with a resource - /');
      });
      
      // 该模块的 /show 路由
      router.get('/show', function(req, res, next) {
        res.send('respond with a resource - /show');
      });
      
      module.exports = router;
      
      // routes/users.js
      
      var express = require('express');
      var router = express.Router();
      
      // 该模块的 默认 路由
      router.get('/', function(req, res, next) {
        res.send('respond with a resource - /users');
      });
      
      // 该模块的 /show 路由
      router.get('/show', function(req, res, next) {
        res.send('respond with a resource - /users/show');
      });
      
      module.exports = router;
      
      // index.js
      
      const express = require('express')
      const app = express()
      
      // 导入模块化路由
      var indexRouter = require('./routes/index');
      var usersRouter = require('./routes/users');
      
      // 注册路由,可以不给路由模块添加前缀或添加更长的前缀,都是可以的
      
      // 不添加前缀,其实默认就是 '/'
      app.use(indexRouter);
      // 模块内部路由:/ ,访问路径为 http://localhost:3000
      // 模块内部路由:/show,访问路径为 http://localhost:3000/show
      
      // 添加前缀
      app.use('/', indexRouter);
      // 模块内部路由:/ ,访问路径为 http://localhost:3000
      // 模块内部路由:/show,访问路径为 http://localhost:3000/show
      
      // 添加前缀
      app.use('/users', usersRouter); 
      // 模块内部路由:/ ,访问路径为 http://localhost:3000/users
      // 模块内部路由:/show,访问路径为 http://localhost:3000/users/show
      
      // 添加更长的前缀
      app.use('/my/users', usersRouter); 
      // 模块内部路由:/ ,访问路径为 http://localhost:3000/my/users
      // 模块内部路由:/show,访问路径为 http://localhost:3000/my/users/show
      
      // 处理未匹配到的路由,返回 404
      app.use((req, res) => {
        res.status(404).send('404 Not Found');
      });
      
      // 监听端口
      app.listen(3000, () => {
        console.log("启动成功!")
      })
      
  • 当多个 ip 同时请求进来的时候,可以通过控制并发数量、负载均衡之类的进行处理,这里给个基础案例

    在这个例子中,虽然多个客户端同时请求 /data/:id 接口,Node.js 会异步处理每个请求,不会阻塞其他请求。

    const express = require('express');
    const app = express();
    const port = 3000;
    
    // 模拟一个异步数据库查询函数
    const fetchDataFromDatabase = (id) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(`Data for ID ${id}`);
        }, 1000);  // 假设数据库查询需要 1 秒钟
      });
    };
    
    app.get('/data/:id', async (req, res) => {
      const id = req.params.id;
      try {
        const data = await fetchDataFromDatabase(id);  // 异步查询
        res.json({ data });
      } catch (error) {
        res.status(500).send('Internal Server Error');
      }
    });
    
    app.listen(port, () => {
      console.log(`Server is running on http://localhost:${port}`);
    });
    

七、中间件

  • 中间件(Middleware),指业务流程的中间处理环节。说白了就是一堆方法,接收客户端发来费请求,可以对该请求做出响应,也可以继续交给下一个中间件进行处理。

    主要由两部分组成:中间件方法请求处理函数

    举例:中间件是需要设置注册的,没有注册就不用管。原理就是请求一个 Get 路由 /users,在进入 /users 路由之前会通过注册好的 全局中间件 判断是否还要继续,如果继续也就是调用 next(),则进入注册好的 app.get 中间件 继续判断,通过层层中间件判断,最后来到 /users 路由中进行处理并返回数据。

  • 中间件的书写顺序

    中间件必须写在路由前面,写在后面就不会生效了。

  • 中间件调用顺序

    中间件的调用顺序不是按 先全局中间件再 app.get 中间件 这么个顺序来的,而是 先注册的中间件先调用(即按代码中定义的顺序执行),上面只是举例。

  • 对特定 url 使用中间件(局部中间件)

    //【app.get 中间件】只会处理 get 请求过来的 /users 路由
    app.get('/users', (req, res, next) => {
      console.log("进入中间件!")
      // 向下执行
      next()
    })
    
    //【app.use 中间件】会处理所有请求方法(如 GET、POST、PUT 等)请求过来的 /users 路由
    // app.use('/users', (req, res, next) => {
    //   console.log("进入中间件!")
    //   // 向下执行
    //   next()
    // })
    
    //【路由】
    app.get('/users', (req, res)=> {
      res.send("Hello World!")
    })
    

    还可以这么写:

    //【路由】与【app.get 中间件】结合
    app.get('/users', (req, res, next) => {
      console.log("进入中间件!")
      // 向下执行
      next()
    }, (req, res)=> {
      res.send("Hello World!")
    })
    

    还可以这么写:

    // 手动实现【app.get 中间件】
    app.use((req, res, next) => {
      if (req.method === 'GET') {
        console.log('GET Request')
        // 继续处理 GET 请求
        next()
      } else {
        res.status(405).send('Method Not Allowed') // 如果不是 GET 请求,返回 405 错误
      }
    })
    
    // 路由
    app.get('/users', (req, res)=> {
      res.send("Hello World!")
    })
    
  • 使用 app.use 设置全局生效的中间件

    // 接收所有的请求的中间件(全局生效)
    app.use((req, res, next) => {
      console.log('请求进入 app.use 中间件!')
      next()
    })
    
    // 当客户端访问 /users 请求的时候走当前中间件
    app.use('/users', (req, res, next) => {
      console.log('请求进入 app.use /users 中间件!')
      next()
    })
    
    app.get('/users', (req, res)=> {
      res.send("Hello World!");
    })
    
  • 中间件执行顺序与规则

    访问 http://localhost:3000/users 只会走 /users 的中间件。

    访问 http://localhost:3000/users/show 则会走 /users/users/show 两个中间件,且从上到下先注册先走。

    // 导入模块化路由
    var indexRouter = require('./routes/index');
    var usersRouter = require('./routes/users');
    
    // 给 /users 路径添加一个中间件
    app.use('/users', (req, res, next) => {
      console.log('进入 /users 路径的中间件')
      // 继续执行后续的中间件或路由
      next()
    })
    
    // 给 /users/show 路径添加一个中间件
    app.use('/users/show', (req, res, next) => {
      console.log('进入 /users/show 路径的中间件')
      // 继续执行后续的中间件或路由
      next()
    })
    
    // 注册路由
    app.use('/', indexRouter);
    app.use('/users', usersRouter);
    

八、静态页面返回(404 页面等)

  • 首先创建一个静态文件夹,用于存放网站静态资源(如 HTMLCSSJS 文件)。比如可以创建一个 public 文件夹,这个文件夹名没固定要求。

    /project-directory
        /public
            /index.html
            /style.css
            /script.js
            /404.html
        /app.js
    
  • 然后进行配置使用

    const express = require('express')
    const path = require('path')
    const app = express()
    
    // 设置静态页面,默认就是 '/' 路由
    app.use(express.static(path.join(__dirname, 'public')));
    // 设置一个路由,访问结果一样的
    app.use('/static', express.static(path.join(__dirname, 'public')));
    // 如果 public 文件夹内有其他静态文件,比如 style.css 和 script.js,也可以通过 URL 访问它们,例如:
    // http://localhost:3000/style.css
    // http://localhost:3000/script.js
    
    // 处理未匹配到的路由,返回 404 页面
    app.use((req, res) => {
      // res.status(404).send('404 Not Found')
      res.status(404).sendFile(path.join(__dirname, 'public/404.html'))
    })
    
    // 监听端口
    app.listen(3000, () => {
      console.log("启动成功!")
    })
    

    在这里插入图片描述

八、动态页面返回

  • 动态页面 Express 提供了与多种模板引擎的集成支持,如 EJSPug(之前称为 Jade)Handlebars 等,自行了解吧,感觉用处不大,也可以选择其他框架的 SSR 开发。

十、PM2 挂载

  • # Nodejs PM2 基本使用(快速上手)

十一、数据库链接使用

  • 数据库本地自行安装好环境。

  • MongoDB (NoSQL)

    $ npm install mongoose
    
    const mongoose = require('mongoose');
    
    // 连接到 MongoDB 数据库
    mongoose.connect('mongodb://localhost:27017/testDB', { useNewUrlParser: true, useUnifiedTopology: true });
    
    // 定义一个 Schema
    const userSchema = new mongoose.Schema({
      name: String,
      age: Number
    });
    
    // 创建一个模型
    const User = mongoose.model('User', userSchema);
    
    // 插入数据
    const newUser = new User({ name: 'Alice', age: 30 });
    newUser.save()
      .then(() => console.log('User saved'))
      .catch(err => console.error('Error saving user:', err));
    
  • MySQL / MariaDB

    如果使用的是 MariaDB,你也可以使用同样的库,因为 MySQL2 兼容 MariaDB

    $ npm install mysql2
    
    const mysql = require('mysql2');
    
    // 创建连接
    const connection = mysql.createConnection({
      host: 'localhost',
      user: 'root',
      database: 'test'
    });
    
    // 查询数据
    connection.query('SELECT * FROM users', (err, results, fields) => {
      if (err) {
        console.error(err);
      } else {
        console.log(results);
      }
    });
    
    // 插入数据
    connection.query(
      'INSERT INTO users (name, age) VALUES (?, ?)',
      ['Alice', 30],
      (err, results) => {
        if (err) {
          console.error(err);
        } else {
          console.log('Inserted row:', results.insertId);
        }
      }
    );
    
    // 关闭连接
    connection.end();
    
  • SQLite

    $ npm install sqlite3
    
    const sqlite3 = require('sqlite3').verbose();
    
    // 打开或创建数据库
    let db = new sqlite3.Database('./test.db');
    
    // 创建一个表
    db.run("CREATE TABLE IF NOT EXISTS users (id INT, name TEXT, age INT)");
    
    // 插入数据
    let stmt = db.prepare("INSERT INTO users VALUES (?, ?, ?)");
    stmt.run(1, 'Alice', 30);
    stmt.finalize();
    
    // 查询数据
    db.each("SELECT * FROM users", (err, row) => {
      console.log(row.id + ": " + row.name + " - " + row.age);
    });
    
    // 关闭数据库
    db.close();
    
转载请注明出处或者链接地址:https://www.qianduange.cn//article/23095.html
标签
express
评论
发布的文章

面试题之强缓存协商缓存

2025-03-11 15:03:21

【C语言】数组篇

2025-03-11 15:03:19

正则表达式(复习)

2025-03-11 15:03:17

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!