react-demo

React 示例项目 · 简易留言板。本项目拥有完善的文档说明与注释,让您快速上手 React 开发 SPA。Webpack / ES6 + Babel / Redux / React Router —— An Excellent React Starter,可能是东半球最佳的 React Starter,基于 Vue Cli 二次开发

Github stars Tracking Chart

React 示例项目 · 简易留言板 + 待办事项

2017.7 升级版预览:react-scaffold,敬请期待!

应用截图

###写在前面
一直以来,我都相当纳闷:为什么 React 的那些 starter kit 都构建得那么恶心?
能不能像 Vue Cli 生成的项目架构般优雅?说干就干,本项目就改自 Vue Demo

更新

2016/8/28   引入 cross-env 解决跨平台问题,新增优化项 DedupePlugin
2016/8/29   重命名 makeContainer / makeReducer.js => createContainer / createReducer.js
2016/9/10   重构 src/redux/
2016/10/15   同步 Vue Demo 的改动
2016/10/16   改进:仅在开发模式下引入 React Hot Loader

目录

§ 技术栈

§ 快速开始

§ 项目架构

§ 开发

§ 测试

§ 部署

§ 参考


§ 技术栈

详情可参阅 package.json

  • React 15.3.0
  • Redux
  • React Router
  • Ajax 请求库(Superagent / jQuery-Ajax / ...)
  • Webpack
  • ES6 + Babel
  • jQuery + BootStrap (UI)

§ 快速开始

在开始前,希望您已通读如下资料

同时您还需要熟悉 ES6。例如,请把如下代码
const foo = ({ hello: { world: bar } }) => ({ bar })
转译成 ES5(答案请自行到 Babel REPL 在线编译验证)

⊙ 安装

推荐升级到 node 5.x/6.x + npm 3.x 环境,强烈推荐使用 cnpm 安装依赖或手动
切换到淘宝 npm 源:npm set registry https://registry.npm.taobao.org/
(经测试,cnpm 对于 node-sass 等问题多多的 Package 拥有秒杀能力)

