时间:2023-07-21 07:58:55 点击次数:9
SAST Weekly 是由电子工程系学生科协推出的科技系列推送,内容涵盖信息领域技术科普、研究前沿热点介绍、科技新闻跟进探索等多个方面,帮助同学们增长姿势,开拓眼界,每周更新,欢迎关注!欢迎愿意分享知识的同学投稿至 eesast@mail.tsinghua.edu.cn , 期待你的作品!
你是否好奇电子科协的网站究竟是如何搭建的呢?
你是否也想搭建一个个人网站呢?
你是否想了解一些技术,不管有没有用呢?
阅读这篇《从零开始的异世界生活从零开始的 React 网站搭建》,从入门到查阅各种文档后搭建个人网站。
目录
技术栈概览
TypeScript 速览
Express, MongoDB 速览
React 速览
Redux 和其他库
Ant Design 速览
构建指南
鸣谢
参考
本文以介绍核心技术栈为主,其余使用到的库可能只是略有提及,不会详细介绍。
01
技术栈概览
基石
JavaScript
JavaScript ( JS ) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。它被用到了很多环境中,例如 浏览器、 Node.js。JavaScript 是一种基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式(如函数式编程)风格。
JavaScript 并不能说是一门设计很好的语言,但其框架众多,可以用来实现很多有趣的功能。
TypeScript
TypeScript 是 JavaScript 的超集,两者最直观,最鲜明的不同是类型注解。
JS 的类型是动态的,江湖评价为“动态类型一时爽,代码重构火葬场”。TS 的结构类型系统解决了 JS 的弱类型带来的问题,加强了工程质量,改善了维护体验。具体介绍可以看后续章节。
Node.js
Node.js 是基于 Chrome V8 引擎的 JavaScript 的运行时。使用 Node.js 可以方便地搭建前端和后端。
考虑到 EESΛST 网站的具体需求和编程环境的统一,目前网站的前后端都采用 Node.js。
安装可访问 https://nodejs.org/ 或是 https://mirrors.tuna.tsinghua.edu.cn/help/nodejs-release/
后端
Express
基于 Node.js 平台,快速、开放、极简的 Web 开发框架
Express 用于实现我们的核心功能绰绰有余,而且扩展性强,可用于未来画饼的需求。
MongoDB
MongoDB 是一个基于分布式文件存储的面向文档的数据库,存储的数据以类似 JSON 的 BSON 进行保存
MongoDB 是现在非常流行的数据库,且官方支持多种语言(包括电子系诸位熟悉的知道的 C/C++,Python,当然也包括我们使用的 JavaScript 和 TypeScript)。如果未来我们更换后端技术栈到其他语言上,仍可以保留现有数据轻松迁移。
前端
React
React 是 Facebook 和社群维护的,用于构建用户界面的 JavaScript 库
React 的声明式组件设计使得网站设计的结构更为清晰。其活跃的社群提供了大量好用的组件设计,极大地简化了网页前端的搭建。
Redux
Redux 是 JavaScript 的状态容器。我们用于配合 React 存储网页需要临时存储的数据。
Ant Design
Ant Design 是蚂蚁金服体验技术部开放的一个设计体系。不过我们本文中更多指antd这个基于 Ant Design 设计体系的 React UI 组件库。
选择antd的原因主要是:开箱即用 + 较为美观
下面,我将粗略地介绍各部分如何入门到精通放弃
02
TypeScript
环境配置
Visual Studio 从 2015 开始默认包含 TypeScript,如果没有安装也可以在功能管理中进行安装。
对于 VSCode 或者其他文本编辑器的使用者,请使用 npm 或者 yarn(JavaScript 的包管理工具)进行安装。npm 的例子如下:
npm install -g typescript
此外,为了较好的编程体验,可能需要安装各类插件。以 VSCode 为例,建议安装Prettier对代码进行格式化,安装ESLint对代码进行检查。
基本语法
下面会用例子来展示 TypeScript:
functionfun(personName: string) {
vara = 1;
letb = {
name:"Alice",
age:20
};
letc: { type: string; tags: string[] } = { type:"type1", tags: ["tag1"] };
constgreeting = "Hello, " + personName;
consthelloWorld = (props: string) => {
// 括号中为函数参数,此处仅用于展示
return"Hello, World";
};
returngreeting;
}
constbasicType = {
bool:true,
num:1,
str:"abc",
list: [1, 2, 3],
u:undefined,
n:null
};
functionfun2(): void {
console.log("return void");
}
functionerror(message: string): never {
thrownewError(message);
}
在 TypeScript 中,有三种声明变量的关键字:var,let,const。var源于 JavaScript,继承了 JS 中的灵活性(各类问题);let则是更为严格的,用于代替var的关键字;const则是声明常量的关键字。
与 JS 鲜明的不同点类型注解便是代码中 : 的格式。这样的写法会告诉编译器该变量是什么类型的,并且可以使用静态类型检查,将运行时才能暴露出来的问题提前发现。
上面还列出了一些常见的类型供参考。
classStudent {
fullName: string;
constructor(
publicfirstName: string,
publicmiddleInitial: string,
publiclastName: string
) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}
interfacePerson {
firstName: string;
lastName: string;
}
functiongreeter(person: Person) {
return"Hello, " + person.firstName + " " + person.lastName;
}
letuser = newStudent("Jane", "M.", "User");
document.body.innerHTML = greeter(user);
这里给出了类和接口的例子。由于现在 React 社群热衷于函数式组件,类的使用在减少,故不才没有多少了解。感兴趣的同学可以参考 TypeScript 的文档。
参考链接
TypeScript 中文文档: https://www.tslang.cn/index.html
JavaScript 中文文档: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
03
Express, MongoDB
Express
安装
使用 npm 的话,在项目根目录下
npm install express --save
使用
Express 是轻量级的 Web 框架,可以快速构建 API。我们采用的是 RESTful 的设计,即使用 url 代表各种资源。
下面给出代码的示例:
constexpress = require("express");
constapp = express();
constport = 3000;
app.get("/", (req, res) =>res.send("Hello World!"));
app.listen(port, () =>console.log(`Example app listening on port ${port}!`));
这段代码实现了使用GET请求localhost:3000/时返回Hello World!
具体到我们的 api 实现
// 在xxx.ts中,实现xxxRouter (省略import部分)
constrouter = express.Router();
// checkToken是一个用于检查用户信息的中间件
// req表示请求,res表示返回结果,next用于异常处理
router.get("/", checkToken, async (req, res, next) => {
/* ... */
});
router.get("/:id", async (req, res, next) => {
/* ... */
});
/* ... */
exportdefaultrouter;
参考链接
Express 官方中文网站:https://www.expressjs.com.cn
菜鸟教程: https://www.runoob.com/nodejs/nodejs-express-framework.html
MongoDB
安装
访问 https://www.mongodb.com/download-center/community,选择需要的版本,下载安装
使用 npm 也可以使用下方命令进行安装,详细说明可以见后面给出的参考链接
npm install mongodb --save
使用
我们使用JS的mongoose包来调用安装好的MongoDB。
使用类似下方的代码,构建存储在 MongoDB 中的文档模板,之后使用mongoose进行存储、更新的时候会将这样结构的数据存入MongoDB。
exportinterfaceArticleModelextendsmongoose.Document {
id: number;
title: string;
alias: string;
authorId: number;
abstract?: string;
image?: string;
content: string;
views: number;
likers: number[];
tags: string[];
visible: boolean;
createdAt: Date;
createdBy: number;
updatedAt: Date;
updatedBy: number;
}
constarticleSchema = newmongoose.Schema<ArticleModel>(
{
id: { type:Number, unique:true }, // use auto-increment id, instead of _id generated by database
title: { type:String, required:true }, // “TensorFlow 初探”
alias: { type:String, required:true }, // for SEO and URL, “tensor-flow-first-look”
authorId: { type:Number, required:true },
abstract:String, // used for preview
image:String, // title image
content: { type:String, required:true }, // markdown string
views: { type:Number, default:0 },
likers: [Number], // likers ids
tags: [String],
visible: { type:Boolean, default:false }, // used for review
createdAt: { type:Date, default:Date.now },
createdBy:Number,
updatedAt: { type:Date, default:Date.now },
updatedBy:Number
},
{
collection:"articles"
}
);
把上面的代码加上 import 和 export 部分后,查询,保存只需要
importArticlefrom"../models/article";
Article.findOne({ id:req.params.id });
constarticle = awaitnewArticle({
...req.body,
createdBy:req.auth.id,
updatedBy:req.auth.id
}).save();
参考链接
MongoDB 官方文档:https://docs.mongodb.com/manual/
MongoDB + Node.js:http://mongodb.github.io/node-mongodb-native/3.4/quick-start/quick-start/
MongoDB + Python:https://api.mongodb.com/python/current/tutorial.html
菜鸟教程:https://www.runoob.com/mongodb/mongodb-tutorial.html
mongoose:https://mongoosejs.com/
mongoose 中文:http://www.mongoosejs.net/
04
React
安装
可以参考 React 官方提供的create-react-app,使用 npm 的npx命令,快速构建单页应用:
npx create-react-app my-app
cd my-app
npm start
使用
React 使用 JSX 或 TSX(JavaScript 和 TypeScript 的一个语法扩展),以统一标记和逻辑。
constname = "Josh Perez";
constelement = <h1>Hello, {name}</h1>;
ReactDOM.render(element, document.getElementById("root"));
React 会使用 Babel 将这类语法扩展转换为对象,然后使用这些对象构建 DOM(Document Object Model),再渲染成用户看到的页面。以上一般称为“元素”
React 中还有“组件”,可以理解为可复用的独立代码片段。目前,React 允许两类组件:函数组件与类组件
functionWelcome(props) {
return<h1>Hello, {props.name}</h1>;
}
classWelcomeextendsReact.Component {
render() {
return<h1>Hello, {this.props.name}</h1>;
}
}
之后使用 JSX(或 TSX)渲染,如下所示
functionWelcome(props) {
return<h1>Hello, {props.name}</h1>;
}
constelement = <Welcomename="Sara"/>;
ReactDOM.render(element, document.getElementById("root"));
实际使用时会将一些可复用的部分或是需要经常更改的部分单独写成组件,再使用组件内部调用组件的形式进行组合。
React 在 16.8 中加入了 Hook,用于函数组件的 state 管理、副作用函数的调用等。由于我们主要使用函数组件,下面将简要介绍 Hook 中常用的两个(useState和useEffect),不会介绍类组件的对应实现。
以我在寒假期间在做的 Weekly EditPage 为例,我使用了以下这些useState用于管理“本页面”内使用的“状态”
const [text, setText] = useState(""); // 正在编辑的文本内容
const [highlight, setHighlight] = useState(true); // 控制Markdown渲染是否高亮代码
const [showModal, setShowModal] = useState(false); // 错误提示用对话框是否显示
const [showImgManage, setShowImgManage] = useState(false); // 图片上传管理对话框是否显示
const [showConfirm, setShowConfirm] = useState(false); // 确认发布文章对话框是否显示
const [info, setInfo] = useState(article); // 存储待发布/更新文章的信息
const [imageFileList, setImageFileList] = useState<UploadFile[]>([]); // 文章中使用图片列表,上传用
const [coverImageFile, setCoverImageFile] = useState<UploadFile[]>([]); // 文章题图
简单的来说,useState定义一个“常量”和用于修改的“方法”,用于保存和管理页面的状态。其使用方式如下:
// 声明
const [varName, setVarName] = useState<varType>(initialValue);
// 修改值
setVarName(newValue);
当这样声明的 state 改变的时候,React 会重新渲染页面(渲染时间有个小小的坑)。
另一个常用的 Hook 是useEffect。React 的函数组件本身要求是纯函数,即返回值只由参数决定,函数不修改外部变量。而useEffect允许操作副作用,下面给出 Weekly ManagePage 中获取文章的代码:
useEffect(() => {
// 获取文章
constfetchData = async () => {
constresponse = awaitapi.getSelfArticles(
user.id,
visible,
(pageNumber - 1) * pageSize,
pageNumber * pageSize
);
setData(response);
};
fetchData();
}, [pageNumber, pageSize, visible, user, operation]);
这里使用了前端包装后的 api 来获取文章,需要传入当前登录用户的 id,是否查看隐藏的文章,获取文章的始末位置(用于分页)。useEffect有两个参数,第一个参数是 JavaScript 的箭头函数(Lambda 表达式),第二个函数是一个变量列表。前者是执行的“副作用”,后者是执行前者的条件。当列表中的任何一个变量改变的时候,会执行箭头函数,从而操作副作用。
以上是我个人比较常用的部分的基本介绍,实际前端开发中更多用的是 Ant Design 已经设计好的组件。想更深入了解 React 的可以参考下面这些链接。
参考链接
React 官方中文网站:https://react.docschina.org/
05
Redux...
React 本身是不足以实现特别繁杂的功能的,我们还使用了许多其他的库实现各类功能(这些库是React生态的小小一部分而已XD)。比较重要的有两个:Redux 和 React Router。
Redux
Redux 是一个服务于 JS 应用的状态容器,且有 react-redux 用于更好地配合 React 进行开发。
Redux 使用时主要有三个部分:store、actions、reducers。store 中存储状态,actions 是各种“操作”,用于得到下一个状态,reducers 则是根据 actions 的结果修改 store 中存储的状态。使用 Redux 可以存储多个页面间共享的状态,比如登录信息。进一步还可以进行持久化(即一段时间内保持登录)。
https://redux.js.org/
React Router
React Router 是用于导航的组件,可以进行页面跳转,获取网页 URL 等操作
https://reacttraining.com/react-router/web/guides/quick-start
……
还有许多其他的库,需要开发人员根据需求去搜索和使用。
06
Ant Design
安装
以下说明以使用 React 进行开发为基础
使用 npm 或者 yarn:
npm install antd --save
yarn add antd
使用
Ant Design 已经提供了大量的组件,包括布局、导航、交互等,可以在 https://ant.design/components/button-cn/ 查看。
官方文档中会展示组件的基本使用方法
并且提供 API 供定制化
进一步,可以将一些组件结合起来,包装成更为常用的组件。(这也是 React 哲学的层级化组件)
在网站中,标签可能是用的比较多的组件。在 Weekly 页面开发的过程中,我将学长留下的代码改为了函数式组件的形式,成为基于 Ant Design 提供的 Tag 组件的 Tags:
基于 Ant Design 的表单、按钮、标签、上传等组件和 react-markdown-editor-lite 库,搭建的 EESAST Weekly Editor 如下图
参考链接
Ant Design 官方文档: https://ant.design/index-cn
07
构建指南
工具链
编辑器
我们选择 TypeScript 语言,VSCode 对其的支持相当完善。(毕竟都是微软的产品)VSCode 的优点在于原生支持好,相关插件多,缺点则在于其基于 Electron 开发,在内存较小的电脑上进行开发的体验不佳。(尤其是同时打开 Chrome 查看效果时)
VSCode 开发用到的插件如下图:
代码高亮优化:Bracket Pair Colorizer, Color Highlight, indent-rainbow
括号颜色配对
颜色 rgb 代码或英文名称添加色块显示
缩进彩虹色区分
代码格式化与检查:ESLint, TSLint(ESLint 也支持 TS,不必须), Prettier, JSON Tools
自动补全等效率工具:Markdown All in One, OpenAPI (Swagger) Editor, Path Intellisense, Visual Studio IntelliCode, Swagger Snippets
Markdown 编辑用快捷键和命令
Swagger API 编辑器,快速添加可复用代码块
路径补全
多语言智能补全
Swagger API 可复用代码块
其他:Chinese Language Pack, Code Spell Checker, GitLens
VSCode 中文包
拼写检查
更好的 Git 支持
调试软件
MongoDB Compass Community,用于查看数据库中内容和修改数据。
Postman,向后端发送请求进行测试。
浏览器及插件
在微软都倒向 Chromium 的时候,有什么理由不用 Chrome 呢(笑
React DevTools 和 Redux DevTools 是非常不错的帮助查看当前页面 React 组件结构和 Redux 存储值变化过程的插件。图为 Redux DevTools
资源
至此,技术栈基本介绍完毕。各部分参考链接在前面已经列出。如果想尝试我们这套方案,可以使用网站组学长放在 Github 上的这个模板:
https://github.com/robertying/create-react-app-typescript-antd
此外,还有许多值得参考的网站,如 W3school(https://www.w3school.com.cn/ ), 菜鸟教程(https://www.runoob.com/ ) 等。有问题时,StackOverflow 和 SegmentFault 上可能会有其他踩过坑的人留下的答案。
08
结语
粗浅地介绍了一下 EESΛST 网站开发所用的技术栈,权当抛砖引玉。希望此文能给对搭建个人网站感兴趣者带来些微的帮助,也希望能吸引大佬参与到 EESΛST 网站的开发中来 XD。
EESΛST 的网站项目目前是开源的,也欢迎热心肠同学在 GitHub 上面提交 issue 反馈问题。
说了半天,科协的网站URL是啥啊?
自然是 eesast.com 嘛
现在这个网站有什么功能呢?
科协介绍,THUAI比赛电子赛道(队式)的报名与对战,很快就要上线的Weekly网页版。
撰稿:贺鲲鹏
审核:孙志尧