Note: This practice is not mono-repo. The two projects were forced into a repository and packaged separately for the sake of massive component and logic reuse.

demand

The requirement is to launch a management platform for internal use within a month, including the front desk website and the management background website.

implementation

Since there are many similarities between the two sites, they are placed in a Git repository for speed of development, reuse and maintainability.

The directory structure

Front Desk project: Customer Management background: Admin

|-- project |-- vite.config.admin.ts |-- vite.config.ts |-- app | |-- admin | | |-- App.vue | | |-- index.html | | |-- main.ts | | |-- public | | |-- favicon.ico | |-- customer | |-- App.vue | |-- index.html | |-- main.ts | |-- public | |-- favicon.ico |-- env | |-- admin | | |-- .env | | |-- .env.development | | |-- .env.production | | |-- .env.test | |-- customer | |-- .env | |-- .env.development | |-- .env.production | |-- .env.test |-- src | |-- api | | |-- common.ts  | | |-- admin | | |-- customer | | |-- sys | |-- components | | |-- common | | |-- admin | | |-- customer | |-- style |  | |-- useClass.ts | |-- hooks | |-- layouts | | |-- admin | | |-- content | | |-- customer | | |-- menu | |-- router | | |-- index.ts | | |-- types.ts | | |-- guard | | |-- menus | | | |-- index.ts | | | |-- admin | | | |-- customer | | |-- routes | | |-- common.ts | | |-- admin | | |-- customer | |-- views | |-- admin | |-- customer | |-- sys | |-- error  | |-- login | |-- Login.vueCopy the code

Vite configuration

package.json

The configuration of scripts is as follows: use –config to specify the configuration file. This warehouse foreground project is the default project, directly using the vite scaffolding to generate the default configuration (i.e. Vite.config.ts).

"scripts": {
    "dev": "vite"."test": "vite --mode test"."build": "vite build"."serve": "vite preview"."admin": "vite --config vite.config.admin.ts"."atest": "vite --mode test --config vite.config.admin.ts"."build:admin": "vite build --config vite.config.admin.ts"."serve:admin": "vite preview --config vite.config.admin.ts",},Copy the code

vite.config*.ts

To be compatible with both projects, the vite configuration needs to be modified as follows:

  1. The entrance
  2. Directory of Environment variables
  3. Package output directory
The customer of vite. Config. Ts:
export default ({ mode, command }: ConfigEnv): UserConfig= > {
  const env = loadEnv(mode, pathResolve('env/customer/'))
  return {
    root: pathResolve('app/customer'),//1. The default entry is index.html in the root directory of the project
    base: env.VITE_PUBLIC_PATH,
    envDir: pathResolve('env/customer/'),//2. Modify the entry of environment variables. The default is the env directory under the root directory
    build: {
      outDir: pathResolve('dist'),//3. Modify the package output. The default is the dist directory under root, such as /app/customer/dist
      emptyOutDir: true}}},Copy the code
The admin vite. Config. Admin. Ts:
export default ({ mode, command }: ConfigEnv): UserConfig= > {
  const env = loadEnv(mode, pathResolve('env/admin/'))
  return {
    root: pathResolve('app/admin'),
    base: env.VITE_PUBLIC_PATH,
    envDir: pathResolve('env/admin/'),
    build: {
      outDir: pathResolve('dist-admin'),
      emptyOutDir: true}}},Copy the code

After the above configuration, you can run two projects independently.

Some practical

Distinguish between project

How do you tell which project is running in a project? VITE_GLOBAL_APP_NAME env variables can be customized in the env directory, for example:

# env/admin/.env
VITE_GLOBAL_APP_NAME = ADMIN

# env/customer/.env
VITE_GLOBAL_APP_NAME = CUSTOMER
Copy the code

Importing a routing table conditionally

The routing table of the two items is different, and the conditional import is as follows:

if (import.meta.env.VITE_GLOBAL_APP_NAME === AppNameEnum.CUSTOMER) {
  routesModule = import.meta.globEager('./routes/customer/index.ts');
} else {
  routesModule = import.meta.globEager('./routes/admin/index.ts');
}
Copy the code

The CSS class name

Private class names can be generated as follows:

import { AppNameEnum } from '@/enums/appEnum';

export const prefixMap = {
  [AppNameEnum.CUSTOMER]: 'customer',
  [AppNameEnum.ADMIN]: 'admin'
};

export function useClass(scope: string) {
  const prefix = prefixMap[import.meta.env.VITE_GLOBAL_APP_NAME];
  return `${prefix}-${scope}`;
}
Copy the code

conclusion

This practice has some disadvantages compared to Mono-repo, such as: no independent version management; Two projects share one package.json, resulting in dependency redundancy… Lerna is recommended for large projects to generate and manage mono-repo.