了解node.js还得追溯到 2009 年,一个名叫 Ryan Dahl 的开发者,决定要创造一种全新的方式来运行 JavaScript —— 不是在浏览器里,而是在服务器端。他利用 Google 的 Chrome V8 引擎,创造了一个神奇的东西,叫做 Node.js。
1、随着 Node.js 的日渐流行,开发者们开始渴望一个简单的方式来分享和管理他们的代码。于是,Isaac Schlueter 创造了 npm (Node Package Manager),从此 Node.js 的世界变得更加丰富多彩。
2、2011年,10月11日:Node.js 0.6.0 版本发布,标志着 npm 成为了一个稳定的工具。这就像是一场盛大的派对,庆祝 Node.js 正式步入成熟阶段。
3、截至 2024 年,Node.js 已经成为一个成熟且备受推崇的平台,被广泛应用于各种场景,从简单的 Web 服务器到复杂的实时应用程序。npm 作为最大的软件注册中心,支持着全球数百万开发者的工作。
Node.js 的故事就像是一个不断发展的传奇,它不仅改变了 Web 开发的方式,也激励着一代又一代的开发者不断探索新的可能。
区别:exports 是 module.exports 的别名。默认情况下,module.exports 是一个空对象。
使用:可以通过 module.exports 替换整个对象,或者通过 exports 添加成员。
示例:
// module.js
module.exports={ name: 'John Doe' };
// 或者
exports.name='John Doe';
以下是一个简单的包示例:
package.json
{
"name": "szh-utils",
"version": "1.0.1",
"main": "index.js",
"description": "我的第一个工具包",
"keywords": ["szh", "format", "escape"],
"license": "ISC"
}
index.js
const dateFormat=require('./dateFormat');
const escape=require('./htmlEscape');
module.exports={
...dateFormat,
...escape
};
dateFormat.js
module.exports={
format: function(date, fmt) {
// 格式化日期的逻辑
}
};
htmlEscape.js
module.exports={
escape: function(str) {
// 转义 HTML 字符串的逻辑
},
unescape: function(str) {
// 反转义 HTML 字符串的逻辑
}
};
以上就是如何简单的创建一个 Node.js 包,并通过require引入模块,以及如何使用exports和module.exports来暴露模块成员。
NPM 是 Node.js 的包管理器,它不仅帮助 Node.js 社区管理和分发第三方模块,还为开发者提供了一个强大的工具集来处理模块的安装、更新、版本控制等问题。借助 NPM,Node.js 和第三方模块之间形成了一个良好的生态系统。
cnpm (淘宝镜像):
i5ting_toc 是一个将 Markdown 文档转换成带有目录的 HTML 页面的小工具。
当在 Node.js 中使用require()函数引入模块时,Node.js 会按照以下顺序搜索模块:
检查当前目录下的 node_modules 文件夹:
递归地向上查找:
如果仍未找到模块:
如果还是找不到:
通过这种方式,Node.js 确保了模块可以在项目的任何层级被正确地找到和使用。
Web项目封装为PC客户端,其中一种方式就是运用 node-webkit 。
node-webkit 是一个基于node.js和 chromium的应用程序运行环境,通过它我们可以把建立在chrome浏览器和node.js上的web应用打包成桌面应用,也就是我们所说的客户端,而且还支持跨平台。
————————————————
3.新建一个index.html 文件
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script language="javascript" type="text/javascript">
// 以下方式直接跳转
window.location.href='https://blog.csdn.net/qq_41464123';
</script>
</body>
</html>
package.json完整代码
{
/**指定程序的起始页面。*/
"main": "index.html",
/**字符串必须是小写字母或者数字,可以包含.或者_或者-不允许带空格。name必须全局唯一。*/
"name": "OA",
/**程序描述*/
"description": "OA办公系统",
/**程序版本号*/
"version": "1.0.0",
/**关键字*/
"keywords": ["demo","node-webkit"],
/**bool值,如果设置为false,将禁用webkit的node支持。*/
"nodejs": true,
/**
* 指定一个node.js文件,当程序启动时,该文件会被运行,启动时间要早于node-webkit加载html的时间。
* 它在node上下文中运行,可以用它来实现类似后台线程的功能。
* (不需要可注释不用)
*/
//"node-main": "js/node.js",
/**
* bool值。默认情况下,如果将node-webkit程序打包发布,那么只能启动一个该应用的实例。
* 如果你希望允许同时启动多个实例,将该值设置为false。
*/
"single-instance": true,
/**窗口属性设置 */
"window": {
/**字符串,设置默认title。*/
"title": "OA",
/**窗口的icon。*/
"icon": "img/tubiao.ico.png",
/**bool值。是否显示导航栏。*/
"toolbar": false,
/**bool值。是否允许调整窗口大小。*/
"resizable": true,
/**是否全屏*/
"fullscreen": false,
/**是否在win任务栏显示图标*/
"show_in_taskbar": false,
/**bool值。如果设置为false,程序将无边框显示。*/
"frame": true,
/**字符串。窗口打开时的位置,可以设置为“null”、“center”或者“mouse”。*/
"position": "center",
/**主窗口的的宽度。*/
"width": 1920,
/**主窗口的的高度。*/
"height": 1080,
/**窗口的最小宽度。*/
"min_width": 400,
/**窗口的最小高度。*/
"min_height": 335,
/**窗口显示的最大宽度,可不设。
"max_width": 800,*/
/**窗口显示的最大高度,可不设。
"max_height": 670,*/
/**bool值,如果设置为false,启动时窗口不可见。*/
"show": true,
/**是否在任务栏显示图标。*/
"show_in_taskbar":true,
/**
* bool值。是否使用kiosk模式。如果使用kiosk模式,
* 应用程序将全屏显示,并且阻止用户离开应用。
* */
"kiosk": false
},
/**webkit设置*/
"webkit": {
/**bool值,是否加载插件,如flash,默认值为false。*/
"plugin": true,
/**bool值,是否加载Java applets,默认为false。*/
"java": false,
/**bool值,是否启用页面缓存,默认为false。*/
"page-cache": false
}
}
Nginx conf配置文件
————————————————
版权声明:本文为CSDN博主「郑为中」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41464123/article/details/118110654
本教程中,您将学习如何使用 React 和 NodeJS 构建一个 Web 应用程序,该应用程序允许您将 ChatGPT 生成的通知发送给您的用户。
介绍
我一生中制造了许多产品。
在所有这些中,我都必须以某种形式向用户发送通知。
它可以是一封“欢迎邮件”或通知用户他们还没有支付最后一张发票
但有一件事是肯定的。我是程序员,不是文案。
那么我如何为我的通知提供正确的消息呢?
一年多以前,我在玩 GPT+3,结果不错,但我无法在自动化生产中使用它。
但 ChatGPT 改变了游戏规则。
ChatGPT是一种由OpenAI 训练的 AI 语言模型, 可以生成文本并以类似人类的对话方式与用户进行交互。值得一提的是,ChatGPT 是免费开放给公众使用的。
用户可以在几秒钟内提交请求并获得信息或问题的答案,主题范围广泛,例如历史、科学、数学和时事。
ChatGPT 执行其他任务,例如校对、释义和翻译。它还可以帮助编写、调试和解释代码片段。其广泛的功能是 ChatGPT 一直流行的原因。
主要问题是它还不能与 API 一起使用。
但这不会阻止我们
简单介绍一下我们的背景。Novu 是第一个开源通知基础设施。我们基本上帮助管理所有产品通知。它可以是应用程序内(像您在 Facebook - Websockets中的铃铛图标)、电子邮件、短信等。
正如我之前提到的,ChatGPT 不能作为公共 API 使用。
因此,要使用它,我们必须设法进入。
这意味着我们将在登录 OpenAI 网站时执行完整的浏览器自动化,解决他们的验证码(为此,您可以使用2captcha),并发送 API 请求使用 OpenAI cookie。
在这里,我将指导您为 Web 应用程序创建项目环境。我们将在前端使用 React.js,在后端服务器使用 Node.js。
通过运行以下代码为 Web 应用程序创建项目文件夹:
mkdir react-chatgpt
cd react-chatgpt
mkdir client server
导航到服务器文件夹并创建一个package.json文件。
cd server & npm init -y
安装 Express、Nodemon 和 CORS 库。
npm install express cors nodemon
ExpressJS是一个快速、极简的框架,它提供了在 Node.js 中构建 Web 应用程序的多种功能, CORS是一个允许不同域之间通信的 Node.js 包,而 Nodemon是一个在检测到文件后自动重启服务器的 Node.js 工具变化。
创建index.js文件 - Web 服务器的入口点。
touch index.js
使用 Express.js 设置 Node.js 服务器。当您http://localhost:4000/api在浏览器中访问时,下面的代码片段会返回一个 JSON 对象。
//index.js
const express=require("express");
const cors=require("cors");
const app=express();
const PORT=4000;
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cors());
app.get("/api", (req, res)=> {
res.json({
message: "Hello world",
});
});
app.listen(PORT, ()=> {
console.log(`Server listening on ${PORT}`);
});
安装 ChatGPT API 库 和 Puppeteer。ChatGPT API 使用 Puppeteer 作为可选的对等依赖项来自动绕过 Cloudflare 保护。
npm install chatgpt puppeteer
要在 中使用 ChatGPT API server/index.js,您需要将文件配置为同时使用require和import关键字来导入库。
因此,更新server/package.json以包含 type 关键字。
{ "type": "module" }
在文件顶部添加下面的代码片段server/index.js。
import { createRequire } from "module";
const require=createRequire(import.meta.url);
完成最后两个步骤后,您现在可以在index.js文件中使用 ChatGPT。
通过将启动命令添加到package.json文件中的脚本列表来配置 Nodemon。下面的代码片段使用 Nodemon 启动服务器。
//In server/package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon index.js"
},
恭喜!您现在可以使用以下命令启动服务器。
npm start
设置 React 应用程序
通过终端导航到客户端文件夹并创建一个新的 React.js 项目。
cd client
npx create-react-app ./
安装 React Router - 一个 JavaScript 库,使我们能够在 React 应用程序的页面之间导航。
npm install react-router-dom
从 React 应用程序中删除多余的文件,例如徽标和测试文件,并更新App.js文件以显示“Hello World”,如下所示。
function App() {
return (
<div>
<p>Hello World!</p>
</div>
);
}
export default App;
导航到该src/index.css文件并复制下面的代码。它包含设置此项目样式所需的所有 CSS。
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap");
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: "Space Grotesk", sans-serif;
}
body {
margin: 0;
padding: 0;
}
textarea,
select {
padding: 10px 15px;
margin-bottom: 15px;
border: 1px solid #ddd;
border-radius: 5px;
}
.notification__form {
width: 80%;
display: flex;
align-items: left;
justify-content: center;
flex-direction: column;
}
.homeContainer h3,
textarea {
margin-bottom: 20px;
}
.notification__form button {
width: 200px;
padding: 15px 10px;
cursor: pointer;
outline: none;
border: none;
background-color: #82aae3;
border-radius: 5px;
margin-bottom: 15px;
}
.navbar {
width: 100%;
height: 10vh;
padding: 20px;
background-color: #82aae3;
display: flex;
align-items: center;
justify-content: space-between;
}
.homeContainer {
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
更新App.js文件以呈现 Home 组件,如下所示:
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./components/Home";
const App=()=> {
return (
<BrowserRouter>
<Routes>
<Route path='/' element={<Home />} />
</Routes>
</BrowserRouter>
);
};
export default App;
从上面的代码片段中,我导入了 Home 组件。创建一个包含该Home.js文件的组件文件夹,如下所示:
cd client
mkdir components
cd components
touch Home.js
将下面的代码片段复制到Home.js文件中:
import React, { useState } from "react";
const Home=()=> {
const [message, setMessage]=useState("");
const [subscriber, setSubscriber]=useState("");
const handleSubmit=(e)=> {
e.preventDefault();
console.log({ message, subscriber });
setMessage("");
setSubscriber("");
};
return (
<div className='home'>
<nav className='navbar'>
<h2>Notify</h2>
</nav>
<main className='homeContainer'>
<h3>Send notifications to your users</h3>
<form
className='notification__form'
onSubmit={handleSubmit}
method='POST'
>
<label htmlFor='title'>Notification Title</label>
<textarea
rows={5}
name='title'
required
value={message}
onChange={(e)=> setMessage(e.target.value)}
placeholder='Let the user know that'
/>
<label htmlFor='subscriber'>Subscribers</label>
<select
value={subscriber}
name='subscriber'
onChange={(e)=> setSubscriber(e.target.value)}
>
<option value='Select'>Select</option>
</select>
<button>SEND NOTIFICATION</button>
</form>
</main>
</div>
);
};
export default Home;
如何将 Novu 添加到 React 和 Node.js 应用程序
我们将使用 Novu 发送应用内通知,但如果您想构建应用内通知,请跳过此步骤。
将 Novu 添加到 React 应用程序
通过在客户端文件夹中运行以下代码来创建 Novu 项目。
cd client
npx novu init
在创建 Novu 项目之前,您需要使用 Github 登录。下面的代码片段包含运行后应遵循的步骤npx novu init。
Now let's setup your account and send your first notification
? What is your application name? Devto Clone
? Now lets setup your environment. How would you like to proceed?
> Create a free cloud account (Recommended)
? Create your account with:
> Sign-in with GitHub
? I accept the Terms and Condidtions (https://novu.co/terms) and have read the Privacy Policy (https://novu.co/privacy)
> Yes
?? Create your account successfully.
We've created a demo web page for you to see novu notifications in action.
Visit: http://localhost:57807/demo to continue
访问演示网页http://localhost:52685/demo,从页面复制您的订阅者 ID,然后单击“跳过教程”按钮。我们将在本教程的后面部分使用它。
在 React 项目中安装 Novu Notification 包作为依赖项。
npm install @novu/notification-center
更新components/Home.js文件以包含 Novu 及其 文档中的必需元素。
import {
NovuProvider,
PopoverNotificationCenter,
NotificationBell,
} from "@novu/notification-center";
import { useNavigate } from "react-router-dom";
const Home=()=> {
const navigate=useNavigate();
const onNotificationClick=(notification)=> {
navigate(notification.cta.data.url);
};
//...other statements
return (
<div className='home'>
<nav className='navbar'>
<h2>Notify</h2>
<NovuProvider
subscriberId={"<YOUR_SUBSCRIBER_ID>"}
applicationIdentifier={"<YOUR_APP_ID>"}
>
<PopoverNotificationCenter onNotificationClick={onNotificationClick}>
{({ unseenCount })=> (
<NotificationBell unseenCount={unseenCount} colorScheme='light' />
)}
</PopoverNotificationCenter>
</NovuProvider>
</nav>
<main className='homeContainer'>...</main>
</div>
);
};
上面的代码片段将 Novu 的通知铃图标添加到导航栏,使我们能够查看所有应用通知。
该NovuProvider组件需要您的订阅者 ID - 之前从Novu Manage Platformhttp://localhost:52685/demo上的 API 密钥下的设置部分复制了您的应用程序 ID 。
接下来,让我们为应用程序创建通知工作流和模板。
在浏览器中打开Novu Manage Platform并创建通知模板。
选择模板,点击工作流程编辑器,确保工作流程如下:
单击该In-App步骤并编辑模板以包含消息变量,如下所示。message 变量将包含 ChatGPT 生成的通知。
{{message}}
单击更新按钮保存模板。
导航到服务器文件夹并安装适用于 Node.js 的 Novu SDK。
cd server
npm install @novu/node
从包中导入 Novu 并使用您的 API 密钥创建一个实例。
//server/index.js
const { Novu }=require("@novu/node");
const novu=new Novu("<YOUR_API_KEY>");
恭喜!您已成功将 Novu 添加到您的 Web 应用程序中。在接下来的部分中,您将学习如何通过 Novu 向您的用户发送 AI 生成的通知。
在本节中,我将指导您从 ChatGPT 为不同的用例生成通知并将它们发送给您的 Novu 订阅者。
该应用程序将允许您指定所需的通知类型并选择将接收消息的订阅者。
我们在Home.js. 接下来,让我们获取订阅者列表并将它们显示在组件中。
在文件中添加一个路由index.js,从 Novu 获取订阅者列表。
app.get("/subscribers", async (req, res)=> {
try {
const { data }=await novu.subscribers.list(0);
const resultData=data.data;
// 返回具有 ID、名字和姓氏的订阅者
const subscribers=resultData.filter(
(d)=> d.firstName && d.lastName && d.subscriberId
);
res.json(subscribers);
} catch (err) {
console.error(err);
}
});
创建一个向/subscribers端点发送请求并在 React 应用程序内加载页面时显示订阅者的函数。
// 表示订阅者列表的状态
const [subscribers, setSubscribers]=useState([
{ firstName: "", lastName: "", subscriberId: "Select", _id: "null" },
]);
// 在页面加载时获取订阅者列表
useEffect(()=> {
async function fetchSubscribers() {
try {
const request=await fetch("http://localhost:4000/subscribers");
const response=await request.json();
setSubscribers([...subscribers, ...response]);
} catch (err) {
console.error(err);
}
}
fetchSubscribers();
}, []);
更新 Home 组件中的 select 标签以呈现订阅者列表,如下所示:
<select
value={subscriber}
name='subscriber'
onChange={(e)=> setSubscriber(e.target.value)}
>
{subscribers.map((s)=> (
<option
key={s._id}
value={`${s.firstName} ${s.lastName} - ${s.subscriberId}`}
>{`${s.firstName} ${s.lastName} - ${s.subscriberId}`}</option>
))}
</select>
在其中创建一个路由,该路由index.js接受来自用户的通知标题和订阅者。
app.post("/notify", (req, res)=> {
// 从对象中解构消息和订阅者
const { message, subscriber }=req.body;
// 分隔名字和订阅者 ID
const subscriberDetails=subscriber.split(" ");
const firstName=subscriberDetails[0];
const subscriberId=subscriberDetails[3];
//在消息中添加了一些规范,使 AI 能够生成简洁的通知。
const fullMessage=`I have a notification system and I want to send the user a notification about "${message}" can you write me one?
please use double curly brackets for variables.
make it short, and use only one variable for the user name.
Please just write 1 notification without any intro.`;
// Log the required variables to the console
console.log({ firstName, subscriberId, fullMessage });
接下来,让我们将表单详细信息提交到/notify服务器上的路由。创建一个函数,在提交表单时向端点发出 POST 请求。
// 发出 POST 请求
async function sendNotification() {
try {
const request=await fetch("http://localhost:4000/notify", {
method: "POST",
body: JSON.stringify({
message,
subscriber,
}),
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
const data=await request.json();
console.log(data);
} catch (err) {
console.error(err);
}
}
// 在用户提交表单时运行
const handleSubmit=(e)=> {
e.preventDefault();
// 调用该函数
sendNotification();
setMessage("");
setSubscriber("");
};
更新/notify路由以将必要的变量传递给另一个函数。
app.post("/notify", (req, res)=> {
const { message, subscriber }=req.body;
const subscriberDetails=subscriber.split(" ");
const firstName=subscriberDetails[0];
const subscriberId=subscriberDetails[3];
const fullMessage=`I have a notification system and I want to send the user a notification about "${message}" can you write me one?
please use double curly brackets for variables.
make it short, and use only one variable for the user name.
Please just write 1 notification without any intro.`;
console.log({ firstName, subscriberId, fullMessage });
// 将变量作为参数传递给函数
chatgptFunction(fullMessage, subscriberId, firstName, res);
});
创建chatgptFunction如下:
// 保存 AI 生成的通知
let chatgptResult="";
async function chatgptFunction(message, subscriberId, firstName, res) {
//使用 puppeteer 绕过 cloudflare(因为有验证码)
const api=new ChatGPTAPIBrowser({
email: "<YOUR_CHATGPT_EMAIL>",
password: "<YOUR_CHATGPT_PASSWORD>",
});
// 在浏览器上打开登录屏幕
await api.initSession();
const result=await api.sendMessage(message);
chatgptResult=result.response;
// 用用户的名字替换用户变量
const notificationString=chatgptResult.replace("{{user}}", firstName);
console.log(notificationString, subscriberId);
}
最后,让我们通过 ID 向订阅者发送通知。创建另一个接受notificationString和subscriberId并发送通知的函数。
async function chatgptFunction(message, subscriberId, firstName, res) {
// 使用 puppeteer 绕过 cloudflare(因为有验证码)
const api=new ChatGPTAPIBrowser({
email: "<YOUR_CHATGPT_EMAIL>",
password: "<YOUR_CHATGPT_PASSWORD>",
});
await api.initSession();
const result=await api.sendMessage(message);
chatgptResult=result.response;
const notificationString=chatgptResult.replace("{{user}}", firstName);
// 传递必要的变量作为参数
sendNotification(notificationString, subscriberId, res);
}
//通过 Novu 发送通知
async function sendNotification(data, subscriberId, res) {
try {
let result=await novu.trigger("<NOTIFICATION_TEMPLATE_ID>", {
to: {
subscriberId: subscriberId,
},
payload: {
message: data,
},
});
return res.json({ message: result });
} catch (err) {
return res.json({ error_message: err });
}
}
恭喜!您已完成本教程的项目。
到目前为止,我们已经涵盖了
本教程将引导您完成一个可以使用 Novu 和 ChatGPT 构建的应用程序示例。ChatGPT 可以被视为终极个人助理,在各个领域都非常有用,使我们能够更智能、更好地工作。
*请认真填写需求信息,我们会在24小时内与您取得联系。