Skip to content

Commit d50e005

Browse files
committed
feat: update
1 parent c61f3b4 commit d50e005

File tree

21 files changed

+423
-100
lines changed

21 files changed

+423
-100
lines changed

README.md

+11-12
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,31 @@
33
服务运行
44

55
```
6-
npm i
7-
npm run dev
6+
npm i
7+
npm run dev
88
```
99

1010
## 升级内容
1111

12-
* 前端代码的实时构建
13-
* 服务端所需代码的实时编译
14-
* http 服务的自动重启
12+
- 前端代码的实时构建
13+
- 服务端所需代码的实时编译
14+
- http 服务的自动重启
1515

1616
## 缺陷
1717

1818
页面的显示内容需要刷新一次才能看到。 后续继续优化,增加热更新。
1919

20-
21-
2220
## 待做
2321

24-
- 修复构建的strat.js bug
25-
- server koa===>改造成ts
26-
- build server 改造成server
22+
- 修复构建的 strat.js bug
23+
- server koa===>改造成 ts
24+
- build server 改造成 server
2725
- 支持 redux
28-
- server端引入ejs进行渲染返回 ===> 参考nuxt
26+
- server 端引入 ejs 进行渲染返回 ===> 参考 nuxt
2927
- css
3028
- 按需加载
31-
- 引用umi文档构建
29+
- 引用 umi 文档构建
3230
- 单元测试
31+
- 8080 所有路由 获取 index 文件然后返回
3332

3433
做成一个完整的项目

build/client/dev-server.js

+13-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const express = require('express')
33
const webpack = require('webpack')
44
const devMiddleware = require('webpack-dev-middleware')
55
const hotMiddleware = require('webpack-hot-middleware')
6+
67
const webpackConfig = require('./webpack.dev.conf')
78

