前言
尝试实现前后端通信,前端用 Vite 打包,同时还有热更新功能。后端则是 server.js 脚本。
初始化项目
新建文件夹
1 2
| mkdir [yourprojectName] cd [yourprojectName]
|
初始化项目结构
项目结构大致如下
- Project
- node_modules
- src
- dist
- index.html
- main.js
- style.css
- .gitignore
- server.js
- vite.config.js
- package.json
- README.md
初始化包管理器
安装Vite
基本配置
进入 package.json 文件,没有则创建一个,写入脚本
1 2 3 4 5 6 7 8 9 10 11
| { ... "main": "server.js", "scripts": { "dev:fe": "vite", "build": "vite build", "start": "node server.js", "preview": "vite build && node server.js" }, ... }
|
进入 vite.config.js 文件,没有则创建一个,写入配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import { defineConfig } from 'vite';
export default defineConfig({ root: 'src' build: { outDir: 'dist', emptyOutDir: true, rollupOptions: { input: 'src/index.html', } } });
|
还有其他参数可以填写,详情可见vite官网
创建 .gitignore 文件,阻止不必要文件夹上传,写入以下内容
1 2 3
| node_modules/ dist/ cache/
|
如果已经上传可以写入以下命令取消追踪
1 2 3 4 5
| git rm -r --cached node_modules
git rm -r --cached dist
|
实现简单前后端通信
创建 node.js 服务器
在 server.js 文件中写入以下内容
1 2 3 4 5 6 7 8 9 10 11
| const http = require("http");
const server = http.createServer((req, res) => { res.writeHead(200); res.end('hello world'); });
const port = 3000; server.listen(port, () => { console.log("服务器已经在 https://localhost:3000 启动") });
|
运行以下代码运行服务器
在浏览器输入 localhost:3000 可以看到 hello world 输出
实现 GET 请求
GET 请求会向服务端发出申请,然后服务端返回数据
在 index.html 文件中写入如下内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head>
<body> <div id="result"></div>
<button id="getBtn">获取数据(GET)</button>
<button id="postBtn">发送数据(POST)</button> <script type="module" src="/main.js"></script> </body>
</html>
|
前端脚本 main.js 写入以下内容发出 GET 请求
1 2 3 4 5 6 7 8 9 10 11 12
| const resultDiv = document.querySelector("#result"); const getBtn = document.querySelector("#getBtn");
getBtn.addEventListener("click", async () => { try { const response = await fetch("http://localhost:3000/api/data"); const data = await response.json(); resultDiv.innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>` } catch (error) { resultDiv.innerHTML = `错误:${error.message}`; } });
|
在后端 server.js 文件中的 createServe 函数中写入以下内容处理 GET 请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ... res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') { res.writeHead(200); res.end(); return; }
if (req.method === "GET" && req.url === '/api/data') { res.writeHead(200, {'content-type': 'application/json'}); res.end(JSON.stringify({ message: "来自服务器的问候:hello", data: [1,2,3] })); } ...
|
终端运行 server.js 和前端
1 2 3 4 5
| npm run dev
npm run start
|
进入浏览器地址 localhost:5173 ,点击 “获取数据(GET)” 按钮,可以看到以下输出
1 2 3 4 5 6 7 8
| { "message": "来自服务器的问候:hello", "data": [ 1, 2, 3 ] }
|
实现 POST 请求与其他请求
POST 请求会向服务端传输数据,然后服务端再返回传输结果
前端脚本 main.js 中写入以下内容来使用 POST 请求传输数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const postBtn = document.querySelector("#postBtn");
postBtn.addEventListener("click", async () => { const postDate = {name: "Charlie", age: 28}; try { const response = await fetch("http://localhost:3000/api/data", { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(postDate) }); const data = await response.json(); resultDiv.innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>` } catch (error) { resultDiv.innerHTML = `错误:${error.message}`; } });
|
后端服务器 server.js 中写入以下内容来处理 POST 请求与其他请求 (其他请求返回代码 404)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| ...
else if (req.method === "POST" && req.url === '/api/data') { let body = ""; req.on('data', chaunk => { body += chaunk.toString(); }); req.on('end', () => { try{ const parsedBody = JSON.parse(body); res.writeHead(200, {'content-type': 'application/json'}); res.end(JSON.stringify({ recived: parsedBody, Response: "数据传输成功" })); } catch (error) { res.writeHead(400, {'content-type': 'application/json'}); res.end(JSON.stringify({ error: 'Invalid JSON'})); } }); }
else { res.writeHead(404, {'content-type': 'application/json'}); res.end(JSON.stringify({error:'Not found'})); } ...
|
重启 server.js 服务器 (Vite是热更新,可以不需要重启,按下 Ctrl + C 可以终止任务)
进入浏览器地址 localhost:5173 ,点击 “传输数据(POST)” 按钮,可以看到以下输出
1 2 3 4 5 6 7
| { "recived": { "name": "Charlie", "age": 28 }, "Response": "Data received successfully" }
|
添加一个简单的功能
给这个简陋的系统添加一个计算平方数的功能
在 index.html 页面中加入以下内容来实现输入数据
1 2 3 4
| <div> <label for="countNum">计算平方<input type="number" id="Num"></label> <button id="count">计算</button> </div>
|
前端脚本 main.js 中写入以下内容来将输入的数据传入后端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const countBtn = document.querySelector("#count");
countBtn.addEventListener("click", async () => { const inputmodule = document.querySelector("#Num"); const input = Number(inputmodule.value); console.log(input) try { const response = await fetch("http://localhost:3000/api/count", { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ "num": input }) }); const data = await response.json(); resultDiv.innerHTML = `<pre>计算结果为${data.result}</pre>` } catch (error) { resultDiv.innerHTML = `错误:${error.message}`; } });
|
后端服务器 server.js 中写入以下内容来处理前端传入的数据与实现核心功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| ... else if (req.method === "POST" && req.url === '/api/count') { let buffer = Buffer.alloc(0); req.on('data', chunk => { buffer = Buffer.concat([buffer, chunk]); }); req.on('end', () => { try { const body = buffer.toString(); const parseData = JSON.parse(body);
const receivedNum = parseData.num;
if (typeof receivedNum !== 'number' || isNaN(receivedNum)) { res.writeHead(400, {'content-type': "application/json"}); res.end(JSON.stringify({ error: '传入的必须是数字'})); return; }
const result = countNum(receivedNum);
res.writeHead(200,{'content-type': 'applicaton/json'}); res.end(JSON.stringify({result: result})); } catch (error) { console.log('JSON解析失败',error.message); res.writeHead(400, {'content-type': 'application/json'}); res.end(JSON.stringify({ error: 'Invalid JSON'})); } }); } ...
function countNum (input) { return input*input; }
|
这样一个简单的平方运算功能就实现了。
结语
折腾半天终于也是成功实现了简单的前后通信。为了整这个中途还去了解了一些 http 相关的东西。
哦对了,写完后还自动引入了其他模块,所有引入的模块如下:
1 2 3 4
| const { error } = require("console"); const { write } = require("fs"); const http = require("http"); const { writeHeapSnapshot } = require("v8");
|