Skip to content

在 egg.js 中内置一个 vite+vue3 项目 并完美支持开发模式和生产部署

2024-1-17

给 egg.js 开启模板渲染功能

安装插件

shell
$ npm i egg-view-nunjucks --save

启动插件

js
// config/plugin.js
exports.nunjucks = {
  enable: true,
  package: 'egg-view-nunjucks',
};

准备前端代码目录

新建目录app/views,作为前端项目目录。虽然 egg.js 规定了 app/view 是视图目录,但我还是自定义了一个 views 文件夹用来给前端用。

为此需要修改 egg.js 的配置,来让这个目录被 egg.js 识别为视图目录。

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 项目

到另一个目录,使用

shell
$ npm create vue@latest

创建一个新的 vue3 项目,这里我们把 ts、tsx、vue-router、pinia 什么的都选了。

然后把这个项目复制到 app/views/admin 目录下。尝试启动。

shell
$ yarn dev

看到可以正常启动。

让 egg.js 渲染 vue 页面

我们需要在 egg.js 中准备一个路由和一个控制器。

js
// app/router.js
router.get('/admin', controller.home.admin);
js
// 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 文件。

html
<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 的静态目录配置。

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.tsapp/views/admin 中移动到最外层。修改其中的内容。

ts
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,中的 devDependenciesdependencies 中的包合并到最外层的 package.json 中,然后删掉前者。

删掉 app/views/admin/node_modules。在最外层重新安装依赖。

修改最外层的 package.json,修改启动命令。

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

json
{
  ... 其它配置
  "compilerOptions": {
    ... 其它配置
    "types": ["vite/client", "vue"],
    "typeRoots": ["./node_modules/@types", "./src/types"]
  }
}

© thebestxt.cc
辽ICP备16009524号-8
本站所有文章版权所有,转载请注明出处