脚手架帮你做了什么?手动搭建 React 后台项目
有时候过于依赖脚手架、各种库,会让我们的能力陷入一个瓶颈。本教程试图从零开始,记录一个项目的形成过程。
本教程涉及什么
涉及技术
-
React
-
Tailwind + SCSS
-
Git(Github)
预备知识
最好能有所了解。
基础工作
创建 Git 仓库
名称:bloggo-admin-frontend
链接:https://github.com/pluveto/bloggo-admin-frontend
创建项目目录
1$ cd ~/proj
2
3$ mkdir bloggo-admin-frontend
4
5$ cd bloggo-admin-frontend
初始化项目
1
2$ npm init
3This utility will walk you through creating a package.json file.
4It only covers the most common items, and tries to guess sensible defaults.
5
6See `npm help init` for definitive documentation on these fields
7and exactly what they do.
8
9Use `npm install <pkg>` afterwards to install a package and
10save it as a dependency in the package.json file.
11
12Press ^C at any time to quit.
13package name: (bloggo-admin-frontend)
14version: (1.0.0)
15description: Frontend project for bloggo dashboard
16entry point: (index.js)
17test command:
18git repository: https://github.com/pluveto/bloggo-admin-frontend
19keywords: bloggo admin frontend tailwind react
20
21license: (ISC) MIT
22About to write to /root/proj/bloggo-admin-frontend/package.json:
23
24{
25 "name": "bloggo-admin-frontend",
26 "version": "1.0.0",
27 "description": "Frontend project for bloggo dashboard",
28 "main": "index.js",
29 "scripts": {
30 "test": "echo \"Error: no test specified\" && exit 1"
31 },
32 "repository": {
33 "type": "git",
34 "url": "git+https://github.com/pluveto/bloggo-admin-frontend.git"
35 },
36 "keywords": [
37 "bloggo",
38 "admin",
39 "frontend",
40 "tailwind",
41 "react"
42 ],
43 "author": "pluveto",
44 "license": "MIT",
45 "bugs": {
46 "url": "https://github.com/pluveto/bloggo-admin-frontend/issues"
47 },
48 "homepage": "https://github.com/pluveto/bloggo-admin-frontend#readme"
49}
50
51
52Is this OK? (yes) yes
安装依赖
react
核心依赖是 react
1$ yarn add react
2$ yarn add react-dom
3$ yarn add react-router-dom
-
react-dom:提供 DOM 元素操作
-
react-router-dom:提供 DOM 的路由绑定
sass
1$ yarn add node-sass --global
sass 是一个 css 预处理器,从而能让我们用 sass 或 scss 语法编写更工程化的样式代码。
webpack
1$ yarn add webpack webpack-cli --dev
-
webpack:用于提供打包功能
-
webpack-cli:提供打包 CLI 命令
devServer
用于提供热重载
1$ yarn add webpack-dev-server --dev
wepack loader
1$ yarn add babel-loader html-loader style-loader css-loader sass-loader --dev
webpack plugin
用于生成 HTML5 文件并引入 webpack 包裹。
1$ yarn add html-webpack-plugin --dev
babel
1$ yarn add @babel/core @babel/preset-react @babel/preset-env --dev
-
babel:提供 ES6 到 ES5 的编译
-
babel-preset-react:提供 react 相关的 babel 插件
-
babel-preset-env:用于配置需要支持的平台和版本(比如 IE>=11,Chrome >64)
配置 babel
.babelrc 进行配置如下:
1{
2 "presets": [
3 "@babel/preset-react"
4 ]
5}
从而支持 JSX 语法
配置 webpack
webpack.config.js 配置如下:
1const path = require("path");
2const webpack = require("webpack");
3const HTMLWebpackPlugin = require("html-webpack-plugin");
4
5module.exports = {
6 mode: "development",
7 entry: "./index.js",
8 output: {
9 filename: "bundle.js",
10 path: path.resolve("dist"),
11 publicPath: "/",
12 },
13 module: {
14 rules: [
15 {
16 test: /\.(js|jsx)$/,
17 exclude: /node_modules/,
18 use: "babel-loader"
19 },
20 {
21 test: /\.html$/,
22 use: "html-loader"
23 },{
24 test: /\.css$/,
25 use: ["style-loader", "css-loader"],
26 },
27 {
28 test: /\.scss$/,
29 use: [
30 "style-loader",
31 "css-loader",
32 "sass-loader"
33 ],
34 },
35 ],
36 },
37 plugins: [
38 new HTMLWebpackPlugin({
39 template: "index.html"
40 }),
41 ]
42}
HTML 首页
index.html
1<!DOCTYPE html>
2<html lang="zh">
3<head>
4 <meta charset="UTF-8">
5 <meta http-equiv="X-UA-Compatible" content="IE=edge">
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <title>Hello, React!</title>
8</head>
9<body>
10 <div id="root"></div>
11</body>
12</html>
入口文件
index.js
1import React from "react";
2import ReactDOM from "react-dom";
3import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
4
5import App from "./App.js";
6import "./styles.scss";
7
8const appRouting = (
9 <Router>
10 <Switch>
11 <Route exact path="/" component={App} />
12 </Switch>
13 </Router>
14);
15const root = document.querySelector("#root")
16ReactDOM.render(appRouting, root);
App.js
1import React from "react";
2
3const App = () => {
4 return <div className="hello">Hello, World!</div>;
5};
6
7export default App;
styles.scss
1.hello {
2 text-align: center;
3}
检查
现在的项目依赖是这样的:
1 "dependencies": {
2 "react": "^17.0.2",
3 "react-dom": "^17.0.2"
4 },
5 "devDependencies": {
6 "@babel/core": "^7.14.8",
7 "@babel/preset-env": "^7.14.8",
8 "@babel/preset-react": "^7.14.5",
9 "babel-loader": "^8.2.2",
10 "css-loader": "^6.2.0",
11 "html-loader": "^2.1.2",
12 "html-webpack-plugin": "^5.3.2",
13 "react-router-dom": "^5.2.0",
14 "sass-loader": "^12.1.0",
15 "style-loader": "^3.2.1",
16 "webpack": "^5.47.1",
17 "webpack-cli": "^4.7.2",
18 "webpack-dev-server": "^3.11.2"
19 }
增加常用脚本
在 package.json
增加:
1 "scripts": {
2 "test": "echo \"Error: no test specified\" && exit 1",
3+ "start": "webpack serve"
4 },
运行
1$ yarn start
效果如下:
推送到 Github
配置忽略规则
.gitignore
1# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
3# dependencies
4/node_modules
5/.pnp
6.pnp.js
7
8# testing
9/coverage
10
11# production
12/build
13
14# misc
15.DS_Store
16.eslintcache
17/.env
18/.env.local
19/.env.development.local
20/.env.test.local
21/.env.production.local
22
23npm-debug.log*
24yarn-debug.log*
25yarn-error.log*
26yarn.lock
推送代码
1$ git init
2$ git remote add origin https://github.com/pluveto/bloggo-admin-frontend.git
3$ git add .
4$ git status
5On branch master
6
7No commits yet
8
9Changes to be committed:
10 (use "git rm --cached <file>..." to unstage)
11
12 new file: .babelrc
13 new file: .gitignore
14 new file: App.js
15 new file: index.html
16 new file: index.js
17 new file: package.json
18 new file: styles.scss
19 new file: webpack.config.js
20$ git commit -m "feat: basic project"
21$ git push --set-upstream origin master
现在,基本的项目有了。但是项目结构是完全平行的:
因此我们需要设计一下项目结构。
新建分支
我们新建一个基于 master 的分支:
1$ git branch v2
切换到新分支:
1$ git checkout v2
重设结构
我比较喜欢相同功能的放在一起,而不是分层,因为那样不好快速跳转到对应的文件。
我们增加一个 如下目录:
-
src/
:存放项目特有的代码 -
public/
:存放静态文件 -
helpers/
:存放工具组件
把 App.js
,index.js
,styles.scss
移动到 src/
,并更新相关依赖。
登录页面
我们首先做登录页面
src/pages/login/LoginPage.jsx
1import React from "react";
2
3export default class LoginPage extends React.Component {
4 render() {
5 return (
6 <div >
7 Login Page
8 </div>
9 )
10 }
11}
增加路由
现在我们要登录页到路由表中。
允许 BrowserRouter
为了避免得到下面的响应:
Cannot GET /login
我们需要做如下设置
webpack.config.js
1 output: {
2 filename: "bundle.js",
3 path: path.resolve("dist"),
4 publicPath: "/", // HERE
5 },
6 devServer: {
7 historyApiFallback: true // HERE
8 },
首页
将 App.js 改成 HomePage.js,放到 src/pages/home
:
1import React from "react";
2import { Link, Route, Switch } from "react-router-dom";
3import LoginPage from "./LoginPage";
4
5const Home = () => {
6 return (
7 <div>
8 <p>Bloggo Admin</p>
9 <Link to="/login">登录</Link>
10 </div>
11 )
12};
13
14export default Home;
路由表
编辑 index.js:
1import React from "react";
2import ReactDOM from "react-dom";
3import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
4
5import HomePage from "./pages/login/HomePage.js";
6import LoginPage from "./pages/login/LoginPage.js";
7import "./styles.scss";
8
9const appRouting = (
10 <Router>
11 <div className="sans-serif">
12 <Route exact path="/" component={HomePage} />
13 <Route path="/login" component={LoginPage} />
14 </div>
15 </Router>
16);
17const root = document.querySelector("#root")
18ReactDOM.render(appRouting, root);
运行,并访问 `http://localhost:8080
两个页面均正常显示。
设计样式
增加 Tailwind 依赖
1$ yarn add tailwindcss
// TODO: 集成 PostCSS,以及按需导出
添加 Tailwind 到项目
index.js 增加:
1import "tailwindcss/tailwind.css"
这时并不会生效,你如果定位到那个文件,会看到:
tailwindcss/tailwind.css:
1@tailwind base;
2
3@tailwind components;
4
5@tailwind utilities;
它用了自己的指令,这些指令由 PostCSS 提供支持
集成 PostCSS
1$ yarn add postcss@latest autoprefixer@latest
postcss.config.js:
1module.exports = {
2 plugins: {
3 tailwindcss: {},
4 autoprefixer: {},
5 }
6}
tailwind.config.js
1module.exports = {
2 // 配置清除 (purge) 选项以删除任何未使用类,这样生成的文件尺寸最小
3 purge: [
4 './src/**/*.html',
5 './src/**/*.js',
6 ],
7 darkMode: false, // or 'media' or 'class'
8 theme: {
9 extend: {},
10 },
11 variants: {},
12 plugins: [],
13}
安装 PostCSS 的 Webpack 插件:
1yarn add postcss-loader --dev
webpack.config.js
1// ...
2module.exports = {
3 mode: "development",
4 entry: "./src/index.js",
5 output: {
6 filename: "bundle.js",
7 path: path.resolve("dist"),
8 publicPath: "/",
9 },
10 devServer: {
11 historyApiFallback: true
12 },
13 module: {
14 rules: [
15 // ...
16 {
17 test: /\.css$/,
18 use: [
19 "style-loader",
20 "css-loader",
21+ "postcss-loader"
22 ],
23 },
24 {
25 test: /\.scss$/,
26 use: [
27 "style-loader",
28 "css-loader",
29 "sass-loader",
30+ "postcss-loader"
31 ],
32// ...
现在,Tailwind 可以正常使用了。
拥抱 jsx:
webpack.config.js
1// ...
2 resolve: {
3 extensions: ['', '.js', '.jsx'],
4 }
5}