An overview of the

The previous front-end project structure adopts node layer + front-end interface to construct and deploy, and the solution is to realize the node layer service with eggJS interface and WebPack + VUe2, which has some mature implementation methods

With the release of Vue version 3.0 and the release of Vite tools, a solution was needed to realize the overall solution built with Vite + vue3 as the front-end of EggJS as a service

Since Vite is superior to WebPack in terms of service startup speed, build speed, package size, etc., this solution is definitely better than the previous solution

The project is developed in typescript and can be directly implemented

plan

The principle of

Start an EggJS service at the development stage, and start the Vite service when HTTP access is available. Accessing egg pages at the development stage is equivalent to using a proxy to access the Vite service for HTML content. After transformation, the resource reference path in the page is replaced with the path of the vite service request address to access the resource. Finally, the HTML is output by the Egg service view engine

The purpose of this is to edit the entry HTML of Vite uniformly during development. After the construction of the project, template resources and static resources are generated for the access of the eggJS online environment service, and the generated HTML is directly output by the online environment

Directories and dependency packages

The main directory structure and description are as follows:

An egg - vite - vue3 ├ ─ app # eggjs implementation │ ├ ─ controller │ │ └ ─ home. Ts │ ├ ─ public │ └ ─ service │ └ ─ Test. The ts ├ ─ config # eggjs │ ├─ ├─ exercises # ├─ build.sh ├─ │ ├─ exercises # ├─ build.sh ├─ │ ├─ exercises # ├─ build.sh ├─ │ ├─ exercises # ├─ build.sh ├─ │ ├─ exercises # │ ├─ ├─ all exercises, ├─ all exercises, all exercises, all exercises, all exercises Service │ └ ─ Test. Test. Ts ├ ─ README. Md ├ ─ appveyor. Yml ├ ─ index. The HTML page # front entrance ├ ─ package. The json ├ ─ postcss. Config. Js ├ ─ # Tailwind.config.js ├─ tsconfig.json # TsConfig ├─ tsconfig.prod.json # TsConfig ├─ vite ├ ─ yarn.lockCopy the code

The following package dependencies are referenced in the project:

{
  "dependencies": {
    "egg": "^ 2.6.1." "."egg-decorator-router": "^ 1.0.7"."egg-scripts": ^ "server"."egg-view-nunjucks": "^ 2.3.0." "."egg-vite-plugin": "^" 1.0.1
  },
  "devDependencies": {
    "@types/egg": "^ 1.5.0." "."@types/mocha": "^ 8.2.1." "."@types/node": "^ 14.14.31"."@types/supertest": "^ 2.0.0." "."@vitejs/plugin-legacy": "^ 1.3.1." "."@vitejs/plugin-vue": "^ 1.1.5." "."@vue/compiler-sfc": "^ 3.0.7"."autod": "^ 3.0.1." "."autod-egg": "^ 1.1.0." "."autoprefixer": "^ 10.2.4"."egg-bin": "^ 4.11.0"."egg-ci": "^ 1.8.0 comes with"."egg-mock": "^ 4.0.1." "."eslint": "^ 7.21.0"."eslint-config-egg": "^ 9.0.0"."mkdirp": "^" 1.0.4."mocha": "5.2.0"."tslib": "^ 2.1.0." "."typescript": "^ 4.2.2." "."vite": "^ 2.0.4"."vue": "^ 3.0.7"}}Copy the code

Egg-view-nunjucks is a dependency and must be installed

Vue3 and vuE-related @vitejs/plugin-vue @vue/ Compiler-SFC will also be installed. @vitejs/ plugin-Legacy is designed to build pages compatible with browsers that do not support Module Script

The definition in vite.config.ts

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import legacy from '@vitejs/plugin-legacy';

export default defineConfig({
  build: {
    manifest: true,},plugins: [vue(), legacy({ targets: ['defaults'.'not IE 11']})]});Copy the code

The eggJS plug-in and configuration

