微服务 ModuleFederationPlugin Vue项目体验

12 篇文章 1 订阅
2 篇文章 0 订阅

随着公司项目的模块越来越多,每次打包后的项目都非常大,而且每修改一个小的模块,都会将整个项目打包,会非常的麻烦,随着前端的发展,微服务的出现,很好的解决了项目庞大的问题,而且每修改一个模块,可以单独打包发布。

项目的公共组件,因为每个单独项目都会有公共的组件,不可能每个项目都复制一份,这样冗余代码太多,也不好维护

1、可以通过构建一个项目组件,发布到npm上面

npm麻烦的地方,在于每次组件的修改,都需要升级npm的版本号,每个项目需要重新更新新的组件,也挺麻烦的

2、还有一个个就是用 Module Federation来解决跨应用代码共享的问题

下面我们就来看下Module Federation是怎么实现代码共享的

Module Federation的意思是模块联邦,使得javascript应用可以从另一个javascript应用中动态的加载代码,共享组件

如何使用ModuleFederationPlugin

配置示例

new ModuleFederationPlugin({
    filename: "remoteEntry.js",
    name: "hcc",
    library: { type: "umd", name: "hcc" },
    exposes: {
        './myCom': "./src/index.js",
    },
    remotes: {
        myCom: "project@http://localhost:3000/remoteEntry.js",
    },
    shared: ['vue']
})

配置属性

  • name,必须,唯一 ID,作为输出的模块名,使用的时通过 ${name}/${expose} 的方式使用;
  • library,必须,其中这里的 name 为作为 umd 的 name;
  • remotes,可选,表示作为 Host 时,去消费哪些 Remote;
  • exposes,可选,表示作为 Remote 时,export 哪些属性被消费;
  • shared,可选,优先用 Host 的依赖,如果 Host 没有,再用自己的;

知道了这个这些概念,下面我们来看看怎么在项目中使用

创建项目

我们创建两个项目,一个用来作为组件库hcc,一个是项目project,项目都是基于webpack5来构建的

创建组件库

我们先创建一个组件项目,hcc,通过npm init初始化项目,再下载一些依赖

npm install webpack weback-cli webpack-dev-server

还需要文件,vue文件的一些插件

npm isntall vue-loader babel-loader @babel/preset-env @babel/core vue-template-compiler

在根目录下新建一个src目录,里面建一个index.js文件,作为道出的入口文件

{
  "name": "hcc",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "serve": "webpack-dev-server  --config webpack.config.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@babel/core": "^7.20.12",
    "@babel/preset-env": "^7.20.2",
    "babel-loader": "^9.1.2",
    "vue-loader": "^17.0.1",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.11.1"
  }
}

在根目录下再新建一个webpack.config.js用来打包的文件

我们来创建两个简单的组件

在src文件下创建组件1【jq-header.vue】

<template>
	<div class="jq-header">
		<h1>我是jq-header组件</h1>
	</div>
</template>

<script>
export default {
	name: 'JqHeadder',
	componentName: 'JqHeadder',
}
</script>

组件2【jq-footer】

<template>
	<div class="jq-footer">
		<h1>我是jq-footer组件</h1>
	</div>
</template>

<script>
export default {
	name: 'JqFooter',
	componentName: 'JqFooter',
}
</script>

在index.js中引入

import JqHeader from "./JqHeader.vue"
import JqFooter from "./JqFooter.vue"
const components = [JqHeader, JqFooter]

const install = (Vue) => {
  components.forEach(component=>{
    Vue.component(component.name,component)
  })
}
export default {
  install
}

下面我们就需要在webpack.config.js中,将我们的组件打包出去

入口文件就是我们的src/index.js,

