Skip to content

Commit 5a3be8d

Browse files
chenbin92Yurisaluhc228ClarkXia
authored
feat: rax ssr (#3588)
* chore: bump version * fix: catch debug webpackConfig error (#3541) * fix: catch debug webpackConfig error * fix: serializing object that contains cyclic object value * chore: code optimize (#3549) * chore: code optimize * chore: bump version * feat: support px2vw (#3546) * feat: support px2vw * docs: changelog.md update * docs: package.json update * docs: fusion.md add usePx2Vw option * fix: remove use postcss-loader * fix: ignore rules (#3544) * docs: test guide (#3545) * chore: bump version * chore: bump version * hotifx: store is undefined in class component (#3579) * feat: support rax ssr * chore: rename plugin ssr * feat: support set the SSR in the build.json * chore: reset code * chore: bump version * fix: eslint warnings (#3543) * feat: call the getInitialData method of appConfig * feat: support mode mpa of rax-app (#3575) * feat: support mpa plugin * fix: build-mpa-config * fix: remove mpa-loader * fix: entry error * fix: ts config * feat: support mpa ssr * feat: support mpa loader (#3594) * fix: update react-refresh-webpack-plugin version (#3558) * feat: support set html in mpa mode (#3566) * feat: support set html in mpa mode * chore: update mpa example * chore: code optimize * chore: code optimize * chore: update example * chore: optional staticConfig * fix: mpa loader in node env * fix: command args * fix: support weex mpa * refactor: rename packages * chore: dependency * chore: code optimize Co-authored-by: Yurisa <779509411@qq.com> Co-authored-by: Hengchang Lu <44047106+luhc228@users.noreply.github.com> Co-authored-by: ClarkXia <xiawenwu41@gmail.com>
1 parent d6d404b commit 5a3be8d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+1557
-321
lines changed

.eslintignore

+4
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ coverage/
2121
**/*.min.js
2222

2323
workspace/
24+
25+
# 忽略 rax 示例
26+
examples/with-rax
27+
examples/with-rax-store

.eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const tsRules = deepmerge(tslint, {
2929
"@typescript-eslint/no-explicit-any": 0,
3030
"@typescript-eslint/interface-name-prefix": 0,
3131
"@typescript-eslint/explicit-function-return-type": 0,
32+
"@typescript-eslint/no-var-requires": 0
3233
},
3334
});
3435

.gitignore

+21-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# https://github.com/github/gitignore/blob/master/Node.gitignore
12
# Dependencies
23
node_modules
34
jspm_packages
@@ -7,7 +8,27 @@ package-lock.json
78
*/**/yarn.lock
89

910
# Logs
11+
logs
1012
*.log
13+
npm-debug.log*
14+
yarn-debug.log*
15+
yarn-error.log*
16+
lerna-debug.log*
17+
18+
# Coverage directory used by tools like istanbul
19+
coverage
20+
*.lcov
21+
22+
# Others
23+
.npm
24+
.eslintcache
25+
.idea
26+
.DS_Store
27+
.happypack
28+
.vscode
29+
.tmp
30+
*.swp
31+
*.dia~
1132

1233
# Packages
1334
packages/*/lib/
@@ -16,10 +37,4 @@ packages/*/lib/
1637
examples/*/.ice
1738
examples/*/.rax
1839

19-
.eslintcache
20-
docs/.vuepress/dist/
21-
2240
build
23-
coverage
24-
25-
.idea

docs/guide/advance/backend.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: 后端应用集成
3-
order: 17
3+
order: 18
44
---
55

66
> 如果是阿里内部同学,请参考 [文档](https://yuque.alibaba-inc.com/ice/rdy99p/rpivf3)

docs/guide/advance/fusion.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ $ npm install build-plugin-fusion --save-dev
1919
* `nextPrefix` Fusion 组件样式 prefix,一般情况下需要配合入口代码的 `ConfigProvider` 使用,可以将所有的 className 改掉
2020
* `importOptions``babel-plugin-import` 参数,默认为 `{ style: true, libraryDirectory: 'es'}` 根据用户设置项将进行合并
2121
* `externalNext` 配合 `externals` 配置,将 Next 组件作为外部依赖引入
22+
* `usePx2Vw` 配合postcss插件,将css样式单位px转化为vw,默认为false不开启,true为开启
2223

2324
## 基础用法
2425

docs/guide/advance/publish.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: 前端资源发布
3-
order: 15
3+
order: 16
44
---
55

66
> 如果是阿里内部同学,请参考 [文档](https://yuque.antfin-inc.com/ice/rdy99p/syvuzh)

docs/guide/advance/quality.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: 代码质量保障
3-
order: 16
3+
order: 17
44
---
55

66
为了保证代码质量,我们推荐使用 lint 相关的工具对代码进行检测,同时为了降低常规 lint 工具的使用成本,我们封装了 [@ice/spec](https://github.com/ice-lab/spec) 这个 npm 包。

docs/guide/advance/statistical.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: 页面埋点统计数据
3-
order: 18
3+
order: 19
44
---
55

66
> 阿里内部用户请参考:https://yuque.antfin-inc.com/ice/rdy99p/paswzc

docs/guide/advance/test.md

+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
---
2+
title: 编写单元测试
3+
order: 15
4+
---
5+
6+
icejs 支持 `icejs test` 命令,内置 Jest 配置提供前端的单元测试解决方案。
7+
8+
## 测试文件名约定
9+
10+
默认的 `testMatch``**/?*.(spec|test).(j|t)s?(x)`,即 icejs 将查找项目目录下所有符合条件的文件来执行测试
11+
12+
* 文件后缀为 `.spec.js``.spec.jsx``.spec.ts``.spec.tsx`
13+
* 文件后缀为 `.test.js``.test.jsx``.test.ts``.test.tsx`
14+
15+
## 使用 jest.config.js
16+
17+
`icejs` 已经内置了 Jest 测试所需的配置,提供了开箱即用的测试能力,如果需要定制自己的 Jest 配置,可以在项目目录下添加 `jest.config.js` 文件。
18+
19+
```js
20+
// jest.config.js
21+
module.exports = {
22+
testMatch: ['**/?*.e2e.js'],
23+
};
24+
```
25+
26+
jest.config.js 中自定义配置最终将和默认配置进行合并,更多 Jest 相关配置,请参见[官网](https://jestjs.io/docs/en/configuration)
27+
28+
## 使用 Jest 相关参数
29+
30+
`icejs` 通过约定的方式支持所有 Jest CLI 参数,相关参数增加 jest 前缀即可。
31+
32+
```bash
33+
# Jest CLI 参数 --config=<path>
34+
$ icejs test --jest-config=<path>
35+
36+
# Jest CLI 参数 --watchAll
37+
$ icejs test --jest-watchAll
38+
```
39+
40+
## 编写测试用例
41+
42+
使用 Jest 提供的内置函数可以快速创建相应的测试用例
43+
44+
```js
45+
function sum(a, b) {
46+
return a + b;
47+
}
48+
49+
it('sum numbers', () => {
50+
expect(sum(1, 2)).toEqual(3);
51+
expect(sum(2, 2)).toEqual(4);
52+
});
53+
```
54+
55+
在日常 React 项目开发中,上述简单的例子不足以满足测试需求,测试实践中的需求往往可以可以分为两类,根据相应的需求可以选择社区的工具来帮助完成测试。
56+
57+
* 通过快照进行 UI 测试 - 可以通过 Jest SnapShot 能力进行测试
58+
* DOM 交互测试 - 推荐使用 Enzyme,它提供了强大的 API 能力支持 UI 交互测试
59+
60+
### 使用 Snapshot 进行 UI 测试
61+
62+
Snapshot 测试是 Jest 提供的能力,可以自动生成组件 UI 输出的描述文件,确保你的 UI 不会发生意外的改变。
63+
64+
组件实现代码:
65+
66+
```js
67+
// ./src/test.js
68+
import React from 'react';
69+
70+
export default function Test() {
71+
return (
72+
<div className="test-component">
73+
test
74+
</div>
75+
);
76+
}
77+
```
78+
79+
组件测试代码:
80+
81+
```js
82+
// ./test/snapshot.test.js
83+
import React from 'react';
84+
import renderer from 'react-test-renderer';
85+
import Test from '../src/test';
86+
87+
it('renders', () => {
88+
const tree = renderer
89+
.create(<Test />)
90+
.toJSON();
91+
expect(tree).toMatchSnapshot();
92+
});
93+
```
94+
95+
在第一次运行后,Jest Snapshot 将会生成对应的 `.snap` 文件,如果组件的输出内容发生变更,则会导致测试用例无法通过。
96+
97+
### 使用 Enzyme 测试组件
98+
99+
Enzyme 是 Airbnb 提供的测试类库,它提供了一套简洁强大的 API。能够灵活操作 DOM,是 React 社区推荐的测试方案。
100+
101+
#### 准备工作
102+
103+
安装测试相关依赖包
104+
105+
```bash
106+
$ npm install --save-dev enzyme enzyme-adapter-react-16 react-test-renderer
107+
```
108+
109+
基于 React 开发的测试,需要安装对应的 React Adapter 来保证 enzyme 渲染的版本和项目中使用的版本一致,以 react 16 版本为例,需要进行如下设置:
110+
111+
```js
112+
import { configure } from 'enzyme';
113+
import Adapter from 'enzyme-adapter-react-16';
114+
115+
configure({ adapter: new Adapter() });
116+
```
117+
118+
如果不想每个测试用例都去定义一遍,可以将上述内容保存至 `src/setupTests.js` 文件中,并自定义 Jest 配置中的 `setupFilesAfterEnv`
119+
120+
```js
121+
// jest.config.js
122+
module.exports = {
123+
setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
124+
};
125+
```
126+
127+
#### 组件测试用例
128+
129+
Enzyme 提供 shallow 方法对组件进行浅渲染,即它仅仅会渲染至虚拟 DOM,不会返回真实的 DOM 节点。多数情况下 shallow 方法就能满足测试需求。
130+
131+
组件实现代码:
132+
133+
```js
134+
import React, { useState } from 'react';
135+
136+
export default function Test() {
137+
const [content, setContent] = useState('default content');
138+
function onContentChanged() {
139+
setContent('test');
140+
}
141+
return (
142+
<div className="test-component">
143+
<span>{content}</span>
144+
<button onClick={onContentChanged}>button</button>
145+
</div>
146+
);
147+
}
148+
```
149+
150+
使用 shallow 方法测试组件:
151+
152+
```js
153+
import React from 'react';
154+
import Test from '../src/test';
155+
import { shallow } from 'enzyme';
156+
157+
it('renders', () => {
158+
const wrapper = shallow(<Test />);
159+
const button = wrapper.find('button').at(0);
160+
// 模拟触发 点击 事件,来改变当前的 state
161+
button.simulate('click');
162+
expect(wrapper.find('span').at(0).text()).toBe('test');
163+
});
164+
```
165+
166+
更多测试用例编写,可以参考 [Enzyme 官网](https://airbnb.io/enzyme/)

examples/basic-mpa/build.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
2-
"mpa": true,
2+
"mpa": {
3+
"openPage": "Home",
4+
"template": {
5+
"web.html": ["Dashboard", "Home"]
6+
}
7+
},
38
"plugins": []
49
}

examples/basic-mpa/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"@types/react-dom": "^16.9.4"
1212
},
1313
"scripts": {
14-
"start": "icejs start --mpa-entry Dashboard",
14+
"start": "icejs start",
1515
"build": "icejs build"
1616
},
1717
"engines": {
File renamed without changes.

examples/basic-store/src/pages/About/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useEffect } from 'react';
2-
import { Link, store as appStore } from 'ice';
2+
import { Link, store as appStore } from 'ice';
33
import { store as pageStore } from 'ice/About';
44

55
const About = (props) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
import { store } from 'ice/Detail';
3+
4+
class Detail extends React.Component {
5+
constructor(props) {
6+
super(props);
7+
console.log(this.props);
8+
}
9+
10+
public render() {
11+
const { default: detailStore } = this.props as any;
12+
const [state, dispatcher] = detailStore;
13+
return (
14+
<>
15+
<div>Detail Page</div>
16+
<div>Title: {state.title}</div>
17+
<button onClick={() => dispatcher.updateDetailTitle('test')} type="button">Change Title</button>
18+
</>
19+
);
20+
}
21+
}
22+
23+
export default store.withModel('default')(Detail);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const delay = (time) => new Promise((resolve) => setTimeout(() => resolve(), time));
2+
3+
4+
export default {
5+
state: {
6+
title: 'detail'
7+
},
8+
9+
reducers: {
10+
update(prevState, payload) {
11+
return {
12+
...prevState,
13+
...payload,
14+
};
15+
},
16+
},
17+
18+
effects: (dispatch) => ({
19+
async updateDetailTitle(title: string) {
20+
await delay(1000);
21+
dispatch.default.update({
22+
title
23+
});
24+
},
25+
}),
26+
};

examples/basic-store/src/routes.ts

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import Layout from '@/layouts/index';
55
import Home from '@/pages/Home';
66
import About from '@/pages/About';
7+
import Detail from '@/pages/Detail';
78
import { NotFound } from '@/pages/NotFound';
89
import Index from '@/pages/Index';
910

@@ -25,6 +26,10 @@ export default [
2526
path: '/about',
2627
component: About
2728
},
29+
{
30+
path: '/detail',
31+
component: Detail
32+
},
2833
{
2934
path: '/index',
3035
component: Index

examples/with-rax/build.json

+5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
2+
"web": {
3+
"mpa": true,
4+
"ssr": true
5+
},
26
"plugins": [],
7+
"inlineStyle": true
38
"targets": ["web", "weex", "kraken", "miniapp"]
49
}

examples/with-rax/src/app.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
import { runApp } from 'rax-app';
22

33
runApp({
4+
router: {
5+
type: 'browser'
6+
},
47
app: {
58
onShow() {
69
console.log('app show...');
710
},
811
onHide() {
912
console.log('app hide...');
13+
},
14+
getInitialData: async () => {
15+
return {
16+
a: 1,
17+
b: 2
18+
};
1019
}
11-
},
12-
router: {
13-
basename: '/home'
1420
}
1521
});

0 commit comments

Comments
 (0)