Egg-viet-plugin this package implements control over the Vite service and view output, and was developed separately to implement the eggJS plug-in for this solution

In config/plugin.ts, perform the following steps

import { EggPlugin } from 'egg';

const plugin: EggPlugin = {
  // static: true,
  nunjucks: {
    enable: true.package: 'egg-view-nunjucks',},vitePlugin: {
    / / to enable an egg - vite - the plugin
    enable: true.package: 'egg-vite-plugin',},decoratorRouter: {
    enable: true.package: 'egg-decorator-router',}};export default plugin;
Copy the code

The startup of the Vite service is actually the middleware implementation of EggJS. The vite service needs to be enabled only in the development environment, as defined below in config/config.local.ts

import { EggAppConfig, PowerPartial } from 'egg';

export default() = > {const config: PowerPartial<EggAppConfig> = {};

  config.vitePlugin = {
    devServer: true};return config;
};
Copy the code

The devServer property in vitePlugin represents enabling vite service middleware

The output of the view is still using the Nunjucks template and also uses static resources, defined in config/config.default.ts

import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';
import * as path from 'path';

export default (appInfo: EggAppInfo) => {
  const config = {} as PowerPartial<EggAppConfig>;

  config.keys = appInfo.name + '_1614221169780_4319';

  config.middleware = [];

  const bizConfig = {
    sourceUrl: `https://github.com/eggjs/examples/tree/master/${appInfo.name}`};// View output definition
  config.view = {
    defaultViewEngine: 'nunjucks'.root: path.join(appInfo.baseDir, 'dist'), //
    mapping: {
      '.html': 'nunjucks',}};Static resource definition
  config.static = {
    prefix: '/assets/'.//
    dir: [
      path.join(appInfo.baseDir, 'app/public'),
      path.join(appInfo.baseDir, 'dist/assets')]}; config.security = {csrf: { enable: false}};return{... config, ... bizConfig, }; };Copy the code

In the development stage, the interface output is obtained through proxy. After the release, the interface output is realized through the plug-in of EggJS. Config. view and config.static are configured to set resource path correlation

The root path of the view in the setup is dist. The results of the Vite build are output to Dist. Eggjs uses the HTML page in Dist as the output template

config.view = {
  defaultViewEngine: 'nunjucks'.root: path.join(appInfo.baseDir, 'dist'), //
  mapping: {
    '.html': 'nunjucks',}};Copy the code

The static resources are prefixed with /assets/. The default static resources output by Vite are assets. You also need to fetch resources from dist/assets

config.static = {
  prefix: '/assets/'.//
  dir: [
    path.join(appInfo.baseDir, 'app/public'),
    path.join(appInfo.baseDir, 'dist/assets')]};Copy the code

The development of

Define a Controller output eggJS view that uses the egg-decorator-Router implementation to automatically generate the router by declaring features like a normal back-end service

The controller uses the extended method await ctx.viet.render (‘index.html’) to output the view

import { Controller } from 'egg';
import { Route, HttpGet, HttpPost } from 'egg-decorator-router';

@Route(a)export default class HomeController extends Controller {
  @HttpGet('/')
  @HttpGet(The '*')
  public async index() {
    const { ctx } = this;

    const renderData: any = {
      serverText: 'title text'};await ctx.vite.render('index.html', renderData);
  }

  @HttpPost('/api')
  public apiPost() {
    const { ctx } = this; ctx.body = ctx.request.body; }}Copy the code

The vite. Render method determines whether ViteDevServer is enabled and obtains the service address. In the development environment, the service address of Vite is automatically obtained from the started service instance without additional configuration, replacing the reference path of resources in the template page, and directly outputs the template view online

You can also define any vite service address in viet.config. ts, which is automatically recognized

HTML = http://ip :[port]/index.html = http://ip :[port]/index.html = http://ip :[port]/index.html

release

Ts of compilation

Eggjs runs on JS files, and because it is developed on typescript, compilation is performed to generate JS files at release time