89
const config = require('../../config')
@@ -15,11 +16,12 @@ const main = function () {
1516
port: getPort.makeRange(port, port + 100)
1617
}).then(function (newPort) {
1718
const app = express()
19+
1820
const compiler = webpack(webpackConfig)
1921

2022
const webpackDevMiddleware = devMiddleware(compiler, {
2123
// logLevel: 'silent',
22-
index: true,
24+
index: 'index.html',
2325
publicPath: webpackConfig.output.publicPath
2426
})
2527

@@ -29,16 +31,15 @@ const main = function () {
2931
path: '/__hmr'
3032
})
3133

32-
33-
//设置跨域访问
34-
app.all('*', function(req, res, next) {
35-
res.header("Access-Control-Allow-Origin", "*");
36-
// res.header("Access-Control-Allow-Headers", "X-Requested-With");
37-
// res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
38-
// res.header("X-Powered-By",' 3.2.1')
39-
// res.header("Content-Type", "application/json;charset=utf-8");
40-
next();
41-
});
34+
//设置跨域访问
35+
app.all('*', function (req, res, next) {
36+
res.header('Access-Control-Allow-Origin', '*')
37+
// res.header("Access-Control-Allow-Headers", "X-Requested-With");
38+
// res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
39+
// res.header("X-Powered-By",' 3.2.1')
40+
// res.header("Content-Type", "application/json;charset=utf-8");
41+
next()
42+
})
4243

4344
app.use(webpackDevMiddleware)
4445

@@ -51,6 +52,7 @@ const main = function () {
5152
config.dev.assetsPublicPath,
5253
config.base.assetsSubDirectory
5354
)
55+
5456
app.use(staticPath, express.static('./static'))
5557

5658
console.log('> Starting dev server...')

build/client/webpack.base.conf.js

+25-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
const os = require('os')
22
const path = require('path')
33
const HtmlWebpackPlugin = require('html-webpack-plugin')
4-
const WebpackBar = require('webpackbar');
4+
const WebpackBar = require('webpackbar')
5+
const webpack = require('webpack')
56

67
// const ProgressBarPlugin = require('progress-bar-webpack-plugin')
78
// const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
@@ -39,18 +40,18 @@ module.exports = {
3940
test: /\.ts|\.tsx/,
4041
use: [
4142
{
42-
loader: 'babel-loader',
43-
},
44-
],
43+
loader: 'babel-loader'
44+
}
45+
]
4546
},
4647
{
4748
test: /\.ts|\.tsx|\.js|\.json/,
4849
exclude: /node_modules/,
4950
loader: 'eslint-loader',
5051
options: {
5152
fix: true,
52-
cache: true,
53-
},
53+
cache: true
54+
}
5455
},
5556
{
5657
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
@@ -84,24 +85,30 @@ module.exports = {
8485
// new ForkTsCheckerWebpackPlugin(),
8586
new WebpackBar({
8687
name: 'client',
87-
color: "green",
88-
}),
88+
color: 'green'
89+
}),
8990
new HtmlWebpackPlugin({
9091
title: config.base.title,
9192
filename: 'index.html',
9293
template: path.resolve(__dirname, '../../templates/index.ejs'),
9394
inject: true
95+
}),
96+
new webpack.DefinePlugin({
97+
'process.env': { NODE_ENV: '"development"' },
98+
__IS_PROD__: false,
99+
__SERVER__: false
94100
})
95101
],
96-
optimization: {
97-
splitChunks: {
98-
cacheGroups: {
99-
libs: { // 抽离第三方库
100-
test: /node_modules/, // 指定是node_modules下的第三方包
101-
chunks: 'initial',
102-
name: 'libs'// 打包后的文件名,任意命名
103-
}
104-
}
102+
optimization: {
103+
splitChunks: {
104+
cacheGroups: {
105+
libs: {
106+
// 抽离第三方库
107+
test: /node_modules/, // 指定是node_modules下的第三方包
108+
chunks: 'initial',
109+
name: 'libs' // 打包后的文件名,任意命名
105110
}
106-
},
111+
}
112+
}
113+
}
107114
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"@typescript-eslint/parser": "^4.22.0",
5555
"babel-loader": "^8.2.2",
5656
"clean-webpack-plugin": "^4.0.0-alpha.0",
57+
"connect-history-api-fallback": "^1.6.0",
5758
"css-loader": "^3.4.0",
5859
"eslint": "^7.25.0",
5960
"eslint-loader": "^4.0.2",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
import React from 'react';
3+
import LoadingCompoent from '../loading'
4+
5+
6+
/**
7+
* 动态加载组件一个组的容器
8+
*
9+
* @class Bundle
10+
* @extends {Component}
11+
*/
12+
export default class AsyncBundle extends React.Component<any, any> {
13+
constructor(props: any) {
14+
super(props);
15+
this.state = {
16+
mod: null
17+
};
18+
}
19+
20+
componentDidMount() {
21+
if (!this.state.mod) {
22+
this.load(this.props);
23+
}
24+
}
25+
26+
// UNSAFE_componentWillReceiveProps(nextProps) {
27+
28+
// //路由改变才会按需
29+
// if (nextProps.match && this.props.match && (nextProps.match.url !== this.props.match.url)) {
30+
// this.load(nextProps);
31+
// }
32+
// }
33+
34+
35+
load(props: any) {
36+
this.setState({
37+
mod: null
38+
});
39+
//注意这里,使用Promise对象; mod.default导出默认
40+
props.load().then((mod: any) => {
41+
this.setState({
42+
mod: mod.default ? mod.default : mod
43+
});
44+
});
45+
}
46+
47+
render() {
48+
// @ts-ignore
49+
return this.state.mod ? this.props.children(this.state.mod) : <LoadingCompoent />;
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//异步加载组件的高阶函数
2+
3+
import AsyncBundle from '../asyncBundle'
4+
// @ts-ignore
5+
import proConfig from '../../../common/pro-config.js'
6+
import React from 'react'
7+
function AsyncLoader(loader: any) {
8+
function asyncFn(props: any) {
9+
return <AsyncBundle load={loader}>{(Comp: any) => <Comp {...props} />}</AsyncBundle>
10+
}
11+
12+
//标记为异步组件
13+
// @ts-ignore
14+
asyncFn[proConfig.asyncComponentKey] = true
15+
16+
return asyncFn
17+
}
18+
19+
export default AsyncLoader
+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// 高阶组件 用于提取重复逻辑
2+
3+
import React from 'react'
4+
5+
let _this: any = null
6+
let _isPop = false //是否触发过popState
7+
let _isMount = false //组件是否挂载完成
8+
const popStateCallback = () => {
9+
// 使用 popStateCallback 保存函数防止 addEventListener 重复注册
10+
if (_this && _this.getInitialProps) {
11+
console.log('popStateFn')
12+
_isPop = true
13+
if (_isMount) {
14+
//只有当前组件挂载后才能执行数据预取,否则会报错
15+
_this.getInitialProps()
16+
}
17+
}
18+
}
19+
20+
export default (SourceComponent: any) => {
21+
return class HoComponent extends React.Component<any, any> {
22+
constructor(props: any) {
23+
super(props)
24+
25+
this.state = {
26+
initialData: {},
27+
canClientFetch: false // 浏览器端是否需要请求数据
28+
}
29+
}
30+
// 用于服务端调用
31+
static async getInitialProps(ctx: any) {
32+
return SourceComponent.getInitialProps
33+
? await SourceComponent.getInitialProps(ctx)
34+
: {}
35+
}
36+
37+
//用于封装处理
38+
async getInitialProps() {
39+
// ssr首次进入页面以及csr/ssr切换路由时才调用组件的getInitialProps方法
40+
const { match, location } = this.props
41+
const res = SourceComponent.getInitialProps
42+
? await SourceComponent.getInitialProps({ match, location })
43+
: {}
44+
this.setState({
45+
initialData: res,
46+
canClientFetch: true
47+
})
48+
49+
console.log('getInitialProps')
50+
let { tdk } = res.page
51+
if (tdk) {
52+
document.title = tdk.title
53+
}
54+
}
55+
56+
async componentDidMount() {
57+
//注册事件,用于在页面回退和前进的时候触发
58+
_isMount = true //组件挂载完成
59+
// @ts-ignore
60+
if (window.__IS__SSR__) {
61+
//只有当启用 ssr 时
62+
_this = this // 修正_this指向,保证_this指向当前渲染的页面组件
63+
//注册事件
64+
window.addEventListener('popstate', popStateCallback)
65+
66+
if (_isPop) {
67+
//如果前进或者后退 则需要异步获取数据
68+
this.getInitialProps()
69+
}
70+
}
71+
72+
const canClientFetch = this.props.history && this.props.history.action === 'PUSH' //路由跳转的时候可以异步请求数据
73+
console.log('canClientFetch', canClientFetch)
74+
// @ts-ignore
75+
if (canClientFetch || !window.__IS__SSR__) {
76+
await this.getInitialProps()
77+
}
78+
}
79+
80+
componentWillUnmount() {
81+
console.log('unmount')
82+
_isPop = false //重置为未触发
83+
_isMount = false //重置为未挂载
84+
}
85+
86+
render() {
87+
// 只有在首次进入页面需要将window.__INITIAL_DATA__作为props,路由切换时不需要
88+
89+
const props = {
90+
initialData: {},
91+
...this.props
92+
}
93+
// @ts-ignore
94+
95+
if (__SERVER__) {
96+
//服务端渲染
97+
props.initialData = this.props.staticContext.initialData || {}
98+
} else {
99+
//客户端渲染
100+
if (this.state.canClientFetch) {
101+
//需要异步请求数据
102+
props.initialData = this.state.initialData || {}
103+
} else {
104+
// @ts-ignore
105+
props.initialData = window.__INITIAL_DATA__
106+
// @ts-ignore
107+
window.__INITIAL_DATA__ = null //使用过后清除数据,否则其他页面会使用
108+
}
109+
}
110+
111+
return <SourceComponent {...props}></SourceComponent>
112+
}
113+
}
114+
}
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import React from 'react';
2+
3+
export default function LoadingComponent(props: any) {
4+
return <div>loading......</div>
5+
}

src/client/library/isConnect.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Container from '@/components/container'
2+
import { connect } from 'react-redux'
3+
// @ts-ignore
4+
import withStyles from 'isomorphic-style-loader/withStyles'
5+
6+
export default ({ css, mapStateToProps, mapDispatchToProps }:any, ActiveComponet:any) => {
7+
return withStyles(css)(
8+
connect(mapStateToProps, mapDispatchToProps)(Container(ActiveComponet))
9+
)
10+
}

0 commit comments

Comments
 (0)