从零开始写一个微前端框架-渲染篇

本文从零开始介绍如何构建一个微前端框架,重点讲解渲染部分。内容涵盖创建容器、引入simple-micro-app、资源加载与渲染、微应用实例创建、卸载应用等步骤,通过实例演示了微前端的基本功能,帮助读者理解微前端框架的工作原理。
摘要由CSDN通过智能技术生成

前言

自从微前端框架micro-app开源后,很多小伙伴都非常感兴趣,问我是如何实现的,但这并不是几句话可以说明白的。为了讲清楚其中的原理,我会从零开始实现一个简易的微前端框架,它的核心功能包括:渲染、JS沙箱、样式隔离、数据通信。由于内容太多,会根据功能分成四篇文章进行讲解,这是系列文章的第一篇:渲染篇。

通过这些文章,你可以了解微前端框架的具体原理和实现方式,这在你以后使用微前端或者自己写一套微前端框架时会有很大的帮助。如果这篇文章对你有帮助,欢迎点赞留言。

相关推荐

micro-app源码地址:https://github.com/micro-zoe/micro-app

整体架构

和micro-app一样,我们的简易微前端框架设计思路是像使用iframe一样简单,而又可以避免iframe存在的问题,其使用方式如下:

最终效果也有点类似,整个微前端应用都被封装在自定义标签micro-app中,渲染后效果如下图:

所以我们整体架构思路为:CustomElement + HTMLEntry

HTMLEntry就是以html文件作为入口地址进行渲染,入上图中的http://localhost:3000/就是一个html地址。

概念图:

前置工作

在正式开始之前,我们需要搭建一个开发环境,创建一个代码仓库simple-micro-app

目录结构

代码仓库主要分为src主目录和examples案例目录,vue2为基座应用,react17为子应用,两个项目都是使用官方脚手架创建的,构建工具使用rollup。

两个应用页面分别如下图:

基座应用 – vue2

子应用 – react17

在vue2项目中,配置resolve.alias,将simple-micro-app指向src目录的index.js。

// vue.config.js
...
chainWebpack: config => {
   
    config.resolve.alias
      .set("simple-micro-app", path.join(__dirname, '../../src/index.js'))
  },

在react17的webpack-dev-server中配置静态资源支持跨域访问。

// config/webpackDevServer.config.js
...
headers: {
   
  'Access-Control-Allow-Origin': '*',
},

正式开始

为了讲的更加明白,我们不会直接贴出已经完成的代码,而是从无到有,一步步实现整个过程,这样才能更加清晰,容易理解。

创建容器

微前端的渲染是将子应用的js、css等静态资源加载到基座应用中执行,所以基座应用和子应用本质是同一个页面。这不同于iframe,iframe则是创建一个新的窗口,由于每次加载都要初始化整个窗口信息,所以iframe的性能不高。

如同每个前端框架在渲染时都要指定一个根元素,微前端渲染时也需要指定一个根元素作为容器,这个根元素可以是一个div或其它元素。

这里我们使用的是通过customElements创建的自定义元素,因为它不仅提供一个元素容器,还自带了生命周期函数,我们可以在这些钩子函数中进行加载渲染等操作,从而简化步骤。

// /src/element.js

// 自定义元素
class MyElement extends HTMLElement {
   
  // 声明需要监听的属性名,只有这些属性变化时才会触发attributeChangedCallback
  static get observedAttributes () {
   
    return ['name', 'url']
  }

  constructor() {
   
    super();
  }

  connectedCallback() {
   
    // 元素被插入到DOM时执行,此时去加载子应用的静态资源并渲染
    console.log('micro-app is connected')
  }

  disconnectedCallback () {
   
    // 元素从DOM中删除时执行,此时进行一些卸载操作
    console.log('micro-app has disconnected')
  }

  attributeChangedCallback (attr, oldVal, newVal) {
   
    // 元素属性发生变化时执行,可以获取name、url等属性的值
    console.log(`attribute ${
     attrName}: ${
     newVal}`)
  }
}

/**
 * 注册元素
 * 注册后,就可以像普通元素一样使用micro-app,当micro-app元素被插入或删除DOM时即可触发相应的生命周期函数。
 */
window.customElements.define('micro-app', MyElement)

micro-app元素可能存在重复定义的情况,所以我们加一层判断,并放入函数中。

// /src/element.js

export function defineElement () {
   
  // 如果已经定义过,则忽略
  if (!window.customElements.get('micro-app')) {
   
    window.customElements.define('micro-app', MyElement)
  }
}

/src/index.js中定义默认对象SimpleMicroApp,引入并执行defineElement函数。

// /src/index.js

import {
    defineElement } from './element'

const SimpleMicroApp = {
   
  start () {
   
    defineElement()
  }
}

export default SimpleMicroApp

引入simple-micro-app

在vue2项目的main.js中引入simple-micro-app,执行start函数进行初始化。

// vue2/src/main.js

import SimpleMicroApp from 'simple-micro-app'

SimpleMicroApp.start()

然后就可以在vue2项目中的任何位置使用micro-app标签。

<!-- page1.vue -->
<template>
  <div>
    <micro-app name='app' url='http://localhost:3001/'></micro-app>
  </div>
</template>

插入micro-app标签后,就可以看到控制台打印的钩子信息。

以上我们就完成了容器元素的初始化,子应用的所有元素都会放入到这个容器中。接下来我们就需要完成子应用的静态资源加载及渲染。

创建微应用实例

很显然,初始化的操作要放在connectedCallback 中执行。我们声明一个类,它的每一个实例都对应一个微应用,用于控制微应用的资源加载、渲染、卸载等。

// /src/app.js

// 创建微应用
export default class CreateApp {
   
  constructor () {
   }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值