const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const {ModuleFederationPlugin} = require('webpack').container
module.exports = {
  mode:"development",
  entry: path.join(__dirname, './src/index.js'),
  devServer:{
    port:3000
  },
  module:{
    rules:[
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env'
            ]
          }
        }
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },
  plugins:[
    // 处理rules的配置,加载文件
    new VueLoaderPlugin(),
    new ModuleFederationPlugin({
      filename:"remoteEntry.js",
      name:"hcc",
      library: { type: 'umd', name: 'hcc' },
      exposes:{
        "./hcc":"./src/index.js"
      }
    })
  ]
}

因为我们项目中会加载vue,js文件,所以需要配置babel-loader和vue-loader,并且通过VueLoaderPlugin来处理rules

这样我们的组件库就基本配置好了,我们来启动项目

npm run serve

没有报错就代表项目启动成功了,但是我们打开服务地址其实是这样的

其实我们在共享组件代码的时候其实用的是remoteEntry.js,我们试着访问下

出现这样的代码,就代表我们的组件已经暴露出去,在项目的就可以引用了

创建项目

 

我们通过vue create来创建项目,因为我们用的是webpack5,所以我们需要升级我们的vue-cli到4版本,这样我们创建的项目才是webpack5

npm install -g @vue/cli

创建完项目以后,我们看下package.json,是不是webpack5,然后我们在vue.config.js配置moduleFederationPlugin

const { defineConfig } = require('@vue/cli-service')
const {ModuleFederationPlugin} = require('webpack').container
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack:config=>{
    config.plugins.push(new ModuleFederationPlugin({
      name: "jqCom",
      remotes: {
        jqCom: "hcc@http://localhost:3000/remoteEntry.js",
      },
    }))
  }
})

我们在这里定义的jqCom引入的组件库的remoteEntry.js

我们来启动我们的项目,不报错的话,代表我们引入组件库的文件成功了

下面我们就在项目中引用下我们的组件,先去注册下组件,

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

(async ()=>{
  let jqCom = await import('jqCom/hcc')

  Vue.use(jqCom.default)

  new Vue({
    render: h => h(App),
  }).$mount('#app')
})()

这里需要注意的一点就是我们的组件库导出的其实是一个异步函数,是一个new Promise,所以我们在引入的时候,需要通过await来接收,创建一个自执行函数,来注册组件

然后我们修改下HelloWorld.vue组件内容,引用我们组件库的组件

<template>
	<div class="hello">
		<jq-header></jq-header>
		<jq-footer></jq-footer>
	</div>
</template>

<script>
export default {
	name: 'HelloWorld',
	props: {
		msg: String,
	},
}
</script>

我们打开页面,就可以看到组件库中的组件了

这样就实现了多个项目共享一套自定义组件库功能,提高我们的开发效率

到这里其实还没有结束,因为我们只打包了js,因为我们组件库都是有样式的,我们试着在组件库添加样式,看能不能被引用到项目中,有没有效果

<template>
	<div class="jq-header">
		<h1>我是jq-header组件</h1>
	</div>
</template>

<script>
export default {
	name: 'JqHeadder',
	componentName: 'JqHeadder',
}
</script>
<style>
.jq-header {
	color: red;
}
</style>

其实只是这样的话,项目是会报错的,因为我们没有对css进行处理,需要下载相应的loader去处理

 

比如我们在组件库中使用scss

npm install style-loader css-loader node-sass sass-loader

在webpack.config.js中加上配置,如果没有style-loader,是不会把css代码打包到js当中,外部项目引用不到

{
   test: /\.css$/,
   use: [ 'style-loader', 'css-loader'],
},
{
   test: /\.scss$/,
   use: ['style-loader','css-loader', 'sass-loader'],
},

把css修改成scss

<template>
	<div class="jq-header">
		<h1>我是jq-header组件</h1>
	</div>
</template>

<script>
export default {
	name: 'JqHeadder',
	componentName: 'JqHeadder',
}
</script>
<style lang='scss'>
.jq-header {
	color: red;
}
</style>

重新运行组件项目

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值