基于 Egg + React + Webpack 服务端渲染开发指南
1. 项目初始化
1.1 通过 easywebpack-cli 脚手架初始化
安装脚手架
npm install easywebpack-cli -g命令行,然后就可以使用easy命令命令行运行
easy init选择 egg + react server side render boilerplate 初始化骨架项目
安装依赖
npm install
1.2 通过骨架项目初始化
git clone https://github.com/easy-team/egg-react-webpack-boilerplate.gitnpm install
初始化的项目提供多页面和SPA(react-router/react-redux)服务端渲染实例,可以直接运行。

1.3 vscode 插件初始化项目
https://marketplace.visualstudio.com/items?itemName=hubcarl.vscode-easy-plugin#overview
2. 项目运行
2.1 本地运行
npm run dev

- 本地开发启动 Webpack 构建, 默认配置文件为项目根目录
webpack.config.js文件。 SSR 需要配置两份 Webpack 配置,所以构建会同时启动两个 Webpack 构建服务。web 表示构建 JSBundle 给前端用,构建后文件目录public, 默认端口 9000; node 表示构建 JSBundle 给 Node 服务端渲染用,构建后文件目录app/view默认端口 9001. - 本地构建是 Webpack 内存构建,文件不落地磁盘,所以
app/view和public在本地开发时,是看不到文件的。 只有发布模式(npm run build)才能在这两个目录中看到构建后的文件内容。
2.2 发布模式
- Webpack 构建文件落地磁盘
npm run build 或 easy build
启动 Webpack 构建,文件落地磁盘
服务端构建的文件放到
app/view目录客户端构建的文件放到
public目录生成的
manifest.json放到config目录构建的文件都是
gitignore的,部署时请注意把这些文件打包进去
- 启动应用
如果非 egg-scripts 方式启动应用, 请设置
EGG_SERVER_ENV环境变量,测试环境设置test, 正式环境设置prod
npm start
- 本地模拟线上启动
npm run buildnpm start
3. 项目构建
easywebpack 通过项目根目录下的
webpack.config.js配置文件构造出 Webpack 实际的配置文件通过 egg-webpack 插件提供本地开发构建和热更新支持。SSR 模式时,egg-webpack 会启动两个 Webpack 构建服务, 客户端jsbundle构建,端口9000, 服务端jsbundle构建端口9001。
// config/config.local.js 本地 npm start 使用const easywebpack = require('easywebpack-react');exports.webpack = {webpackConfigList:easywebpack.getWebpackConfig()};
- webpack.config.js 配置
easywebpack 根据以下配置会自动生成两份 Webpack 配置,一份配置用于 SSR 渲染 Node 渲染使用,生成的文件放到 app/view 目录,也就是 Egg Controller 里的 render('home/home.js') ; 一份配置用于 SSR渲染的浏览器 hydrate 使用,放到 public 目录, 也就是渲染后 HTML 页面的 script <script src='/home/home.js'></script> 。
// ${root}/webpack.config.jsmodule.exports = {entry: {'home/home': 'app/web/page/home/index.jsx'}};
4. 项目规范
React 项目代码放到 app/web 目录,页面入口目录为 page,该目录的 所有 .jsx 文件默认会作为 Webpack 的 entry 构建入口。建议每个页面目录的只保留一个.jsx 文件,jsx关联的组件可以放到widget 或者 component 目录。具体 entry 入口配置与构建流程请阅读:https://www.yuque.com/easy-team/egg-react/config 。
5. 项目开发
支持多页面/单页面服务端渲染, 前端渲染, 静态页面三种方式.
5.1 多页面服务端渲染实现
5.1.1 多页面前端页面实现
在app/web/page 目录下面创建 home 目录 和 home.jsx 文件, Webpack 自动根据 .jsx 文件创建 entry入口, 具体实现请见webpack.config.js
- home.jsx 以组件的方式实现页面逻辑
import React, { Component } from 'react';import Header from 'component/layout/standard/header/header.jsx';import List from 'component/home/list.jsx';import './home.css';export default class Home extends Component {componentDidMount() {console.log('----componentDidMount-----');}render() {return <div><Header></Header><div className="main"><div className="page-container page-component"><List list={this.props.list}></List></div></div></div>;}
5.1.2 通过 egg-view-react-ssr 插件 render 方法实现 Server Side Render
- 创建 controller 文件 home.js
exports.index = function* (ctx) {// home/home.js 是 app/web/page/home/home.js 构建后的服务端页面渲染的 JSBundle 文件。yield ctx.render('home/home.js', Model.getPage(1, 10));};
- 添加路由配置
app.get('/home', app.controller.home.home.index);
5.1.3 通过 egg-view-react-ssr 插件 renderClient 方法实现 Client Side Render
- 在 controller 文件home.js 添加 client 方法
exports.client = function* (ctx) {yield ctx.renderClient('home/home.js', Model.getPage(1, 10));};
- 添加路由配置
app.get('/client', app.controller.home.home.client);
6. 项目部署
正式环境部署,请设置
EGG_SERVER_ENV=prod环境变量, 更多请见运行环境构建的
app/view目录,public目录以及buildConfig.json和manifest.json等文件, 都是gitignore的,部署时请注意把这些文件打包进去。
一. Webpack构建目录
Webpack构建服务端(Node) JSBundle运行文件, 构建的服务端渲染模板文件位置
${app_root}/app/viewWebpack构建浏览器JSBundle运行文件, 构建的前端资源(js/css/image)文件位置
${app_root}/publicWebpack构建的
manifest.json和buildConfig.js文件位置${app_root}/config目录easywebpack-cli 构建配置文件
webpack.config.js放到项目根目录${app_root}/webpack.config.jsReact代码文件
${app_root}/app/web下面, 主要包括asset,component,framework,page,store,view等目录
├── asset // 资源文件│ ├── css│ │ ├── global.css│ │ ├── normalize.css│ │ └── style.css│ ├── images│ │ ├── favicon.ico│ │ ├── loading.gif│ │ └── logo.png├── component // jsx组件│ ├── home│ │ └── list.jsx│ └── layout│ └── standard│ └── header│ ├── header.css│ └── header.jsx├── framework│ └── entry│ ├── app.js│ └── loader.js├── page // 页面目录, jsx结尾的的文件默认作为entry入口│ ├── hello│ │ └── hello.jsx // 页面入口文件, 根据framework/entry/loader.js模板自动构建│ └── home│ ├── home.css│ └── home.jsx└── view└── layout.jsx // layout模板文件, 提供统一html, header, body结构, page下面的jsx文件无需关心
二. 项目结构和基本规范
├── app│ ├── controller│ │ ├── test│ │ │ └── test.js│ ├── extend│ ├── lib│ ├── middleware│ ├── mocks│ ├── proxy│ ├── router.js│ ├── view│ │ ├── home│ │ │ └── home.js // 服务器编译的jsbundle文件│ └── web // 前端工程目录│ ├── asset // 存放公共js,css资源│ ├── framework // 前端公共库和第三方库│ │ └── entry│ │ ├── loader.js // 根据jsx文件自动生成entry入口文件loader│ ├── page // 前端页面和webpack构建目录, 也就是webpack打包配置entryDir│ │ ├── home // 每个页面遵循目录名, js文件名, scss文件名, jsx文件名相同│ │ │ ├── home.scss│ │ │ ├── index.jsx│ └── component // 公共业务组件, 比如loading, toast等, 遵循目录名, js文件名, scss文件名, jsx文件名相同│ ├── loading│ │ ├── loading.scss│ │ └── loading.jsx│ ├── test│ │ ├── test.jsx│ │ └── test.scss│ └── toast│ ├── toast.scss│ └── toast.jsx├── config│ ├── config.default.js│ ├── config.local.js│ ├── config.prod.js│ ├── config.test.js│ └── plugin.js├── doc├── index.js├── webpack.config.js // easywebpack-cli 构建配置├── public // webpack编译目录结构, render文件查找目录│ ├── static│ │ ├── css│ │ │ ├── home│ │ │ │ ├── home.07012d33.css│ │ │ └── test│ │ │ ├── test.4bbb32ce.css│ │ ├── img│ │ │ ├── change_top.4735c57.png│ │ │ └── intro.0e66266.png│ ├── test│ │ └── test.js│ └── vendor.js // 生成的公共打包库
8. 项目和插件
egg-react-webpack-boilerplate基于easywebpack-react和egg-view-react(ssr)插件的工程骨架项目
easywebpack-react Webpack React 构建工程化方案.
easywebpack-cli Webpack 构建工程化脚手架.
egg-view-react-ssr react ssr 解决方案.
egg-webpack 本地开发热更新使用.
egg-webpack-react 本地开发渲染内存读取辅助插件
