This repository has been archived by the owner on Jun 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
lawler61
committed
Jun 20, 2019
1 parent
bc1991d
commit 817e47a
Showing
78 changed files
with
7,506 additions
and
333 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,6 @@ node_modules/ | |
build | ||
dist | ||
config | ||
server | ||
app/mobx | ||
app/tools |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,152 @@ | ||
# init-react-project | ||
To initialize your react project | ||
# react-lighter | ||
|
||
## 初始化 react 项目 | ||
to initialize your react project as simple as lighting a fire | ||
|
||
初始化 react 项目 | ||
|
||
## 技术栈 | ||
|
||
react + mobx + router + antd + axios | ||
|
||
## 目录结构 | ||
|
||
```markdown | ||
├── src // 项目主目录 | ||
│ ├── assets | ||
│ ├── components // 可重用组件 | ||
│ ├── index.tsx | ||
│ ├── interface.ts | ||
│ ├── mobx // mobx 注入工具 | ||
│ ├── pages // 项目界面 | ||
│ │ ├── 404 | ||
│ │ └── Example | ||
│ ├── routes | ||
│ ├── tools // 脚手架 | ||
│ ├── utils | ||
│ └── websocket | ||
└── config // webpack 配置 | ||
``` | ||
|
||
## 运行 | ||
|
||
```bash | ||
yarn or npm i // 下载包 | ||
yarn dll // 预编译 | ||
yarn start // 本地开发 | ||
yarn build // 项目打包 | ||
yarn server // 加载打包后的项目 | ||
yarn or npm i | ||
|
||
yarn dll | ||
|
||
yarn start // for dev | ||
|
||
yarn build && yarn server // for prod | ||
``` | ||
|
||
## 特点 | ||
|
||
待更新 | ||
### 一、热加载 | ||
|
||
采用 [react-hot-loader](https://github.com/gaearon/react-hot-loader) 配合 babel,可实现样式替换、节点改变不影响 state 等功能,达到局部热加载的效果 | ||
|
||
### 二、抽离 dll | ||
|
||
使用 webpack DllReferencePlugin 插件,先把 react 抽离成 dll,在后续开发中能更快加载 | ||
|
||
### 三、多线程打包 | ||
|
||
使用 [happypack](https://github.com/amireh/happypack) 启动多线程,实现光速打包 | ||
|
||
### 四、css 处理 | ||
|
||
1. 使用 [postcss](https://github.com/postcss/postcss) 提供样式兼容 | ||
|
||
2. 使用 [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) 抽离 css | ||
|
||
3. 使用 [purgecss-webpack-plugin](https://github.com/FullHuman/purgecss-webpack-plugin) 去除无用 css | ||
|
||
4. 使用 [postcss-px-to-viewport](https://github.com/evrone/postcss-px-to-viewport) 规范长度单位 | ||
|
||
### 五、mobx 注入 | ||
|
||
参考: | ||
|
||
- [用mobx构建大型项目的最佳实践](https://juejin.im/post/5c627df76fb9a049c232e990) | ||
|
||
- [mobx 项目最佳实践](https://github.com/luruozhou/mobx-example) | ||
|
||
1. mobx 分层:views、actions、stores | ||
|
||
> views 派发 actions,由 actions 做逻辑处理后调用 stores 做数据持久化,views 通过注入的 stores 获取到最新的数据。典型的 MVC 架构 | ||
> | ||
> 解决了 mobx 中数据随处可定义、逻辑交互方法随处可声明等问题 | ||
2. 唯一数据源 | ||
|
||
## TODO | ||
> 每个 view 绑定 store 数据源,顶层 view 保存着全局数据源,类似于 redux 的 createStore 机制 | ||
> | ||
> 实现了 stores 间交叉引用的可能,同时能够达到 redux 中 initialState 的“数据恢复”机制 | ||
1. react-hot-loader 监听 css 变化(react-hot-loader 不能监听抽离的 css 代码) √ | ||
3. 按需实例化 | ||
|
||
> 通过 [ts-plugin-mmlpx 插件](https://github.com/mmlpxjs/ts-plugin-mmlpx),实现 stores 和 actions 的自动查找和绑定、通过 Object.defineProperty 实现按需实例化,提高性能 | ||
4. tools 脚手架使用 | ||
|
||
> 参见 [mobx example 开发章节](https://github.com/luruozhou/mobx-example#%E5%BC%80%E5%8F%91) | ||
### 六、Axios 封装 | ||
|
||
参考 | ||
|
||
- [axios restful 封装](https://github.com/zhaotoday/rest) | ||
|
||
将 axios 进行 restful 风格的封装,配合 interceptor 和 histroy 进行权限验证和跳转 | ||
|
||
使用: | ||
|
||
1. GET /users/:id | ||
|
||
```js | ||
request.setPath('users').get({ uri: 'lawler' }) | ||
``` | ||
|
||
2. POST /users | ||
|
||
```js | ||
request.setPath('users').post({ | ||
data: { email: 'lawler61@163.com', password: '123456' } | ||
}) | ||
``` | ||
|
||
3. PUT /users/:id | ||
|
||
```js | ||
request.setPath('users').put({ | ||
uri: 'lawler', data: { name: 'jeffery' } | ||
}) | ||
``` | ||
|
||
4. DELETE /users/:id | ||
|
||
```js | ||
request.setPath('users').delete({ uri: 'lawler' }) | ||
``` | ||
|
||
5. GET /users/:id/articles?page=2&limit=10 | ||
|
||
```js | ||
request.setPath('users/{id}/articles').replace('lawler').get({ | ||
query: { page: 2, limit: 10 } | ||
}) | ||
``` | ||
|
||
6. PATCH /users/:id/articles/:id | ||
|
||
```js | ||
request.setPath('users/{id}/articles/{id}').replace('lawler', 'react 学习之路').patch({ | ||
data: { title: '前端学习' } | ||
}) | ||
``` | ||
|
||
2. 懒加载组件 √ | ||
## 项目展示 | ||
|
||
3. 去除无用 css 代码 (不能使用 css 分离,否则无法去除)√ | ||
1. [问答系统 前端 -> https://github.com/lawler61/qa-app](https://github.com/lawler61/qa-app) | ||
|
||
4. 制作成脚手架 | ||
2. [线上地址,去看看 -> https://qa.omyleon.com](https://qa.omyleon.com) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
// https://github.com/mmlpxjs/ts-plugin-mmlpx | ||
|
||
const ts = require('typescript') | ||
|
||
const defaultOptions = { | ||
bindings: ['mStore', 'mAction'] | ||
} | ||
|
||
const createTransformer = (options = defaultOptions) => { | ||
const transformer = context => { | ||
const bindings = [] | ||
|
||
let fileName, pageName | ||
|
||
const visitor = node => { | ||
if (ts.isSourceFile(node)) { | ||
;[pageName, fileName] = getFileNameFrom(node.fileName) | ||
return ts.visitEachChild(node, visitor, context) | ||
} | ||
|
||
if (ts.isImportDeclaration(node)) { | ||
node.forEachChild(importChild => { | ||
if ( | ||
ts.isImportClause(importChild) && | ||
importChild.namedBindings && | ||
ts.isNamedImports(importChild.namedBindings) | ||
) { | ||
importChild.namedBindings.elements.forEach( | ||
({ propertyName, name }) => { | ||
// import {mStore as otherName} from './store.js' | ||
const lib = node.moduleSpecifier.text // './store.js' 暂时没用到 | ||
const namedBinding = | ||
(propertyName && propertyName.getText()) || name.getText() // mStore | ||
const aliasBinding = propertyName && name.getText() //otherName | ||
if (options.bindings.indexOf(namedBinding) > -1) { | ||
bindings.push(aliasBinding || namedBinding) | ||
} | ||
} | ||
) | ||
} | ||
}) | ||
|
||
return node | ||
} | ||
|
||
if (node.decorators) { | ||
node.decorators.forEach(decorator => { | ||
const { expression } = decorator | ||
if ( | ||
ts.isIdentifier(expression) && | ||
bindings.indexOf(expression.getText()) > -1 | ||
) { | ||
// 调用形式 @mStore @mAction | ||
decorator.expression = ts.createCall(expression, undefined, [ | ||
ts.createObjectLiteral([ | ||
ts.createPropertyAssignment( | ||
ts.createLiteral('page'), | ||
ts.createLiteral(`${pageName}`) | ||
), | ||
ts.createPropertyAssignment( | ||
ts.createLiteral('name'), | ||
ts.createLiteral(`${fileName}`) | ||
) | ||
]) | ||
]) | ||
} else if ( | ||
ts.isCallExpression(expression) && | ||
ts.isIdentifier(expression.expression) && | ||
bindings.indexOf(expression.expression.getText()) > -1 | ||
) { | ||
// 调用形式 @mStore({...someProps}) @mAction({...someProps}) | ||
let arg0 = expression.arguments[0] | ||
if (ts.isObjectLiteralExpression(arg0)) { | ||
decorator.expression = ts.createCall( | ||
expression.expression, | ||
undefined, | ||
[ | ||
ts.createObjectLiteral([ | ||
ts.createPropertyAssignment( | ||
ts.createLiteral('page'), | ||
ts.createLiteral(`${pageName}`) | ||
), | ||
ts.createPropertyAssignment( | ||
ts.createLiteral('name'), | ||
ts.createLiteral(`${fileName}`) | ||
), | ||
...arg0.properties | ||
]), | ||
...expression.arguments.slice(1) | ||
] | ||
) | ||
} | ||
} | ||
}) | ||
|
||
return node | ||
} | ||
|
||
return ts.visitEachChild(node, visitor, context) | ||
} | ||
|
||
return node => ts.visitNode(node, visitor) | ||
} | ||
|
||
return transformer | ||
} | ||
|
||
function getFileNameFrom(path) { | ||
let reg = /([^\/]+)\/(?:actions|stores)\/(.+)\.(?:t|j)sx?$/ | ||
let matched = path.match(reg) | ||
let pageName = matched && matched[1] | ||
let fileName = matched && matched[2] | ||
return [pageName, fileName] | ||
} | ||
|
||
module.exports = createTransformer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.