在 egg.js 中内置一个 vite+vue3 项目 并完美支持开发模式和生产部署
给 egg.js 开启模板渲染功能
安装插件
$ npm i egg-view-nunjucks --save
启动插件
// config/plugin.js
exports.nunjucks = {
enable: true,
package: 'egg-view-nunjucks',
};
准备前端代码目录
新建目录app/views
,作为前端项目目录。虽然 egg.js 规定了 app/view
是视图目录,但我还是自定义了一个 views
文件夹用来给前端用。
为此需要修改 egg.js 的配置,来让这个目录被 egg.js 识别为视图目录。
// config.default.js
config.view = {
defaultViewEngine: 'nunjucks',
defaultExtension: '.html',
root: [
// path.join(appInfo.baseDir, 'app/view'),
path.join(appInfo.baseDir, 'app/views'),
].join(','),
}
新建 vite + vue3 项目
到另一个目录,使用
$ npm create vue@latest
创建一个新的 vue3 项目,这里我们把 ts、tsx、vue-router、pinia 什么的都选了。
然后把这个项目复制到 app/views/admin
目录下。尝试启动。
$ yarn dev
看到可以正常启动。
让 egg.js 渲染 vue 页面
我们需要在 egg.js 中准备一个路由和一个控制器。
// app/router.js
router.get('/admin', controller.home.admin);
// app/controller/home.js
async admin() {
const env = process.env.NODE_ENV
if (env == 'development') {
await this.ctx.render('admin/index.html', { env })
} else {
await this.ctx.render('admin/dist/index.html', { env })
}
}
在 egg.js 中,可以通过 process.env.NODE_ENV
来获取当前的运行环境是开发还是生产。我们期望的结果是,生产部署之前将前端构建到 app/views/admin/dist
中,在生产环境下 egg.js 直接去渲染 app/views/admin/dist/index.html
。但是在开发环境下,egg.js 只需要渲染 app/views/admin/index.html
即可。
为了达到这个目的,我们还需要修改 app/views/admin/index.html
,通过 egg 模板渲染的方式来选择性的引入对应的 js 文件。
<script>
window.onload = function() {
if (location.href.indexOf('localhost:5173') > -1) {
location.href = 'http://127.0.0.1:7001/admin'
}
}
</script>
<body>
<div id="app"></div>
{% if env == 'development' %}
<script type="module" src="http://localhost:5173/src/main.ts"></script>
{% else %}
<script type="module" src="/src/main.ts"></script>
{% endif %}
</body>
除了需要渲染 index.html,还会有很多构建的产物需要被 egg.js 访问到。这时我们直接修改 egg.js 的静态目录配置。
// config.default.js
config.static = {
prefix: '/',
dir: [
path.join(appInfo.baseDir, 'app/public'),
path.join(appInfo.baseDir, 'app/views/admin/dist'),
path.join(appInfo.baseDir, 'app/views/admin/public'),
path.join(appInfo.baseDir, 'app/views/admin')
],
dynamic: true,
preload: false,
maxAge: 31536000,
}
移动 vite.config.ts
将 vite.config.ts
从 app/views/admin
中移动到最外层。修改其中的内容。
export default defineConfig({
plugins: [
vue(),
vueJsx(),
],
resolve: {
// 需要修改 @ 的指向
alias: {
'@': fileURLToPath(new URL('./app/views/admin/src', import.meta.url))
}
},
// 从这开始是添加的内容
build: {
manifest: true
},
root: `${process.cwd()}/app/views/admin`,
})
修改包管理配置和启动命令
将 app/views/admin/package.json
,中的 devDependencies
和 dependencies
中的包合并到最外层的 package.json
中,然后删掉前者。
删掉 app/views/admin/node_modules
。在最外层重新安装依赖。
修改最外层的 package.json
,修改启动命令。
"scripts": {
"start": "egg-scripts start --daemon --title=egg-server-hikari3",
"stop": "egg-scripts stop --title=egg-server-hikari3",
"dev:api": "egg-bin dev",
"dev:admin": "vite",
"preview:admin": "cd app/views/admin && yarn preview",
"test": "npm run lint -- --fix && npm run test:local",
"test:local": "egg-bin test",
"cov": "egg-bin cov",
"lint": "eslint .",
"ci": "npm run lint && npm run cov"
},
这样在项目最外层也可以启动项目和执行构建了。
修改 tsconfig
全部配置完后我们发现 vscode 有一些报错,可能是因为 vue 的一些类型没有正确导入。我们需要修改 tsconfig.json
。
{
... 其它配置
"compilerOptions": {
... 其它配置
"types": ["vite/client", "vue"],
"typeRoots": ["./node_modules/@types", "./src/types"]
}
}