微前端

简介: 微前端,听这名字感觉很超前,其实已经有很多公司都已经用上了该技术,例如我的项目组也用上了,跟后端的微服务很类似,用作解耦。现在的网站开发日渐复杂,通常会有很多独立的模块组成,分成不同的业务组,在之前用的是iframe 进行嵌套。

image.png


什么是微前端


微前端,听这名字感觉很超前,其实已经有很多公司都已经用上了该技术,例如我的项目组也用上了,跟后端的微服务很类似,用作解耦。现在的网站开发日渐复杂,通常会有很多独立的模块组成,分成不同的业务组,在之前用的是iframe 进行嵌套。随着技术的发展现在出现了微前端的概念,目前微前端框架有很多,如single-spaqiankun(阿里)  Micro App(京东)  wujie(腾讯)擎天(vivo)


无界官网


micro-app官网


乾坤官网


在微前端的架构下,需要一个主应用,也可以叫基座应用,其次每一个独立的模块都可以叫做子应用,子应用和主应用不受框架的限制,可以用任何框架任何技术。


举个栗子


image.png



在这张图我们可以把菜单和头部看做是一个主应用,然后菜单中的每一个模块都可以看做一个子应用(也就是每一个单独的项目),这样就可以就行解耦,并且应用之间是可以进行通讯的。


这一章我们主要体验一下micro-app支持一下自家产品。他的原理也很简单,就是把子应用做成一个webComponents 进行沙箱隔离,应用之间的通讯用的是CustomEvent


开整


在开整之前得吐槽一下,在github的issues提的很多问题,得不到及时回复,平时忙也能理解,如果使用vite将变的比较复杂,做好准备。


tips:当子应用是vite应用时需要做特别的适配,适配vite的代价是巨大的,我们必须关闭沙箱功能,因为沙箱在module script下不支持,这导致大部分功能失效,包括:环境变量、样式隔离、元素隔离、资源路径补全、baseroute 等。


1.框架我这边主子应用使用vite+vue3,大家可以随意选择框架。

2.目录结构mfe->主应用,web放子应用,子应用可以有多个第一个是main


image.png

image.png


3.主子应用安装依赖npm install 然后 启动主应用,和子应用使用 npm run dev。启动完成之后我这边主应用端口是5173,子应用是5174,当然也可以自己配置不要冲突就行。


4.主应用安装micro-app


npm install  @micro-zoe/micro-app


5.主应用在views新建一个文件如views/page.vue子应用修改vite.config.ts主子应用不要搞错, 子应用的vite.config.ts 增加代码


tips:如果是production记得换成服务器的地址,如果是本地增加一个自定义前缀随便写我这儿写的basename


export default defineConfig({
    base: `${process.env.NODE_ENV === 'production' ? 'http://xxxxx.com' : ''}/basename/`,
    plugins:[vue()]
})


6.在刚才主应用新建的page.vue 加入以下代码


<template>
    <div>
        <h1>子应用</h1>
        <micro-app disable-sandbox disable-scopecss name='main' :url='url'></micro-app>
    </div>
</template>
<script lang="ts" setup>
import { ref, reactive } from "vue"
let url = ref('')
if (import.meta.env.MODE == "development") {
    url.value = "http://localhost:5174/basename"
} else {
    url.value = "http://xxxxxxxx/basename"
}
</script>
<style lang="less" scoped>
</style>


解释一下 micro-app 是个自定义组件可以直接用,如果报错可以配置以下代码忽略警告


image.png


主应用的vite.config.ts 修改


vue({
    template: {
        compilerOptions: {
            isCustomElement: tag => /^micro-app/.test(tag)
        }
    }
})


image.png


其次是必须要设置 disable-scopecss 这个属性取消沙箱,不然打包之后会有乱码,也就是必须得放弃沙箱。


url 就是子应用的地址,本地的地址和服务器地址做个切换。


7.主应用配置路由 主应用使用history模式,子应用换成hash模式createWebHashHistory


import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/vue3:page*', //自定义地址
      component: ()=> import('@/views/page.vue') //刚才主应用创建的page.vue
    },
  ]
})
export default router


8.主应用加载子应用 main.ts


