之前写过一篇类似文章,本篇为重写
本篇教程讲 eggjs
怎么配合 umi
开启 ssr
(服务端渲染)。
一、 创建 eggjs
工程
1 2 3 4 5 6 7 8 9
| mkdir ssr-with-eggjs && cd ssr-with-eggjs
npm init egg --type=simple
yarn
yarn dev open http://127.0.0.1:7001/
|
二、创建 umi
工程
1 2 3 4 5 6 7 8 9
| mkdir app/web && cd app/web
yarn create @umijs/umi-app
yarn
yarn start open http://127.0.0.1:8000
|
三、修改 umi
工程配置
.umirc.ts
文件新增如下配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { defineConfig } from 'umi';
export default defineConfig({ ... ssr: { devServerRender: false, }, hash: true, outputPath: '../public', manifest: { fileName: '../../config/manifest.json', publicPath: '', } ... });
|
修改项目根目录 .gitignore
文件,添加如下内容
1 2 3
| app/public config/manifest.json
|
启动 umi
项目看有没问题
四、修改 eggjs
项目
安装 egg-view-assets
和 egg-view-nunjucks
1
| yarn add egg-view-assets egg-view-nunjucks
|
config/plugin.js
中开启 egg-view-assets
和 egg-view-nunjucks
插件
1 2 3 4 5 6 7 8 9 10 11 12 13
| 'use strict';
module.exports = { assets: { enable: true, package: 'egg-view-assets', }, nunjucks: { enable: true, package: 'egg-view-nunjucks', }, };
|
修改 config/config.default.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
'use strict'; const path = require('path');
module.exports = (appInfo, appConfig = {}) => { const assetsDir = (appConfig.assets && appConfig.assets.dir) || 'app/web';
const config = (exports = {});
config.keys = appInfo.name + '_1636442650677_1894';
config.middleware = [];
const userConfig = { static: { gzip: true, }, assets: { publicPath: '/public', devServer: { command: 'app/web/node_modules/umi/bin/umi.js dev', env: { APP_ROOT: path.join(appInfo.baseDir, assetsDir), PORT: '{port}', BROWSER: 'none', ESLINT: 'none', SOCKET_SERVER: 'http://127.0.0.1:{port}', PUBLIC_PATH: 'http://127.0.0.1:{port}', }, }, }, view: { mapping: { '.html': 'nunjucks', }, defaultViewEngine: 'nunjucks', }, };
return { ...config, ...userConfig, }; };
|
创建 config/config.local.js
文件,添加如下配置
1 2 3 4 5 6 7 8 9 10 11 12 13
| 'use strict';
module.exports = (appInfo) => { const config = (exports = {}); config.assets = { devServer: { debug: true, autoPort: true, }, dynamicLocalIP: false, }; return config; };
|
创建 app/view/index.html
,添加如下内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <!doctype html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <title></title> {{ helper.assets.getStyle('umi.css') | safe }} </head> <body>
<div id="root"></div>
<script> window.routerBase = '/'; window.resourceBaseUrl = '{{ helper.assets.resourceBase }}'; </script> {{ helper.assets.getScript('umi.js') | safe }} </body> </html>
|
修改 router.js
文件
1 2 3 4 5
| module.exports = app => { const { router, controller } = app; router.get('*', controller.home.index); };
|
添加 mime
修改 app/controller/home.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| 'use strict';
const Controller = require('egg').Controller; const mime = require('mime');
class HomeController extends Controller { constructor(ctx) { super(ctx); this.serverRender = require('../public/umi.server'); } async index() { const { ctx } = this;
const htmlTemplate = await ctx.view.render('index.html');
const { html, error } = await this.serverRender({ path: ctx.url, getInitialPropsCtx: {}, htmlTemplate, });
if (error) { ctx.logger.error( '[SSR ERROR] 渲染报错,切换至客户端渲染', error, ctx.url ); } ctx.type = mime.getType(ctx.url); ctx.status = 200; ctx.body = html; } }
module.exports = HomeController;
|
创建 app/web/.env
,添加如下环境变量
eggjs
项目安装 cross-env
在根目录的 package.json
添加如下配置
1 2 3 4 5
| { "scripts": { "build": "cross-env APP_ROOT=app/web app/web/node_modules/umi/bin/umi.js build", } }
|
至此,项目配置基本已经完成,下面介绍怎么启动开发环境和生产环境
开发环境
生产环境
启动
1 2 3 4
| // 构建 yarn build // 启动 yarn start
|
关闭
总结
以上是根据 umi
官方 srr + egg 总结出来的主要步骤。不过要注意,目前 umi
工程配置 不能开启 dynamicImport
,不然服务端渲染时会出错。
项目地址
续
按上面配置完后,发现 yarn dev
启动后会报 too many open files
错误,看了下报错日志,是 eggjs
把 web
项目的 node_modules
文件夹也加入了 watcher,导致大量文件句柄,目前解决方法是将 web 项目依赖都移到项目根目录。以下是解决步骤
1、 将 app/web/package.json
中依赖都移到根目录的 package.json
现在根目录 package.json
新增依赖如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| { "dependencies": { "@ant-design/pro-layout": "^6.5.0", "react": "17.x", "react-dom": "17.x", "umi": "^3.5.20" }, "devDependencies": { "@types/react": "^17.0.0", "@types/react-dom": "^17.0.0", "@umijs/preset-react": "1.x", "@umijs/test": "^3.5.20", "lint-staged": "^10.0.7", "prettier": "^2.2.0", "typescript": "^4.1.2", "yorkie": "^2.0.0" } }
|
2、 将 app/web/package.json
中脚本移到根目录的 package.json
,根目录 package.json
新增如下脚本:
1 2 3 4 5 6 7 8 9
| { "scripts": { "build": "cross-env APP_ROOT=app/web umi build", "start-web": "cross-env APP_ROOT=app/web umi dev", "postinstall-web": "cross-env APP_ROOT=app/web umi generate tmp", "test-web": "cross-env APP_ROOT=app/web umi-test", "test:coverage-web": "cross-env APP_ROOT=app/web umi-test --coverage" } }
|
现在可以把 app/web/package.json
文件删了
3、 修改 config/config.default.json
1 2 3 4 5 6
| assets: { devServer: { command: 'umi dev', }, },
|
4、 重新安装依赖
以上就是相关解决方案,现在 yarn dev
启动开发环境,就不会报错了。本来想找找有什么配置,能让 eggjs
直接忽略 node_modules
,不过没找到。