在现代 Web 开发中,无服务器架构已经成为了一种趋势。它能够提供更好的可伸缩性、更高的性能和更低的成本。Next.js 是一种流行的 React 框架,可以帮助我们快速构建无服务器应用程序。MongoDB Atlas 是一种云数据库服务,可以提供高可用性、自动扩展和安全性。在本文中,我们将介绍如何使用 Next.js 和 MongoDB Atlas 构建无服务器应用程序。
需求分析
我们需要构建一个简单的 Web 应用程序,该应用程序提供以下功能:
- 用户可以注册并登录。
- 用户可以创建、更新和删除他们的博客文章。
- 用户可以查看所有博客文章。
为了实现这些功能,我们需要使用以下技术:
- Next.js:用于构建 React 应用程序。
- MongoDB Atlas:用于存储用户数据和博客文章数据。
- Express.js:用于构建 API。
环境搭建
首先,我们需要安装 Node.js 和 MongoDB。然后,我们可以使用以下命令创建一个新的 Next.js 项目:
npx create-next-app my-app
在项目的根目录下,我们可以使用以下命令安装 Express.js 和 MongoDB 驱动程序:
npm install express mongodb
MongoDB Atlas 配置
我们需要在 MongoDB Atlas 上创建一个新的集群,并创建一个新的数据库和一个新的用户。然后,我们可以使用以下代码连接到 MongoDB Atlas:
// javascriptcn.com 代码示例 const { MongoClient } = require('mongodb'); const uri = 'mongodb+srv://<username>:<password>@<cluster>.mongodb.net/<database>?retryWrites=true&w=majority'; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); async function connectToDatabase() { try { await client.connect(); console.log('Connected to MongoDB Atlas'); const database = client.db('my-database'); const collection = database.collection('my-collection'); return collection; } catch (error) { console.error(error); } } module.exports = connectToDatabase;
替换 <username>
、<password>
、<cluster>
和 <database>
为你的 MongoDB Atlas 配置信息。
用户认证
我们可以使用 Passport.js 和 bcrypt.js 实现用户认证。Passport.js 是一个流行的 Node.js 认证库,支持多种认证策略,包括本地认证和 OAuth 认证。bcrypt.js 是一个密码哈希库,可以帮助我们存储用户密码的哈希值而不是明文密码。
首先,我们需要安装 Passport.js 和 bcrypt.js:
npm install passport passport-local bcrypt
然后,我们可以使用以下代码实现用户认证:
// javascriptcn.com 代码示例 const passport = require('passport'); const LocalStrategy = require('passport-local').Strategy; const bcrypt = require('bcrypt'); const collection = require('./database')(); passport.use(new LocalStrategy( { usernameField: 'email', passwordField: 'password', }, async (email, password, done) => { try { const user = await collection.findOne({ email }); if (!user) { return done(null, false, { message: 'Incorrect email.' }); } const isMatch = await bcrypt.compare(password, user.password); if (!isMatch) { return done(null, false, { message: 'Incorrect password.' }); } return done(null, user); } catch (error) { return done(error); } }, )); passport.serializeUser((user, done) => { done(null, user._id); }); passport.deserializeUser(async (id, done) => { try { const user = await collection.findOne({ _id: id }); done(null, user); } catch (error) { done(error); } }); module.exports = passport;
API 实现
我们可以使用 Express.js 实现 API。首先,我们需要安装 Express.js:
npm install express
然后,我们可以使用以下代码实现 API:
// javascriptcn.com 代码示例 const express = require('express'); const passport = require('./passport'); const collection = require('./database')(); const app = express(); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(passport.initialize()); app.post('/api/register', async (req, res) => { try { const { email, password } = req.body; const hash = await bcrypt.hash(password, 10); const user = await collection.insertOne({ email, password: hash }); req.login(user.ops[0], (error) => { if (error) { return res.status(500).send(error); } return res.send(user.ops[0]); }); } catch (error) { return res.status(500).send(error); } }); app.post('/api/login', passport.authenticate('local'), (req, res) => { return res.send(req.user); }); app.get('/api/logout', (req, res) => { req.logout(); return res.send('Logged out'); }); app.get('/api/posts', async (req, res) => { try { const posts = await collection.find().toArray(); return res.send(posts); } catch (error) { return res.status(500).send(error); } }); app.post('/api/posts', async (req, res) => { try { const { title, content } = req.body; const post = await collection.insertOne({ title, content }); return res.send(post.ops[0]); } catch (error) { return res.status(500).send(error); } }); app.put('/api/posts/:id', async (req, res) => { try { const { id } = req.params; const { title, content } = req.body; const post = await collection.findOneAndUpdate({ _id: id }, { $set: { title, content } }, { returnOriginal: false }); return res.send(post.value); } catch (error) { return res.status(500).send(error); } }); app.delete('/api/posts/:id', async (req, res) => { try { const { id } = req.params; const post = await collection.findOneAndDelete({ _id: id }); return res.send(post.value); } catch (error) { return res.status(500).send(error); } }); module.exports = app;
页面实现
我们可以使用 React 和 Next.js 实现页面。首先,我们需要安装 React 和 Next.js:
npm install react react-dom next
然后,我们可以使用以下代码实现页面:
// javascriptcn.com 代码示例 import React, { useState } from 'react'; import fetch from 'isomorphic-unfetch'; const Home = ({ posts, user }) => { const [title, setTitle] = useState(''); const [content, setContent] = useState(''); const [message, setMessage] = useState(''); const handleSubmit = async (event) => { event.preventDefault(); const response = await fetch('/api/posts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title, content }), }); const post = await response.json(); setTitle(''); setContent(''); setMessage(`Created post ${post.title}`); }; return ( <> <h1>Welcome to my blog</h1> {user ? ( <> <h2>Create a new post</h2> <form onSubmit={handleSubmit}> <div> <label htmlFor="title">Title:</label> <input id="title" type="text" value={title} onChange={(event) => setTitle(event.target.value)} /> </div> <div> <label htmlFor="content">Content:</label> <textarea id="content" value={content} onChange={(event) => setContent(event.target.value)} /> </div> <button type="submit">Create post</button> </form> {message && <p>{message}</p>} </> ) : ( <p>Please <a href="/login">login</a> to create a new post.</p> )} <h2>Recent posts</h2> <ul> {posts.map((post) => ( <li key={post._id}> <h3>{post.title}</h3> <p>{post.content}</p> </li> ))} </ul> </> ); }; Home.getInitialProps = async ({ req }) => { const baseUrl = req ? `${req.protocol}://${req.get('Host')}` : ''; const response = await fetch(`${baseUrl}/api/posts`); const posts = await response.json(); const user = req ? req.user : null; return { posts, user }; }; export default Home;
总结
在本文中,我们介绍了如何使用 Next.js 和 MongoDB Atlas 构建无服务器应用程序。我们实现了用户认证和 API,并使用 React 和 Next.js 实现了页面。这个应用程序可以帮助我们了解如何使用无服务器架构构建现代 Web 应用程序。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/657100c9d2f5e1655d9ab284