【webpack】webpack5模块联邦实战

前言

  • weback的模块联邦原理和import相似,也是做成了预留的promise坑位,通过webpackjsonp加载,获取变成发请求获取而已。
  • 下面来实战一下。

安装

  • webpack最新做了个init脚手架,首先安装以下包:
yarn add @webpack-cli/init webpack-cli webpack webpack-dev-server -D
  • 初始化脚手架:
npx webpack-cli init
  • 注意!如果总是提示你找不到webpack,但你已经安装,很可能是因为你没有装webpack-cli。
  • 经过一系列选项即可生成项目
  • 编写执行脚本:
	"start": "webpack serve",
		"build": "webpack"
  • 我一开始以为start是webpack-dev-server,现在是webpack serve启动,且webpack-dev-server无法独立启动并且必须安装。

  • 我们模拟2个团队,团队A开发组件部署到线上给团队B使用,团队B使用远程组件。

TeamA

  • 首先做teamA的设置,新建webpack.config.js:
const path = require("path");
const webpack = require("webpack");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
	mode: "development",
	entry: "./src/index.ts",
	output: {
		publicPath: "http://localhost:3000/", //部署后的资源地址
	},
	experiments: {
		topLevelAwait: true, // 试验性质顶级作用域允许await
	},
	plugins: [
		new webpack.ProgressPlugin(),
		new HtmlWebpackPlugin({
			template: "index.html",
		}),
		// name	string	必传值,即输出的模块名,被远程引用时路径为${name}/${expose}
		// library	object	声明全局变量的方式,name为umd的name
		// filename	string	构建输出的文件名
		// remotes	object	远程引用的应用名及其别名的映射,使用时以key值作为name
		// exposes	object	被远程引用时可暴露的资源路径及其别名
		// shared	object	与其他应用之间可以共享的第三方依赖,使你的代码中不用重复加载同一份依赖
		new ModuleFederationPlugin({
			filename: "teamA.js",
			name: "teamA",
			exposes: {
				"./componentA": "./src/componentA", // 这个键名是拿到teamA.js后用o函数取的位置,因为远程调用是import(teamA/XXX),切了路径所以是个路径
				"./componentB": "./src/componentB",
			},
		}),
	],

	module: {
		rules: [
			{
				test: /\.(ts|tsx)$/,
				loader: "ts-loader",
				include: [path.resolve(__dirname, "src")],
				exclude: [/node_modules/],
			},
			{
				test: /.(less|css)$/,

				use: [
					{
						loader: "style-loader",
					},
					{
						loader: "css-loader",

						options: {
							sourceMap: true,
						},
					},
					{
						loader: "less-loader",

						options: {
							sourceMap: true,
						},
					},
				],
			},
		],
	},

	resolve: {
		extensions: [".tsx", ".ts", ".js"],
	},

	devServer: {
		open: true,
		host: "localhost",
		port: 3000, //本地调试
	},
};
  • 我们会导出2个组件,componentA与componentB,自己对应位置新建a和b:
function AAA() {
	console.log("i am componentA");
}
export default AAA;
function BBB() {
	console.log("i am componentB");
}
export default BBB;
  • teamA部分完成,启动teamA项目

teamB

  • 同理,teamB也编写webpack.config.js:
/*
 * @Author: yehuozhili
 * @Date: 2021-03-05 13:03:13
 * @LastEditors: yehuozhili
 * @LastEditTime: 2021-03-06 16:16:04
 */
const path = require("path");
const webpack = require("webpack");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
	mode: "development",
	entry: "./src/index.ts",
	output: {
		publicPath: "http://localhost:3001/", //部署后的资源地址
	},
	devServer: {
		open: true,
		host: "localhost",
		port: 3001, //本地调试
	},
	experiments: {
		topLevelAwait: true, // 试验性质顶级作用域允许await
	},
	plugins: [
		new webpack.ProgressPlugin(),
		new HtmlWebpackPlugin({
			template: "index.html",
		}),
		// name	string	必传值,即输出的模块名,被远程引用时路径为${name}/${expose}
		// library	object	声明全局变量的方式,name为umd的name
		// filename	string	构建输出的文件名
		// remotes	object	远程引用的应用名及其别名的映射,使用时以key值作为name
		// exposes	object	被远程引用时可暴露的资源路径及其别名
		// shared	object	与其他应用之间可以共享的第三方依赖,使你的代码中不用重复加载同一份依赖
		new ModuleFederationPlugin({
			filename: "teamB.js",
			name: "teamB",
			remotes: {
				teamA: "teamA@http://localhost:3000/teamA.js",
			},
		}),
	],

	module: {
		rules: [
			{
				test: /\.(ts|tsx)$/,
				loader: "ts-loader",
				include: [path.resolve(__dirname, "src")],
				exclude: [/node_modules/],
			},
			{
				test: /.(less|css)$/,

				use: [
					{
						loader: "style-loader",
					},
					{
						loader: "css-loader",

						options: {
							sourceMap: true,
						},
					},
					{
						loader: "less-loader",

						options: {
							sourceMap: true,
						},
					},
				],
			},
		],
	},

	resolve: {
		extensions: [".tsx", ".ts", ".js"],
	},
};
  • 我们使用remote加载teamA的资源。
  • 在teamB的index中,使用webpackimport导入:
/*
 * @Author: yehuozhili
 * @Date: 2021-03-05 18:04:47
 * @LastEditors: yehuozhili
 * @LastEditTime: 2021-03-06 17:25:56
 */

//@ts-ignore
import("teamA/componentA").then((res) => {
	const componentA = res.default;
	componentA();
});
//@ts-ignore
import("teamA/componentB").then((res) => {
	const componentA = res.default;
	componentA();
});
  • 即可在teamB中获取到teamA的资源。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

业火之理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值