了解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小時內與您取得聯系。