从零开始搭建 Egg React SSR 服务端渲染项目

外包流浪者
• 阅读 5284

从零开始搭建 Egg React SSR 服务端渲染项目

1. 初始化环境

安装 Node LST (>=8) 环境: https://nodejs.org/zh-cn

2. 初始化 egg 项目

https://github.com/eggjs/egg-init/blob/master/README.zh-CN.md

npm i egg-init -g egg-init

  • 选择 Simple egg app boilerplate project 初始化 egg 项目
  • 新建 ${app_root}/app/view 目录(egg view规范目录),并添加 .gitkeep 文件,保证该空目录被 git 提交到仓库
  • 新建 ${app_root}/app/view/layout.html 文件,用于服务端渲染失败后,采用客户端渲染

<!DOCTYPE html> <html lang="en"> <head> <title>Egg + React + Webpack</title> <meta name="keywords"> <meta name="description"> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> </head> <body> <div id="app"></div> </body> </html>

3. 安装依赖

  • 服务端渲染依赖

react 没有内置在 egg-view-react-ssr 里面, 项目需要显示安装依赖。

npm i react react-dom axios egg-view-react-ssr egg-scripts --save

  • 构建开发依赖

npm i egg-bin cross-env easywebpack-cli easywebpack-react egg-webpack egg-webpack-react --save-dev

  • 安装全部依赖

npm install

4. 添加配置

  • 添加 ${app_root}/config/plugin.local.js 配置

exports.webpack = { enable: true, package: 'egg-webpack' }; exports.webpackreact = { enable: true, package: 'egg-webpack-react' };

  • 添加 ${app_root}/config/plugin.js 配置

exports.reactssr = { enable: true, package: 'egg-view-react-ssr' };

  • 添加 ${app_root}/config/config.default.js 配置

'use strict'; const path = require('path'); module.exports = app => { const config = exports = {}; config.keys = '123456'; // 保证构建的静态资源文件能够被访问到 config.static = { prefix: '/public/', dir: path.join(app.baseDir, 'public') }; config.reactssr = { layout: path.join(app.baseDir, 'app/view/layout.html') }; return config; }

  • 添加 easywebpack-cli 配置文件 ${app_root}/webpack.config.js
关于 entry 配置,请务必先看这篇文档:https://www.yuque.com/easy-team/egg-react/config

module.exports = { entry: { 'home/index': 'app/web/page/home/index.jsx' } };

  • 添加 ${app_root}/.babelrc 文件

{ "presets": [ "react", ["env", { "modules": false }] ], "plugins": [ "transform-object-assign", "syntax-dynamic-import", "transform-object-rest-spread", ["import", { "libraryName": "antd", "style": "css" }] ], "env": { "development": { "plugins": [ "react-hot-loader/babel" ] } }, "comments": false }

安装 babel 相关依赖

npm i babel-core babel-loader@7 --save-dev

npm i babel-preset-env babel-plugin-syntax-dynamic-import babel-plugin-transform-object-assign babel-plugin-transform-object-rest-spread --save-dev

  • 添加 ${app_root}/postcss.config.js 文件(非必须)

module.exports = { plugins: [ require('autoprefixer') ] };

安装 autoprefixer 依赖

npm i autoprefixer --save-dev

  • 添加 ${app_root}/.gitignore 配置

.DS_Store .happypack/ node_modules/ npm-debug.log .idea/ dist static public private run *.iml *tmp _site logs .vscode config/manifest.json app/view/* !app/view/layout.html !app/view/.gitkeep package-lock.json

5. 写代码

编写前端 react 代码

  • 新建 ${app_root}/app/web/page/home/index.jsx  页面文件

import React, { Component } from 'react'; import Layout from 'component/layout.jsx'; import List from './componets/list'; import './index.css'; export default class HomeIndex extends Component { componentDidMount() { console.log('----componentDidMount-----'); } render() { return <Layout> <div className="main"> <div className="page-container page-component"> <List list={this.props.message}></List> </div> </div> </Layout>; } }

编写 Node 端代码

通过 egg-view-react-ssr 插件 render 方法实现, 请看服务端渲染前端渲染模式

  • 创建 controller 文件 ${app_root}/app/controller/home.js

module.exports = app => { return class HomeController extends app.Controller { async server() { const { ctx } = this; // home/index.js 对应 app/web/page/home/index.jsx webpack 构建后 JSBundle 文件 await ctx.render('home/index.js', { message: 'egg react server side render' }); } async client() { const { ctx } = this; // renderClient 前端渲染,Node层只做 layout.html和资源依赖组装,渲染交给前端渲染。与服务端渲染的差别你可以通过查看运行后页面源代码即可明白两者之间的差异 await ctx.renderClient('home/index.js', { message: 'egg react client render' }); } }; };

  • 添加路由配置

app.get('/', app.controller.home.server); app.get('/client', app.controller.home.client);

6. 本地运行

npm run dev

npm run dev 做了如下三件事情

  • 首先启动 egg 应用
  • 启动 webpack(egg-webpack) 构建, 文件不落地磁盘,构建的文件都在内存里面(只在本地启动, 发布模式是提前构建好文件到磁盘)
  • 构建会同时启动两个 Webpack 构建服务, 客户端js构建端口9000, 服务端端口9001
  • 构建完成,Egg 应用正式可用,自动打开浏览器

7. 发布模式

  • ${app_root}/package.json 添加命令

{ "scripts": { "dev": "egg-bin dev", "start": "egg-scripts start", "debug": "egg-bin debug", "clean": "easy clean all", "build": "easy build", }, }

  • 命令行运行 webpack 编译

npm run build 或 easy build prod

  1. 启动 Webpack 构建,文件落地磁盘
  2. 服务端构建的文件放到 app/view 目录
  3. 客户端构建的文件放到 public 目录
  4. 生成的 manifest.json 放到 config 目录
  5. 构建的文件都是gitignore的,部署时请注意把这些文件打包进去
  • 部署

启动应用前, 如果是非 egg-scripts  方式启动, 请设置 EGG_SERVER_ENV 环境变量,本地local, 测试环境设置 test, 正式环境设置 prod

npm start

8. 项目和插件

9. 建议

以上详细步骤只是告诉大家 Egg + React + easywebpack 搭建项目整个流程,帮助搭建理清流程和细节。实际使用使用时建议使用 easywebpack-cli 初始化项目或者 clone egg-react-webpack-boilerplate 代码初始化项目。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
可莉 可莉
4年前
18个常用 webpack插件,总会有适合你的!
!(https://oscimg.oschina.net/oscnet/71317da0c57a8e8cf5011c00e302a914609.jpg)来源| https://github.com/Michaellzg/myarticle/blob/master/webpack/Plugin何为插
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
4年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
4年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这