微前端 micro-app 搭建
微前端 micro-app 搭建
官网:https://zeroing.jd.com/docs.html#/zh-cn/configure
环境:
主应用:vue2,名称:cde-railfore
子应用:vue3,名称:cde-standard,vite 搭建,参考:https://www.cnblogs.com/1285026182YUAN/p/17823873.html
各语言框架 demo 案例:
主应用配置
1. 主应用安装插件
yarn add @micro-zoe/micro-app pnpm add @micro-zoe/micro-app npm i @micro-zoe/micro-app
2. 在应用入口main.js 中引入并启动 micro-app
。
import microApp from '@micro-zoe/micro-app' microApp.start({ destroy: true })
3. 创建页面page1,承载子页面 ,配置子项目的地址路由,参考:https://zeroing.jd.com/docs.html#/zh-cn/configure
<template> <div class="container"> <micro-app name="my-app-page1" url="http://localhost:5173/stand" disableSandbox inline></micro-app> </div> </template>
子应用配置
path
是子应用路由地址。非严格匹配,/login/*
都指向 SubApp
页面。使用 vue-router@4.x
时写法为:'/login/:page*'
。history
路由,Vite
子应用使用 hash
路由,避免一些可能出现的问题。 子应用如果是 Vue3
,在初始化时路由时,createWebHashHistory
不要传入参数,如下:
import { createRouter, createWebHashHistory, createWebHistory, } from "vue-router"; export const routes = [ { path: "/", redirect: "/login", }, { name: "login", path: "/login", component: () => import("@/pages/login.vue"), }, { name: "index", path: "/index", component: () => import("@/pages/index.vue"), }, ]; const router = createRouter({ // scrollBehavior: () => ({ left: 0, top: 0 }), history: createWebHashHistory(), // // history: createWebHistory(), // routes, }); router.beforeEach((to, from, next) => { next(); }); export default router;
import { join } from 'path' import { writeFileSync } from 'fs' function VitePluginMicroApp() { (function () { let basePath = ""; return { name: "vite:micro-app", apply: "build", configResolved(config) { basePath = `${config.base}${config.build.assetsDir}/`; }, writeBundle(options, bundle) { for (const chunkName in bundle) { if (Object.prototype.hasOwnProperty.call(bundle, chunkName)) { const chunk = bundle[chunkName]; if (chunk.fileName && chunk.fileName.endsWith(".js")) { chunk.code = chunk.code.replace( /(from|import\()(\s*['"])(\.\.?\/)/g, (all, $1, $2, $3) => { return all.replace($3, new URL($3, basePath)); } ); const fullPath = join(options.dir, chunk.fileName); writeFileSync(fullPath, chunk.code); } } } }, }; })(); } export default VitePluginMicroApp;
3. 修改配置文件:vite.config.ts
1. 导入插件并配置公共资源基础路径
2. 项目输出到 dist/stand/ 目录
import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; import { resolve } from "path"; import VitePluginMicroApp from "./vite-plugin-micro-app"; export default defineConfig({ base: `${ process.env.NODE_ENV === "production" ? "http://stand.procde.cn" : "" }/stand/`, // base: "/stand/", plugins: [vue(), VitePluginMicroApp()], resolve: { alias: { "@": resolve(__dirname, "./src"), }, extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"], }, server: { port: 5173, }, build: { outDir: "dist/stand/", }, });
if (window.__MICRO_APP_ENVIRONMENT__) {
__webpack_public_path__ = window.__MICRO_APP_PUBLIC_PATH__;
}
5. 修改容器元素 id
当多个vite子应用同时渲染时,必须修改容器元素的id值,确保每个子应用容器元素id的唯一性,否则无法正常渲染。
修改 index.html
中容器元素的 id 值
<body> <div id="my-vite-app"></div> <script type="module" src="/src/main.ts"></script> </body>
6. 使用新的 id 渲染,修改 main.ts
import { createApp } from "vue"; import "./common.scss"; import App from "./App.vue"; import router from "@/router/index"; import { createPinia } from "pinia"; import ElementPlus from "element-plus"; import "element-plus/dist/index.css"; import http from "./utils/request.js"; const app = createApp(App); app.use(router); app.use(createPinia()); app.use(ElementPlus); app.use(http); app.mount("#my-vite-app");
7. 静态资源
图片等静态资源需要使用绝对地址,可以使用 new URL('../assets/logo.png', import.meta.url).href
等方式获取资源的全链接地址。
主应用配置
修改 main.js 中的启动配置
microApp.start({ // shadowDOM: true, // 默认值false destroy: true, plugins: { modules: { // appName即应用的name值 "my-app-page12": [{ loader(code) { if (process.env.NODE_ENV === 'development') { // 这里 basename 需要和子应用vite.config.js中base的配置保持一致 code = code.replace(/(from|import)(\s*['"])(\/stand\/)/g, all => { return all.replace('/stand/', 'http://localhost:5173/stand/') }) } return code } }], 'appname-vite': [ { loader(code) { if (process.env.NODE_ENV === 'development') { // 这里 /basename/ 需要和子应用vite.config.js中base的配置保持一致 code = code.replace(/(from|import)(\s*['"])(\/child\/vite\/)/g, all => { return all.replace('/child/vite/', 'http://localhost:4007/child/vite/') }) } return code } } ], } } })
这些标记字段应与上面配置的一 一对应,否则会报错。
报错现像:
Uncaught TypeError: Failed to resolve module specifier "/stand/node_modules/vite/dist/client/env.mjs". Invalid relative url or base scheme isn't hierarchical.
page1:1 Uncaught TypeError: Failed to resolve module specifier "/stand/src/utils/public-path.js". Invalid relative url or base scheme isn't hierarchical.
配置完成。
引用:https://zeroing.jd.com/docs.html#/zh-cn/configure
引用:https://www.jianshu.com/p/65b81afc0cb5
引用:https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/framework/vite
引用:https://blog.csdn.net/outsider76557/article/details/129687164
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2019-11-13 Beyond Compare 文件对比工具的使用
2019-11-13 SourceTree - 对Git的使用