@@ -414,9 +414,11 @@ app.listen(9001, () => {
414
414
console .log (' 监听9001端口' );
415
415
})
416
416
```
417
- ## 8、异常处理和请求转发
418
- ### 异常处理
419
- header页面接口报错,其它页面也能显示正常。解决方案:在axios里面需要捕获错误
417
+ ### 8、异常处理和请求转发
418
+ #### 异常处理
419
+ header页面接口报错,其它页面也能显示正常。解决方案:
420
+
421
+ (1)在axios里面需要捕获错误
420
422
``` js
421
423
export const getUserInfo = () => {
422
424
return (dispatch ) => {
@@ -430,20 +432,124 @@ export const getUserInfo = () => {
430
432
}
431
433
}
432
434
```
433
- ### 请求转发
435
+ (2)服务端给每个loadData包装成新的Promise
436
+ ``` js
437
+ if (match) {
438
+ const { loadData } = route .component ;
439
+ if (loadData) {
440
+ // 规避报错
441
+ const promise = new Promise ((resolve , reject ) => {
442
+ loadData (store).then (resolve).catch (resolve)
443
+ });
444
+ promises .push (promise);
445
+ }
446
+ }
447
+ ```
448
+ #### 请求转发
434
449
每次让服务端请求数据(转发),不需要客户端去请求数据,避免跨域。解决方案:使用``` http-proxy-middleware ```
435
450
``` js
436
451
// 使用http-proxy-middleware进行请求转发,防止出现跨域的问题
437
452
const proxy = require (' http-proxy-middleware' )
438
453
app .use (' /api/*' , proxy ({ target: ' http://localhost:8082' , changeOrigin: true }));
454
+ ```
455
+ ### 9、将axios和redux结合
456
+ (1)首先在store.js里面,创建服务端和客户端的实例,然后传入thunk.withExtraArgument的参数里面
457
+ ``` js
458
+ // 引入axios
459
+ import axios from ' axios'
460
+
461
+ const serverAxios = axios .create ({
462
+ baseURL: ' http://localhost:8081'
463
+ })
439
464
440
- // const match = matchPath(req.url, route);
441
- // if (match && route.component.loadData) {
442
- // promises.push(route.component.loadData(store))
443
- // }
465
+ const clientAxios = axios .create ({
466
+ baseURL: ' /'
467
+ })
444
468
445
- // 取消客户端拉取数据的行为,全部由服务端拉取
446
- if (route .component .loadData ) {
447
- promises .push (route .component .loadData (store))
469
+ // 获取客户端的store
470
+ export const getClientStore = () => {
471
+ // 通过window对象来获取服务端获取的数据
472
+ const defaultStore = window .__store ? window .__store : {};
473
+ console .log (' 客户端defaultStore' , defaultStore);
474
+ return createStore (reducers, defaultStore, applyMiddleware (thunk .withExtraArgument (clientAxios)))
475
+ }
476
+ // 获取服务端的store
477
+ export const getServerStore = () => {
478
+ return createStore (reducers, applyMiddleware (thunk .withExtraArgument (serverAxios)))
448
479
}
449
- ```
480
+ ```
481
+ (2)index.js里面使用$axios即可
482
+ ``` js
483
+ export const getIndexList = () => {
484
+ return (dispatch , getState , $axios ) => {
485
+ return $axios .get (' /api/course/list' ).then (res => {
486
+ const { list } = res .data
487
+ dispatch ({ type: GET_LIST , list })
488
+ }).catch (e => {
489
+ // 在这里需要捕获错误,才不会出现所有页面都挂了的情况
490
+ console .log (e)
491
+ })
492
+ }
493
+ }
494
+ ```
495
+ ### 10、css处理
496
+ 用style-loader和css-loader,服务端需要用isomorphic-style-loader
497
+ ### 11、错误页面状态码支持
498
+ ### 12、放弃SEO的降级渲染的实现
499
+ (1)server/index.js,服务端判断是否需要进行csr渲染,需要的话,就读取html模板文件
500
+ ``` js
501
+ function csrRender (res ) {
502
+ const filePath = path .resolve (process .cwd (), ' public/index.csr.html' );
503
+ return res .send (fs .readFileSync (filePath,' utf-8' ));
504
+ }
505
+
506
+ // 使用*监听所有路由
507
+ app .get (' *' , (req , res ) => {
508
+ if (req .query .mode == ' csr' ) {
509
+ console .log (' csr参数开启' )
510
+ return csrRender (res);
511
+ }
512
+ // 省略.....
513
+ ` ` `
514
+ (2)client/index.js,客户端判断是否有window.__store变量,有的话用hydrate,没有的话用render
515
+ ` ` ` js
516
+ if (window .__store ) {
517
+ ReactDom .hydrate (page, document .getElementById (" root" ))
518
+ } else {
519
+ ReactDom .render (page, document .getElementById (" root" ))
520
+ }
521
+ ` ` `
522
+ (3)webpack.client.js,用html-webpack-plugin将bundle注入到HTML模板里面
523
+ ` ` ` js
524
+ plugins: [
525
+ new HtmlWebpackPlugin ({
526
+ filename: ' index.csr.html' ,
527
+ template: ' src/index.csr.html' ,
528
+ inject: true
529
+ })
530
+ ]
531
+ ` ` `
532
+ ### 13、css细节优化
533
+ 组件内部样式渲染,开始css module
534
+ ` ` ` js
535
+ {
536
+ test: / \. css$ / ,
537
+ use: [' style-loader' , {
538
+ loader: ' css-loader' ,
539
+ options: {
540
+ modules: true // 开启css module的支持
541
+ }
542
+ }]
543
+ }
544
+ ` ` `
545
+ 组件内使用模块化引入css的方式
546
+ ` ` ` js
547
+ import React from ' react'
548
+ import styles from ' ./about.css'
549
+ function About (props ) {
550
+ return < div className= {styles .title }> 关于页面< / div>
551
+ }
552
+
553
+ export default About
554
+ ` ` `
555
+ ### 14、puppeteer实现ssr
0 commit comments