import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import microApp from '@micro-zoe/micro-app'
const app = createApp(App)
app.use(router)
app.mount('#mfe')
microApp.start({
    plugins:{
        modules:{
            main: [{
                loader(code) {
                  if (import.meta.env.MODE === 'development') {
                    // 这里 basename 需要和子应用vite.config.js中base的配置保持一致
                    code = code.replace(/(from|import)(\s*['"])(\/basename\/)/g, all => {
                      return all.replace('/basename/', 'http://localhost:5174/basename/')
                    })
                  }
                  return code
                }
              }]
        }
    }
})


固定写法,有额外的子应用只需要改一下code.replace正则和all.replace第一个参数,以及第二个参数对应的地址就好,其他不用动


tips:注意modules下面的名字需要跟micro-app 的name对应 我这儿都是main


tips:主子应用不能使用同一个#App名字 我这儿主应用的名称换成了mfe,app.mount('#mfe')


<!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>微前端</title>
  </head>
  <body>
     <!--名字要变-->
    <div id="mfe"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>


访问主应用你会发现子应用已经出来了


tips:注意我得路由写的是/vue3


image.png


坑来了:你的图片如果加载不出来,加载静态资源的方式变了


//js获取
const logo = new URL('./assets/logo.png',import.meta.url).href
//template使用
 <img alt="Vue logo" class="logo" :src="logo" width="125" height="125" />


如果还出不来,我也遇到了 需要把vite的版本降级为3.0.0方可好使


上线


打包主应用npm run build 记得换成服务器地址之前提到的


子应用需要修改vite.config.ts


import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import {join} from 'path'
import {writeFileSync} from 'fs'
// https://vitejs.dev/config/
export default defineConfig({
  base: `${process.env.NODE_ENV === 'production' ? '上线地址' : ''}/basename/`,
  plugins: [vue(), vueJsx(),(function () {
    let basePath = ''
    return {
      name: "vite:micro-app",
      apply: 'build',
      configResolved(config:any) {
        basePath = `${config.base}${config.build.assetsDir}/`
      },
      writeBundle (options:any, bundle:any) {
        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:any, $1:any, $2:any, $3:any) => {
                return all.replace($3, new URL($3, basePath))
              })
              const fullPath = join(options.dir, chunk.fileName)
              writeFileSync(fullPath, chunk.code)
            }
          }
        }
      },
    }
  })() as any],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  build:{
    outDir:"../basename"
  }
})


解释一下 这是micro-app写的一个vite插件主要是子应用支持微前端做的直接贴进去就行了


outDir打包之后我输出到上层目录这个随意


子应用然后进行打包 npm run build


服务器我用的是宝塔方便


目录结构 主应用放到最外面,子应用直接把文件夹拖进去我得是basename


image.png


修改nginx代理


image.png


location /{
     add_header Access-Control-Allow-Origin *;
      if ( $request_uri ~* ^.+.(js|css|jpg|png|gif|tif|dpg|jpeg|eot|svg|ttf|woff|json|mp4|rmvb|rm|wmv|avi|3gp)$ ){
      add_header Cache-Control max-age=7776000;
      add_header Access-Control-Allow-Origin *;
    }
     try_files $uri $uri/ /index.html;
    }
    location /basename {
      add_header Access-Control-Allow-Origin *;
    if ( $request_uri ~* ^.+.(js|css|jpg|png|gif|tif|dpg|jpeg|eot|svg|ttf|woff|json|mp4|rmvb|rm|wmv|avi|3gp)$ ){
      add_header Cache-Control max-age=7776000;
      add_header Access-Control-Allow-Origin *;
     }
      try_files $uri $uri/ /basename/index.html;
     }


上线预览


image.png

目录
相关文章
|
7月前
|
前端开发 UED
微前端实战
微前端实战
66 2
|
3月前
|
前端开发 JavaScript 架构师
了解微前端,深入前端架构的前世今生
该文章深入探讨了微前端架构的起源、发展及其解决的问题,并详细讲解了微前端在现代Web应用中的实现方式与优势,帮助读者理解微前端的设计理念和技术细节。
|
7月前
|
前端开发 JavaScript 开发者
探索前端领域中的微前端架构
随着前端应用的规模不断增长,传统的单体应用架构已经无法满足需求。本文将深入探讨微前端架构的概念、优势以及实现方式,为前端开发者提供新的思路和解决方案。
|
7月前
|
监控 前端开发 Serverless
微前端解决方案
微前端解决方案
100 1
|
前端开发 微服务
微前端应用
微前端(Micro-Frontends)是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。
|
前端开发 数据可视化 JavaScript
为什么要用微前端?如何使用乾坤微前端?
为什么要用微前端?如何使用乾坤微前端?
为什么要用微前端?如何使用乾坤微前端?
|
存储 缓存 前端开发
理解微前端
我们就从微前端解决了哪些现存前端问题,并在解决这些问题的过程中做出了哪些取舍和权衡。
146 0
|
存储 前端开发 JavaScript
2022 你还不会微前端吗 (下) — 揭秘微前端核心原理(一)
2022 你还不会微前端吗 (下) — 揭秘微前端核心原理
330 0
|
前端开发 JavaScript 数据格式
2022 你还不会微前端吗 (下) — 揭秘微前端核心原理(二)
2022 你还不会微前端吗 (下) — 揭秘微前端核心原理
170 0
|
存储 前端开发 JavaScript
2022 你还不会微前端吗 (下) — 揭秘微前端核心原理(三)
2022 你还不会微前端吗 (下) — 揭秘微前端核心原理
139 0