本示例项目需要结合 简易留言板 RESTful API
模拟前后端分离开发(还为了与 Vue Demo 共用)
请分别 git clone,打开两个命令窗口( Windows 下推荐使用 Cygwin / Git Bash分别切换到两者的目录下
分别敲下 npm install 安装依赖(为避免 Windows 下 npm 2.x 的软链接问题,可加上 --no-bin-link 完全解构所有依赖)

⊙ 启动

先后在 msg-board-apireact-demo 的命令窗口下,敲下 npm start
如无意外,默认浏览器就会自动打开 localhost:9090,您立即可以看到效果
若浏览器没有自动弹出,则请自行手动访问

P.S. 如果您还不清楚如何安装与启动,请看这个 issue


§ 项目架构

⊙ 目录结构

.
├─ build/            # Webpack 配置目录
├─ dist/             # build 生成的生产环境下的项目
├─ src/              # 源码目录(开发都在这里进行)
│   ├─ assets/         # 放置需要经由 Webpack 处理的静态文件
│   ├─ components/     # 组件(COMPONENT)
│   ├─ redux/          # Redux 一箩筐
│   │   ├─ actions/      # (ACTION)
│   │   ├─ reducers/     # (REDUCER)
│   │   ├─ store/        # (STORE)
│   ├── routes/        # 路由(ROUTE)
│   ├── services/      # 服务(SERVICE,用于统一管理 XHR 请求,这是从 Vue Demo 中直接复制过来的)
│   ├── utils/         # 工具库(UTIL)
│   │   ├─ HoC/          # 高阶组件(HOC,全称 Higher Order Component)
│   │   ├─ mixins/       # 混合(MIXIN)
│   ├── views/         # 路由视图基页(VIEW)
│   │   ├─ layout/       # 全局布局
│   ├── app.js         # 启动文件
│   ├── index.html     # 静态基页
├── static/          # 放置无需经由 Webpack 处理的静态文件
├── .babelrc         # Babel 转码配置
├── .eslintignore    # (配置)ESLint 检查中需忽略的文件(夹)
├── .eslintrc        # ESLint 配置
├── .gitignore       # (配置)需被 Git 忽略的文件(夹)
├── package.json     # (这个就不用多解释了吧)

在这里您可能会问:怎么没有 containers/ 目录?
在本项目中,木偶组件与智能组件最大的差别在于:
前者的状态是通过父组件传入获得,而后者是直接连接state 获得
亦即:若一个木偶组件直接连接state,那么它就是一个所谓的智能组件
(详见 src/utils/createContainer.js 中对 react-reduxconnect 函数的封装)
本示例项目唯一在组件的定义中自行使用 connect 函数的是 Navbar 组件(且用到了 ES7 的装饰器)

有关木偶组件与智能组件更为精确的论述,推荐 Redux 作者 Dan 的这篇文章,避免教条主义

您可以根据业务需求改动目录结构。若目录使用频繁,建议配置 路径别名
默认的路径别名见上面目录结构注释中大写形式的常量
特别推荐: 更新版本的 Vue Demo 文档 · 目录结构

⊙ 特色

  • 本示例项目秉承最佳实践,高度洁癖地实现代码分离/复用
  • 优化目录结构,更好的模块分离,更接近 Vue 的开发模式
  • Redux DevTools,可选 Chrome 插件形式(默认) 或 内嵌页面的组件形式
  • Redux Logger 打印动作及前后状态变化
  • why-did-you-update 检测不必要的组件重渲染(默认关闭)
  • 引入服务层统一管理 XHR 请求(好处请参考 Vue Demo 中的 引入服务层
  • 引入 路径别名 实现优雅的加载模式
  • 引入 React Hot Reload,支持热替换
  • 生产环境下的编译对代码进行优化
  • 迄今为止我见过的最完美的 starter kit

有关 Redux DevTools 与 why-did-you-update 的启用与禁用,见下面的 开发环境全局变量 配置


§ 开发

⊙ Webpack 配置

由于已经拥有相对成熟的 Webpack 配置,因此在一定程度上您可以不求甚解,但了解其配置会更能把握整体开发

  • 前端开发服务器为 localhost:9090,可在 build/webpack.dev.conf.js 中找到

后端 RESTful API 基地址写在了 src/services/xhr/config.js 中,请根据实际自行修改

  • 框架 / 类库 须分离打包以加快开发时的编译速度并有利于缓存,详见 build/webpack.base.conf.js 中的 vendor

实际上该步骤可通过读取 package.jsondependencies 字段实现自动化,但其灵活度不够高,必要性也不大
P.S. 安装包时勿忘 --save / --save-dev 以添加依赖记录

  • 路径别名 的定义位于 build/webpack.base.conf.js,好处就是引入与重构都很方便

例如,在某组件中,引入 userService 需要 import userService from '../../../services/userService'
但有了路径别名后,只需要 import userService from 'SERVICE/userService'
相比于 AngularJS 中的依赖注入,这种方式依赖于构建工具,显得更为简单

您可能会说,Webpack 只需要设定了 root属性为 src/
就可以 import userService from 'services/userService'
但在这里其实是会引起歧义的(不过这属于强迫症的范畴。。。)
例如,import createBrowserHistory from 'history/lib/createBrowserHistory'
您可能会觉得这是 src/history/lib/createBrowserHistory.js
但实际上 history 是一个 npm package
同样地,您又怎么知道 services 不是一个 npm package?
而且重构之后,文件夹的变动会导致相对路径的变化,services/ 目录未必仍在 src/
因此,路径别名相当有必要。其常量的形式,让人一看就知道不是一个 npm package

  • 开发环境全局变量,由 webpack.DefinePlugin 提供(详见 build/webpack.base.conf.js

默认有 __DEV__ / __PROD__ / __COMPONENT_DEVTOOLS__ / __WHY_DID_YOU_UPDATE__ 四个全局变量
若要继续添加,则还需要在 .eslintrcglobals 同步写入

在此需要提醒,在 package.json 中设置 NODE_ENV 要注意末尾空格的问题
最好就是使用前 trim 一下:process.env.NODE_ENV.trim()

拓展阅读:解读 UglifyJS
看看生产环境下编译 if (__PROD__) { ... } => if (true) { ... }UglifyJS 会如何处理

⊙ 规范

本示例项目的代码极尽详细地添加了注释,其中不乏最佳实践提示

为了减少代码量,我省去了 Prop 验证,建议您在往后的开发中使用

⊙ 性能

大概可参阅如下文章:


§ 测试

请自行选择测试工具


§ 部署

react-demo 的命令窗口下,敲下 npm run build,将会在项目根目录下生成 dist/

您可以使用命令行静态资源服务器 serve ( npm i serve -g ),敲下 serve dist/ -p [端口] 来快速查看 build 后的项目
还可以 cd dist 后,python -m SimpleHTTPServer [端口]php -S localhost:[端口] 快速便捷地实现静态资源服务器

关于生产环境下的部署与优化,已超出本文档的论述范围,请自行查阅相关资料


§ 参考

Main metrics

Overview
Name With Ownerkenberkeley/react-demo
Primary LanguageJavaScript
Program languageJavaScript (Language Count: 2)
Platform
License:
所有者活动
Created At2016-08-02 09:44:32
Pushed At2023-04-24 08:26:40
Last Commit At2017-07-03 10:43:17
Release Count0
用户参与
Stargazers Count1.9k
Watchers Count104
Fork Count535
Commits Count64
Has Issues Enabled
Issues Count38
Issue Open Count4
Pull Requests Count2
Pull Requests Open Count2
Pull Requests Close Count4
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private