Implementation of TS file compilation

ets && tsc -p tsconfig.prod.json
Copy the code

Tsconfig. json complete definition:

{
  "extends": "./tsconfig.json"."compilerOptions": {
    "outDir": "./output"
  },
  "exclude": [
    "app/public"."app/views"."node_modules*"."src"."vite.config.ts"]}Copy the code

Tsconfig.prod. json is defined for compilation. In addition to the configuration of references to./tsconfig.json, we also exclude the directory related to the front-end page, which is implemented by Vite

The TSC command by default puts the compilation result of ts files in the same directory as the ts file, using the outDir attribute to put the compilation result in a different location

Front-end construction

Use vite build-c vite.config.ts to build the front end and get the dist folder

Directory integration

To integrate the results of the eggJS compilation with the static resources built by Vite, scripts/build.sh are implemented directly with a script that generates the output directory

The output ├ ─ app │ ├ ─ controller │ │ └ ─ home. Js │ └ ─ service │ └ ─ Test. The js ├ ─ config │ ├ ─ config. The default. Js │ ├ ─ The config. Local. Js │ ├ ─ config. Prod. Js │ └ ─ plugin. Js ├ ─ dist │ ├ ─ assets │ │ ├ ─ the About - legacy. C3f1bf9e. Js │ │ ├ ─ .b856361a.js │ │ ├─ Homes.09CDf4F7.js │ │ ├─ Element - ICONS.a30F5b3b Element - ICONS.ab40A589. Woff │ │ ├─ ├─ Index.868 f201c. CSS │ │ ├─ Index.e5001C38 Polyfills - legacy. 3 e7a3c9b. Js │ │ ├ ─ vendor - legacy. 675 af630. Js │ │ └ ─ vendor. 4 c85d832. Js │ ├ ─ index. The HTML │ └ ─ The manifest. Json └ ─ package. JsonCopy the code

In package.json eggScriptsConfig sets the properties associated with eggJS execution

{
  "eggScriptsConfig": {
    "daemon": true."env": "prod"."title": "egg-vite-vue3"}}Copy the code

To start the project, run egg-scripts start. /output directly in the root directory

You can also execute NPM install — production on the output directory separately to install only the packages needed to run, and then build a Docker image to run

About vite + vue2

If you are still using vue2 please refer to github.com/fyl080801/e…

Install dependencies

npm i
Copy the code

Start the project

npm run dev
Copy the code

Build the front

npm run dist
Copy the code

Online running and stopping

npm run start
Copy the code
npm run stop
Copy the code

Some resource reference issues about the development environment

During development and debugging, if vite service resources are referenced through the path, resource loading will be abnormal because the eggJS service is accessed and there is no corresponding static resource under this service

Such as http://127.0.0.1:7001/node_modules/element-ui/lib/theme-chalk/fonts/element-icons.woff, in fact, in resources http://127.0.0.1:3000/node_modules/element-ui/lib/theme-chalk/fonts/element-icons.woff, That is, the vite service http://127.0.0.1:3000 provides resources

The solution is to set up egg-vite-plugin to implement proxy forwarding of paths

Add the following parameters to the config/config.local.ts file

config.vitePlugin = {
  devServer: true.targets: [
    /^(\/node_modules)/g.'/assets/(.*)'],}Copy the code

Targets is an array. Requests that define matching path rules are automatically forwarded to the Vite service. Regular expressions and strings are supported

This is only necessary in the development environment, not the online environment

A link to the

The name of the instructions Github Gitee
egg-vite-vue3 Complete solution implementation Github.com/fyl080801/e… Gitee.com/fyl080801/e…
egg-vite-plugin Eggjs integrates with the Vite service plug-in Github.com/fyl080801/e… Gitee.com/fyl080801/e…
egg-decorator-router The eggJS decorator routing plug-in Github.com/fyl080801/e… Gitee.com/fyl080801/e…