React 示例项目 · 简易留言板 + 待办事项(Github 地址)
写在前面
一直以来,我都相当纳闷:为什么 React 的那些 starter kit 都构建得那么恶心? 能不能像 Vue Cli 生成的项目架构般优雅?说干就干,本项目就改自 Vue Demo
§ 技术栈
详情可参阅 package.json
§ 快速开始
在开始前,希望您已通读如下资料
同时您还需要熟悉 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/
本示例项目需要结合 简易留言板 RESTful API 模拟前后端分离开发(还为了与 Vue Demo 共用) 请分别 git clone ,打开两个命令窗口( Windows 下推荐使用 Cygwin )分别切换到两者的目录下 分别敲下 npm install 安装依赖(为避免 Windows 下的 npm 软链接问题,可加上 --no-bin-link 完全解构所有依赖)
虽然我们已经切换到了淘宝 npm 源,但安装 node-sass@3.8.0 的时候还是很有可能卡住 因为它的安装需要从 Github 的 AWS 服务器拉取二进制文件,因此您可以为它指定源:
npm i node-sass@3.8.0 --registry=https://registry.npm.taobao.org
如果您想简单粗暴一点,这里还提供了 node_modules.zip ,直接解压即可
⊙ 启动
先后在 msg-board-api 、react-demo 的命令窗口下,敲下 npm start 如无意外,默认浏览器就会自动打开 localhost:9090 ,您立即可以看到效果 若浏览器没有自动弹出,则请自行手动访问
开发过程中,通过 Webpack 处理的静态资源都由基于内存的 webpack-dev-server 提供 P.S. 如果您还不清楚如何安装与启动,请看这个 issue
§ 项目架构
⊙ 目录结构
.
├─ build/ # Webpack 配置目录
├─ dist/ # build 生成的生产环境下的项目
├─ src/ # 源码目录(开发都在这里进行)
│ ├─ 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/makeContainer.js 中对 react-redux 的 connect 函数的封装) 本示例项目唯一在组件的定义中自行使用 connect 函数的是 Navbar 组件(且用到了 ES7 的装饰器)
您可以根据业务需求改动目录结构。若目录使用频繁,建议配置 路径别名 默认的路径别名见上面目录结构注释中大写形式的常量
⊙ 特色
本示例项目秉承最佳实践,高度洁癖地实现代码分离/复用
优化目录结构,更好的模块分离,更接近 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 配置,因此在一定程度上您可以不求甚解,但了解其配置会更能把握整体开发
后端 RESTful API 基地址写在了 src/services/xhr/config.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
默认有 __DEV__ / __PROD__ / __COMPONENT_DEVTOOLS__ / __WHY_DID_YOU_UPDATE__ 四个全局变量 若要继续添加,则还需要在 .eslintrc 中 globals 同步写入
在此需要提醒,在 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 -p [端口] dist 来快速查看 build 后的项目 还可以 cd dist 后,python -m SimpleHTTPServer [端口] 或 php -S localhost:[端口] 快速便捷地实现静态资源服务器
关于生产环境下的部署与优化,已超出本文档的论述范围,请自行查阅相关资料 在这里您可能需要全局安装 rimraf: npm i rimraf -g (或根据指引配置环境变量避免全局安装)
§ 参考
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|