不小心将 Webpack 升级后我搞定了微前端。

2,830 阅读2分钟

昨天项目升级的时候,把 Webpack 升级了一个版本。瞬间让我囧大了,你懂的,我就不说了。反正给我一顿操作啊,终于摆平了。

再梳理项目的时候,我用 Webpack 新版本的模块联邦还真实现了应用程序和应用程序之间的引用。一个微前端的雏形就出现了!

借这个机会,刚好把 Webpack 的微前端实现流程介绍一下。

创建两个应用

既然是应用和应用之间的引用,所以我们就创建两个项目,一个叫 app,一个叫 slide。

app 项目的配置文件 webpack.config.js 内容如下:

//app/webpack.config.js
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
//微前端的模块
const ModuleFederationPlugin = require("webpack").container.ModuleFederationPlugin;
module.exports = {
    mode:"development",
    devtool:false,
    entry:"./src/index.js",
    output:{
       filename:"build.js",
       path: path.resolve(__dirname,"dist")
    },
    devServer:{
        contentBase: path.join(__dirname, 'dist'),
        port:8081
    },
    module:{
        rules:[
            {
                test:/\.js$/,
                exclude:/node_modules/,
                use:{
                    loader:"babel-loader"
                }
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            title:"webpack5",
            template:"./public/index.html"
        }),
        new ModuleFederationPlugin({
            name:"remote",
            // library:{type:"var",name:"remote"},
            filename:"remoteEntry.js",
            exposes:{  //导出
                "./App":"./src/App.js"
            }
        })
    ]

​}

Slide 项目的配置文件 webpack.config.js 内容如下:

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
// 模块联邦
const ModuleFederationPlugin = require("webpack").container.ModuleFederationPlugin;
module.exports = {
    mode:"development",
    devtool:false,
    entry:"./src/index.js",
    output:{
        filename:"build.js",
       path: path.resolve(__dirname,"dist")
    },
    devServer:{
        contentBase: path.join(__dirname, 'dist'),
        port:3000
    },
    module:{
        rules:[
            {
                test:/\.js$/,
                exclude:/node_modules/,
                use:{
                    loader:"babel-loader"
                }
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            title:"webpack5",
            template:"./public/index.html"
        }),
        new ModuleFederationPlugin({
            name:"slide",
            library:{type:"var",name:"slide"},
            remotes:{
                "remote":"remote@http://127.0.0.1:8081/remoteEntry.js"
            }
        })
    ]

​}

重点

在 ModuleFederationPlugin 实例化的时候传入参数 options 的字段说明。

  • name 模块名

  • library 目前看到的用法有 { type: "var" } { type: "commonjs-module" },可以用来指定模块的使用规范

  • remotes 需要依赖的模块名

  • exposes 暴露出的模块,可以有多个

  • shared app 打包暴露模块时,不会将 shared 打包,是两个应用的共享依赖,比如 react vue 等

注意:library 是对外导出的一种规范,前端使用 {type:"var"}。在引入的应用程序中这个字段不要加哈,不然会不显示内容,而被引入模块可以加上。

还有就是 exposes 和 remotes 的字段小伙伴们也要注意。

  • exposes 的暴露字段要写上 ./name

  • remotes 的字段跟暴露模块的 name 保持一致,里面别名的定义也要一致

最后,两个应用同时启动,就会发现最终你要的应用就把其他应用的模块也引入进来了(●'◡'●)。