外贸企业网站建设一条龙,专业网站建设 公司排名,免费制作婚介网站,织梦网站怎么做索引地图B站课程视频 课程视频
课程课件笔记#xff1a; 1.微前端
2.无界
现有的微前端框架#xff1a;iframe、qiankun、Micro-app#xff08;京东#xff09;、EMP#xff08;百度#xff09;、无届
前置
初始化
新建一个文件夹 1.通过npm i typescript -g安装ts 2.然后可…B站课程视频 课程视频
课程课件笔记 1.微前端
2.无界
现有的微前端框架iframe、qiankun、Micro-app京东、EMP百度、无届
前置
初始化
新建一个文件夹 1.通过npm i typescript -g安装ts 2.然后可以使用tsc --init初始化项目这样项目目录下会有tsconfig.json配置文件 3.再新建index.ts 4.使用tsc -w命令可以实时的编译index.ts出一个index.js文件 5.通过index.html引入index.js即可
!DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlescript src./index.js/script
/head
body
/body
/htmlwebComponents初使用
主要是为了样式隔离
wu-jie初体验
在index.ts文件中书写
// webComponents 的写法
window.onload () {// 初始化class Wujie extends HTMLElement {// 类的基本用法constructor() {super()// this.attachShadow创建shadowdom并打开就具有样式隔离的性质不会影响外层的样式let dom this.attachShadow({mode: open})// 获取templatelet template document.querySelector(#wujie) as HTMLTemplateElement// 并绑定,这里是把template的内容深度克隆一份给dom而不是直接给true表示深度克隆dom.appendChild(template.content.cloneNode(true))// 这样就把template的内容渲染到了wu-jie/wu-jie的组件里面console.log(this.getAttr(url), this.getAttr(age))}// 获取传参this.getAttribute 传入属性名即可private getAttr(attr: string) {return this.getAttribute(attr)}}// webComponents挂载,注意名字不能启成驼峰的但是-横线连接可以第二个参数是上面类的名字// 类似vue组件 原生js写的一个组件 可以在html中使用了wu-jie/wu-jiewindow.customElements.define(wu-jie, Wujie)
}在上述建立的index.html中书写
body!-- 相当于组件也可以传参 --wu-jie urlxxxxx age18/wu-jiediv我是外层的div/divtemplate idwujiediv我是 template 里面的div/divstylediv{background: red;}/style/template
/body无届的三个生命周期
//生命周期自动触发有东西插入
connectedCallback () {console.log(类似于vue 的mounted);
}
//生命周期卸载
disconnectedCallback () {console.log(类似于vue 的destory);
}
//跟watch类似
attributeChangedCallback (name:any, oldVal:any, newVal:any) {console.log(跟vue 的watch类似有属性发生变化自动触发);
}pnpm介绍
1.全局安装npm i pnpm -g 2.使用 pnpm -v可以查看版本号 3.pnpm 比 npm的优势在pnpm中文网的动机这样写pnpm官网 简单来说就是但有100个vue项目每个项目都会去安装相应的依赖包这样导致磁盘的缩小和安装速度慢每次都会重新下载依赖包很麻烦。 但是pnpm使用软链接、硬链接和仓库解决
硬链接
1.使用cmd查看提示表示 /H就是硬链接
2.创建命令含义 mklink /H 硬链接的名字 通过谁创建 例如在pnpm文件目录下建立index.js文件并通过mklink /H ying.js index.js创建了硬链接 3.并且目录下多出了一个ying.js
4.然后打开文件发现ying.js中内容和index.js中一样 5.而且当修改index.js中的内容时ying.js中的内容会跟着修改因为他们共享的同一个磁盘地址
软链接符号链接
1.创建软链接需要管理员权限所以管理员打开cmd后进入目录可以使用cd ../../等回退到根目录下然后直接 D: 进入相应盘再cd命令 2.默认就是软链接 mklink ruan.js index.js 即可不用加任何修饰符 3.成功创建后VScode中会有一个标志 4.且文件管理器中查看也是一个0字节的因为他只记录一个路径快捷方式并不会占用资源点击会跳转指向的还是index.js
pnpm如何利用硬链接、软链接解决上述问题
1.使用pnpm init命令创建package.json 2.以安装vue包为例使用pnpm i vue 安装vue依赖可以看到node_modules下面有vue的软链接快捷方式地址指向 3.实际上上述软链接指向在.pnpm包下找到真正的vue3.3.13的包下面的vue文件夹这个vue硬链接指向.pnpm store 4.实际上就对应了pnpm官网的这张图非扁平化的方式可能嵌入因为这个库可能还依赖其他库这样依次来
绿色黄色实线为软链接、红色虚线为硬链接
pnpm的CLI命令管理
假设你之前使用的npm 安装包会生成一个package-lock.json或者使用yarn安装过会生成一个yarn.lock
但是你再通过pnpm import命令 他会把你的上述的软件包管理器的 lockfile 生成 pnpm-lock.yaml文件
monorepo项目
创建monorepo项目目录
1.使用命令npm init vue创建vue项目并创建项目名为main 2.创建web文件目录存放子应用 3.创建vue子应用使用npm init vite选择vuetypescript 4.创建react子应用使用npm init vite选择reacttypescript 5.在web文件夹下有多个子应用分别安装有点繁琐所以在monorepo文件夹下使用命令pnpm init生成文件并手动创建pnpm-workspace.yaml文件和配置。配置
官网是
packages:# all packages in direct subdirs of packages/- packages/*# all packages in subdirs of components/- components/**# exclude packages that are inside test directories- !**/test/**替换为自己的目录
packages:# all packages in direct subdirs of packages/- main/*# all packages in subdirs of components/- web/**
此时目录如下 6.替换好pnpm-workspace.yaml之后可以在根目录直接pnpm i即可自动为所有的项目安装包 最外层根目录下的node_modules是所有项目公共的包而vue项目或者react项目里面的node_modules是他们单独所需要的这样结构更加清晰。
子项目启动
假设这时候我们要跨级执行命令想要执行react-demo项目中package.json的dev命令可以使用pnpm -F react-demo dev其中F是过滤filter
子模块复用
1.新建目录common下并进入想要common目录下的东西其余子项目(vue、react等都可以使用 2.使用pnpm init初始化生成package.json文件。在pnpm-workspace.yaml中写
packages:# all packages in direct subdirs of packages/- main/*# all packages in subdirs of components/- web/**- common3.安装axios包了pnpm i axios 3.新建index.ts编写一些公共代码
import axios from axios// 公共的提取出来
export const a axios.get(xxx)4.进入main目录使用命令pnpm -F main add common则把common添加进main项目的依赖中查看main/package.json文件里面有 5.然后就可以在main/src/main.ts中引入
import { a } from common6.同理也可以去给react-demo项目添加或者vue-demo添加pnpm -F vue-demo add common一样查看那个package.json有common包然后可以导入进行使用
无届
安装
1.使用pnpm i wujie在main.ts中引入wujie并配置启动的参数
import { startApp } from node_modules/wujie/esm/index
// 启动的参数
startApp({name, url, el})2.如果是vue项目可以直接安装npm i wujie-vue3进行安装
import Wujie from wujie-vue3
app.use(router).use(Wujie)3.然后分别启动好子应用记录端口就可以在App.vue中使用了
templatedivh1这是主应用/h1!-- 分别是子应用子应用启动之后各自的端口 --WujieVue urlhttp://127.0.0.1:5174 namevue3/WujieVueWujieVue urlhttp://127.0.0.1:5175 namereact/WujieVue/div
/template在main.ts中全部代码如下
import ./assets/main.cssimport { createApp } from vue
import App from ./App.vue
import router from ./router
import Wujie from wujie-vue3 // 引入一下对应的框架
import { preloadApp } from wujieconst app createApp(App)app.use(router).use(Wujie) // 注册无界
app.mount(#app)// exac预加载为true即可那么components/react.vue和vue3.vue就会有url
preloadApp({ name: vue3, url: http://127.0.0.1:5173, exec: true})
preloadApp({ name: react, url: http://127.0.0.1:5174, exec: true})封装无届
1.创建的目录
封装无届
1.创建的目录文件如下 其中使用pnpm init创建package.json 使用tsc --init创建 tsconfig.json 2.使用pnpm i wujie安装无届 3.使用pnpm i vue -D把vue装在开发环境中 4.安装webpack使用pnpm i webpack webpack-cli -D 5.安装typescript使用 pnpm i typescript -D 6.安装typescript解析器使用pnpm i ts-loader -D
书写相关配置代码
配置代码部分可以看源码参照下面的代码
写完后使用 npm run lib 打包
1.在env.d.ts中书写
import { defineComponent, h, getCurrentInstance, onMounted, watch, onBeforeUnmount } from vue
import type { App, PropType } from vue
import { Props } from ./type
import { startApp, bus } from wujie// 函数式定义组件
const wujie defineComponent({props: {width: { type: String, default: },height: { type: String, default: },name: { type: String, default: , required: true },loading: { type: HTMLElement, default: undefined },url: { type: String, default: , required: true },sync: { type: Boolean, default: undefined },prefix: { type: Object, default: undefined },alive: { type: Boolean, default: undefined },props: { type: Object, default: undefined },attrs: { type: Object, default: undefined },replace: { type: Function as PropTypeProps[replace], default: undefined },fetch: { type: Function as PropTypeProps[fetch], default: undefined },fiber: { type: Boolean, default: undefined },degrade: { type: Boolean, default: undefined },plugins: { type: Array as PropTypeProps[plugins], default: null },beforeLoad: { type: Function as PropTypeProps[beforeLoad], default: null },beforeMount: { type: Function as PropTypeProps[beforeMount], default: null },afterMount: { type: Function as PropTypeProps[afterMount], default: null },beforeUnmount: { type: Function as PropTypeProps[beforeUnmount], default: null },afterUnmount: { type: Function as PropTypeProps[afterUnmount], default: null },activated: { type: Function as PropTypeProps[activated], default: null },deactivated: { type: Function as PropTypeProps[deactivated], default: null },},setup(props, { emit }) {// 读取当前组件实例// this.$refs.wujie // 在vue2中可以通过this获取当前组件实例const instance getCurrentInstance() // vue3中通过getCurrentInstance获取组件实例// 封装启动函数const init () {// startApp({name, url, el})//初始化无界startApp({name: props.name,url: props.url,el: instance?.refs.wujie as HTMLElement,loading: props.loading,alive: props.alive,fetch: props.fetch,props: props.props,attrs: props.attrs,replace: props.replace,sync: props.sync,prefix: props.prefix,fiber: props.fiber,degrade: props.degrade,plugins: props.plugins,beforeLoad: props.beforeLoad,beforeMount: props.beforeMount,afterMount: props.afterMount,beforeUnmount: props.beforeUnmount,afterUnmount: props.afterUnmount,activated: props.activated,deactivated: props.deactivated,})}watch([props.name, props.url], () {init() // 如果发生变化就重新执行startApp})const handlerEmit (event:string, ...args:any[]) {emit(event, ...args)}onMounted(() {// 发布订阅模式bus.$onAll(handlerEmit) init()})onBeforeUnmount(() {bus.$offAll(handlerEmit)})// 定义渲染函数return () h(div, {style: {width: props.width,height: props.height},ref: wujie // 方便之后读取})}
})
// install 方法给vue使用的app.use(router).use(wujie)会调用install
wujie.install function(app: App) {app.component(WujieVue, wujie)
}export default wujie2.type.ts中写
import type { plugin } from wujie
type lifecycle (appWindow: Window) any;
interface Props {/** 唯一性用户必须保证 */name: string;/** 需要渲染的url */url: string;/** 需要渲染的html, 如果用户已有则无需从url请求 */html?: string;/** 渲染的容器 */loading?: HTMLElement;/** 路由同步开关 false刷新无效但是前进后退依然有效 */sync?: boolean;/** 子应用短路径替换路由同步时生效 */prefix?: { [key: string]: string };/** 子应用保活模式state不会丢失 */alive?: boolean;/** 注入给子应用的数据 */props?: { [key: string]: any };/** js采用fiber模式执行 */fiber?: boolean;/** 子应用采用降级iframe方案 */degrade?: boolean;/** 自定义运行iframe的属性 */attrs?: { [key: string]: any };/** 自定义降级渲染iframe的属性 */degradeAttrs?: { [key: string]: any };/** 代码替换钩子 */replace?: (codeText: string) string;/** 自定义fetch资源和接口 */fetch?: (input: RequestInfo, init?: RequestInit) PromiseResponse;/** 子应插件 */plugins: Arrayplugin;/** 子应用生命周期 */beforeLoad?: lifecycle;/** 没有做生命周期改造的子应用不会调用 */beforeMount?: lifecycle;afterMount?: lifecycle;beforeUnmount?: lifecycle;afterUnmount?: lifecycle;/** 非保活应用不会调用 */activated?: lifecycle;deactivated?: lifecycle;
};export { Props } 3.webpack.config.js中写
const { Configuration } require(webpack)
const path require(path)/*** type {Configuration} //配置智能提示*/const config {entry: ./src/index.ts, // 入口文件mode: none,output: {filename: index.js,path: path.resolve(__dirname, lib)},externals: { // 防止打包后的代码包含wujie和vue代码显得过多vue: vue,wujie: wujie},module: {rules: [{test: /\.ts$/,use: ts-loader}]}}module.exports configSWC和babel
SWC官网 1.swc比babel快20倍如果是4核情况下快70倍 使用pnpm add -D swc/score swc-loader安装命令
2.然后替换webpack.config.js中的use
module: {rules: [{test: /\.ts$/,use: ts-loader // babel的ts-loader换成swc-loader}]}3.因为swc底层是rust写的rust性能是js的好几倍所很快
4.然后再打包npm run lib打包后还不能直接使用 因为前端有很多代码规范AMD, CMDCommonJSESModule所以统一配置一个UMD 5.安装pnpm i -D swc/cli swc/core以便使用swc-cli 6.新建配置文件.swcrc
{$schema: https://json.schemastore.org/swcrc,jsc: {parser: {syntax: typescript, // js是ecmascript// jsx: false,// dynamicImport: false,// privateMethod: false,// functionBind: false,// exportDefaultFrom: false,// exportNamespaceFrom: false,// decorators: false,// decoratorsBeforeExport: false,// topLevelAwait: false,// importMeta: false},// transform: null,target: es5,loose: false,externalHelpers: false,// Requires v1.2.50 or upper and requires target to be es2016 or upper.keepClassNames: false},minify: false}
7.在根目录的package.json的 scripts中编写打包命令写esm: swc src/index.ts -d esm, 8.控制台执行 npm run swc即可打包在esm文件中 9.修改增添package.json中 设定一些版本号和启动的入口
name: vuejie-setup,
version: 0.0.1,main: lib/index.js,
module: esm/index.js,添加files
files: [lib,esm,index.d.ts],10.在根目录下的index.d.ts声明文件中写
// import { bus, preloadApp, destroyApp, setupApp } from wujie;
import type { App } from vue;declare const WujieVue: {// bus: typeof bus;// setupApp: typeof setupApp;// preloadApp: typeof preloadApp;// destroyApp: typeof destroyApp;install: (app: App) void
};export default WujieVue;发布包
1.切换镜像 mmp use输入 npm 2.使用 npm adduser命令然后输入npm的用户名 3.使用npm login 4.使用 npm publish发布
使用
1.在MONOREPO项目中切换进主应用cd main 2.命令安装pnpm i vuejie-setup 3.在main.ts中引入import Wujie from vuejie-setup 4.使用npm run dev启动各种主应用或者子应用查看效果
无届的预加载和FPS
1.requestldleCallback函数 MDN的解释
2.FPS扩展
无届的传参
总共三种方法
第一种方法
无届的架构是把JS单独存放在了iframe中那么iframe可以通过window和父级进行通讯所以第一种传参就是通过 window.parent.变量名 进行读取。
1.在vue-demo/App.vue中添加按钮绑定函数获取a
script setup langts
const send () {alert(window.parent.a) //
}
/script
button clicksend点击/button2.在控制台输入变量 var a 控制台的输入 3.点击按钮发现可以弹出 第二种方法
通过props 传参子应用不需要绑定无界主应用接进来之后会自动捕获vue实例所以子应用可以访问到无界实例对象获取参数
1.例如在主应用的components/App.vue组件中挂载数据通过props传参
templateWujieVue :props{name: 张三, age: 18} urlhttp://127.0.0.1:5173 namevue3/WujieVue
/template2.然后在vue-demo子项目中的App.vue中写JS代码
const send () {// alert(window.parent.a) // 第一种方法console.log(window.$wujie) // 第二种方式
}3.为了防止上述$wujie报错可以在main.ts中添加
declare global {interface Window {$wujie: {props: Recordstring, anybus: {$emit: any}}}
}4.打印的结果如下可以看到还有bus第三种方法获取 4.上述可以访问props console.log(window.$wujie)进行打印
d第三种方案eventBus发布订阅
可以双向数据传递直接使用wujie的bus.$on 1.在 主应用的App.vue中通过bus.$on绑定数据
script langts
import { bus } from wujie
bus.$on(vue3, (data: any) {console.log(data, 我是主应用的bus.$on)
})
/script2.在子应用vue-demo的App.vue中通过实例直接使用
const send () {// alert(window.parent.a)// console.log(window.$wujie.props) // 获取到App.vue下的propswindow.$wujie.bus.$emit(vue3, 我是子应用vuedemo)
}模块联邦
1.创建文件如下目录
2.安装下面四个依赖包 npm i webpack webpack-cli webpack-server html-webpack-plugin -D 3.书写代码略结果如下总之host里面没有的List数据却通过引入到了remote的数据进行展示 4.pnpm run build进行打包host项目下 点开dist/bundle.js可以看到使用CDN的方式进行引入的 之前10个项目引用同一个模块通过把这个项目发布到npm上面然后这是个项目可以install这个模块但是当这个模块发生改变的时候例如从1.0.0 - 1.0.1那么这十个项目得重新下载install一遍 现在的CDN当你的模块修改了直接就是最新的版本通过这个链接远程调用联邦的技术正是用的这种
报错
1.在tsconfig.app.json中报错没有 “node” 模块解析策略的情况下无法指定选项 “-resolveJsonModule”。
修改tsconfig.app.json 文件中 compilerOptions 选项配置 “moduleResolution”: “node”
{extends: vue/tsconfig/tsconfig.dom.json,include: [env.d.ts, src/**/*, src/**/*.vue],exclude: [src/**/__tests__/*],compilerOptions: {composite: true,/** 模块解析策略ts默认用node的解析策略即相对的方式导入, 可选值node、classic* 如果未指定则 --module commonjs 默认为 node否则默认为 classic包括 --module 设置为 amd、system、umd、es2015、esnext 等* Node 模块解析是 TypeScript 社区中最常用的推荐用于大多数项目。 * 如果您在 TypeScript 中遇到导入和导出的解析问题请尝试设置 moduleResolution: “node” 以查看它是否解决了问题。*/moduleResolution: node, baseUrl: .,paths: {/*: [./src/*]}}
}参考自
一些文件爆红
1.找不到模块“./App.vue”或其相应的类型声明 2.ts.config.app.json找不到文件vue tsconfig tsconfig dom json
如果报错vite找不到之类的以及奇怪的错误请删除两个子应用重新建立和安装和初始化最外层的包pnpm init
ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL vue-demo0.0.0 dev: vite Exit status 1一些常用的命令
pnpm i 和 pnpm init
pnpm i是 pnpm install的简写表示安装包会根据package.json的包版本进行安装 pnpm init是初始化一个项目一般只会在空项目文件下创建package.json一些必要的包
pnpm run dev 和 pnpm run start
前者是开发环境后者是打包之后的生产环境运行项目
使用脚手架建立项目
因为涉及诸多配置建议按照vite、webpack官网来看
使用vite脚手架建立vue、react项目
使用webpack脚手架建立vue、react项目