Extends

前端集成Vite

Malagu 框架支持前端项目集成 Vite,提供了一种简单的方式来托管前端项目构建产物。

通过手动创建启动文件的方式进行适配,目前仅支持前端项目。

在Vue项目中,.tsx后缀文件中无法使用依赖注入。

Vue

创建项目

terminal
npm create vite@latest malagu-vue-for-vite --template vue-ts
npm i
npm i -D @malagu/core @malagu/vue

适配项目

// src/main.ts
import { createApp } from "vue";
import { App } from "@malagu/vue";
import Root from "./App.vue";

@App(createApp(Root))
export default class {}
// src/module.ts
import { autoBind } from "@malagu/core";
import "./main";

export default autoBind();

添加启动文件

添加src/boot.ts文件,手动创建容器并加载模块:

src/boot.ts
import "reflect-metadata";
import "setimmediate";
import { Container } from "inversify";
import { Application } from "@malagu/core/lib/common/application/application-protocol";
import { ContainerProvider } from "@malagu/core/lib/common/container/container-provider";
import { currentThis } from "@malagu/core/lib/common/utils";
import commonModule from "@malagu/core/lib/common/static-module";
import browserModule from "@malagu/core/lib/browser/static-module";

function bootstrap() {
  currentThis.malaguProps = {
    malagu: {
      hostDomId: "app",
    },
  };
  const container = new Container({ skipBaseClassChecks: true });
  container.load(commonModule, browserModule);
  import("@malagu/vue/lib/browser/module")
    .then((res) => container.load(res.default))
    .then(() => import("./module"))
    .then((res) => container.load(res.default))
    .then(() => {
      ContainerProvider.set(container);
      const application = container.get<Application>(Application);
      application.start().catch((reason) => {
        console.error(`Failed to start the ${application.constructor.name}.`);
        if (reason) {
          console.error(reason);
        }
      });
    });
}

bootstrap();

配置启动

编辑index.html文件,修改入口文件为src/boot.ts

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/boot.ts"></script>
  </body>
</html>

React

创建项目

terminal
npm create vite@latest malagu-react-for-vite --template react-ts
npm i
npm i -D @malagu/core

添加 Shell 和 App 修饰器

添加以下文件:

src/common/constant.ts
export const APP = Symbol("APP");
src/annotation/app.ts
import { Constant } from "@malagu/core";
import { APP } from "../common/constant";

export function App(app: any, rebind: boolean = false): ClassDecorator {
  return (t: any) => {
    Constant(APP, app, rebind)(t);
  };
}
src/shell/index.ts
import { Component, Autowired, Optional } from "@malagu/core";
import { ApplicationShell } from "@malagu/core/lib/browser";
import { APP } from "../common/constant";

@Component({ id: ApplicationShell, rebind: true })
export class Shell implements ApplicationShell {
  @Optional()
  @Autowired(APP)
  protected readonly app: any;

  attach(host: HTMLElement): void {
    this.app(host);
  }
}

适配项目

// src/createApp.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

export function createApp(el: HTMLElement) {
  const root = ReactDOM.createRoot(el);
  root.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  );
}

修改src/main.tsxsrc/main.ts,编辑内容如下:

src/main.ts
import { App } from "./annotation/app";
import { createApp } from "./createApp";
import "./index.css";

@App(createApp)
export default class {}

添加src/module.ts

src/module.ts
import "./shell";
import { autoBind } from "@malagu/core";

import "./main";
export default autoBind();

添加启动文件

添加启动文件src/boot.ts

src/boot.ts
import "reflect-metadata";
import "setimmediate";
import { Container } from "inversify";
import { Application } from "@malagu/core/lib/common/application/application-protocol";
import { ContainerProvider } from "@malagu/core/lib/common/container/container-provider";
import { currentThis } from "@malagu/core/lib/common/utils";
import commonModule from "@malagu/core/lib/common/static-module";
import browserModule from "@malagu/core/lib/browser/static-module";

function bootstrap() {
  currentThis.malaguProps = {
    malagu: {
      hostDomId: "app",
    },
  };
  const container = new Container({ skipBaseClassChecks: true });
  container.load(commonModule, browserModule);
  import("./module")
    .then((res) => container.load(res.default))
    .then(() => {
      ContainerProvider.set(container);
      const application = container.get<Application>(Application);
      application.start().catch((reason) => {
        console.error(`Failed to start the ${application.constructor.name}.`);
        if (reason) {
          console.error(reason);
        }
      });
    });
}

bootstrap();

配置启动

编辑index.html文件,修改入口文件为src/boot.ts

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/boot.ts"></script>
  </body>
</html>

tsx 文件下启用装饰器

默认请况下无法在后缀为.tsx的文件中使用装饰器,需进行以下配置:

安装依赖

terminal
npm i -D @babel/plugin-proposal-decorators

修改配置vite.config.ts

vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
-  plugins: [react()]
+  plugins: [react({
+    babel: {
+      parserOpts: {
+        plugins: ['decorators-legacy']
+      }
+    }
+  })]
})

验证:将index.html中的src/main.ts修改为src/main.tsx尝试运行即可。


Copyright © 2024 Zero (github@groupguanfang) 粤ICP备2023102563号