《Webpack5 核心原理与应用实践》学习笔记-> 构建微前端应用

简介: 《Webpack5 核心原理与应用实践》学习笔记-> 构建微前端应用

初始化项目



项目名称我这边就叫MF,然后对着课程中提供的项目结构建好对应的目录和文件,之前记录过很多次初始化过程了,这里是最后一次了。


  • 新建MF的目录作为项目根目录。
  • 使用终端cd进入到MF
  • npm init -y初始化出package.json
  • npm i -D webpack webpack-cli webpack-dev-server安装webpack的依赖配置。


课程中提到了一个lerna的玩意,让你自己去看,自己去学习,自己啥也不讲,很郁闷的自己去找资料,过程不提了,感兴趣的自己去试试。


  • npx lerna init初始化lerna


这一步会初始lerna,自动创建lerna.json,还有其他的东西,初始化完了也就完了,不用管其他的了,我不讲是因为我还没学会。


app1的配置

  • 新建app1目录
  • npm init -y初始一个package.json
  • app1下新建src目录。
  • src下新建main.jsutils.jsfoo.js


app1在这里是作为子应用的存在创建的,里面有3个js文件,都没有讲里面的内容是什么,这里我试过了,其他的不用管,主要是utils.js里面需要导出一个名为sayHello的函数,如下


// utils.js
export function sayHello() {
    console.log('sayHello')
}

  • 新建webpack.config.js并配置,如下


const path = require("path");
const {ModuleFederationPlugin} = require("webpack").container;
module.exports = {
    mode: "development",
    devtool: false,
    entry: path.resolve(__dirname, "./src/main.js"),
    output: {
        path: path.resolve(__dirname, "./dist"),
        // 必须指定产物的完整路径,否则使用方无法正确加载产物资源
        publicPath: `http://localhost:8081/dist/`,
    },
    plugins: [
        new ModuleFederationPlugin({
            // MF 应用名称
            name: "app1",
            // MF 模块入口,可以理解为该应用的资源清单
            filename: `remoteEntry.js`,
            // 定义应用导出哪些模块
            exposes: {
                "./utils": "./src/utils",
                "./foo": "./src/foo",
            },
            // 可被共享的依赖模块
            shared: ['lodash']
        }),
    ],
    // MF 应用资源提供方必须以 http(s) 形式提供服务
    // 所以这里需要使用 devServer 提供 http(s) server 能力
    devServer: {
        port: 8081,
        hot: true,
    },
};

app2的配置

  • 新建app2目录
  • npm init -y初始一个package.json
  • app2下新建src目录。
  • src下新建main.js,内容如下


(async () => {
    const { sayHello } = await import("RemoteApp/utils");
    sayHello();
})();

这里的app2作为主应用,简单的说明一下import("RemoteApp/utils")

RemoteApp:是在webpack.config.js中配置的,代码在下面,他指向的是app1中生成的remoteEntry.js:这个文件包含utils.jsfoo.js

utilsapp1webpack.config.js使用ModuleFederationPlugin导出的utils,可以对比一下和修改一下代码尝试一下。

  • 新建webpack.config.js并配置,如下


const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ModuleFederationPlugin } = require("webpack").container;
module.exports = {
    mode: "development",
    devtool: false,
    entry: path.resolve(__dirname, "./src/main.js"),
    output: {
        path: path.resolve(__dirname, "./dist"),
    },
    plugins: [
        // 模块使用方也依然使用 ModuleFederationPlugin 插件搭建 MF 环境
        new ModuleFederationPlugin({
            // 使用 remotes 属性声明远程模块列表
            remotes: {
                // 地址需要指向导出方生成的应用入口文件
                RemoteApp: "app1@http://localhost:8081/dist/remoteEntry.js",
            },
            shared: ['lodash']
        }),
        new HtmlWebpackPlugin(),
    ],
    devServer: {
        port: 8082,
        hot: true,
        open: true,
    },
};

上面可以看到ModuleFederationPlugin.shared中有个lodash,这里需要在外层安装lodash的依赖,同时上面提到的lerna初始化完成之后,会自动在package.json中添加依赖的,但是没有安装,也是需要安装的。


全局配置

  • 首先安装一个lodash再说,npm i -D lodash
  • 然后把lerna安装一下npm i
  • 接着在app1app2package.json中添加lodash的依赖,手动添加,不用npm安装。


上面都完成之后就可以在终端中,进入app1下执行npx webpack server,然后再打开一个终端进入app2下执行npx webpack serverapp2会自动打开页面,可以打开控制台查看是否输出sayHello


这里都有热更新,可以尝试修改代码查看效果。


课程里面讲到了依赖共享,我这里略过了,上面的配置是一步到位的,依赖共享我这里没有做记录,个人觉得有一个大概的了解就好了。


微前端


课程中直接新开了一个项目,我这里就继续沿用刚才的,课程中使用的React,我这里就用vue,目的就是为了说明微前端是跨平台的。

  • 根目录下新建一个vue-app的目录。
  • npm init -y初始化package.json文件。
  • 根目录下安装依赖,不是在vue-app下面安装。
  • npm i vue (这个是可以共享的)/ npm i -D vue-loader babel-loader
  • 这个vue项目其实可以使用之前创建好的,我这里就拿出之前的配置,简化一点,这里没有css
  • vue-app下新建一个webpack.config.js的配置文件,如下


const path = require('path');
const { VueLoaderPlugin } = require("vue-loader");
const {ModuleFederationPlugin} = require("webpack").container;
module.exports = {
    mode: "development",
    entry: {
        index: './main.js'
    },
    output: {
        path: path.resolve(__dirname, "./dist"),
        publicPath: `http://localhost:8083/dist/`,
    },
    module: {
        rules: [
            {
                test: /.js$/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /.vue$/,
                use: {
                    loader: 'vue-loader'
                }
            }
        ]
    },
    optimization: {
        splitChunks: false,
    },
    plugins: [
        new VueLoaderPlugin(),
        new ModuleFederationPlugin({
            // MF 应用名称
            name: "vueApp",
            // MF 模块入口,可以理解为该应用的资源清单
            filename: `remoteEntry.js`,
            // 定义应用导出哪些模块
            exposes: {
                "./app": "./main",
            },
            // 可被共享的依赖模块
            shared: ['vue']
        }),
    ],
    devServer: {
        port: 8083,
        hot: true,
    },
};
  • 根目录下新建main.js,内容如下


import {createApp} from 'vue'
import App from './src/App.vue'
// 这里的创建函数需要放到一个导出函数里面使用
export const createVueApp = () => {
    const app = createApp(App);
    app.mount('#app');
    return app;
}

  • 新建src目录
  • src目录下新建App.vue文件,随便写点什么都可以,我的内容如下


<template>
  <h1>这里是Vue项目</h1>
</template>
  • 修改app2webpack.config.js配置


module.exports = {
    plugins: [
        new ModuleFederationPlugin({
            remotes: {
                // 地址需要指向导出方生成的应用入口文件
                RemoteApp: "app1@http://localhost:8081/dist/remoteEntry.js",
                // 这里是新增的vue配置
                vueApp: 'vueApp@http://localhost:8083/dist/remoteEntry.js'
            },
            shared: ['lodash']
        }),
    ]
};

  • 修改app2src/main.js文件,如下


(async () => {
    const {sayHello} = await import("RemoteApp/utils");
    const btn1 = document.createElement('button');
    btn1.innerText = 'sayHello';
    btn1.addEventListener('click', sayHello);
    document.body.append(btn1);
    const {createVueApp} = await import("vueApp/app");
    const btn2 = document.createElement('button');
    btn2.innerText = 'vueApp';
    btn2.addEventListener('click', createVueApp);
    document.body.append(btn2);
    const app = document.createElement('div');
    app.id = 'app';
    document.body.append(app);
})();

这里为啥不是用html-webpack-plugin去写页面的按钮呢?因为报错了,我找了两个小时没找到原因,只用html-webpack-plugin中指定了template的指向就会报错,感兴趣的可以拿创建微前端的之前的示例去做实验,如果找到问题麻烦在评论区留言,感激不尽。


经过上面的一番操作,这里我们同步启动这三个服务,执行命令npx webpack server


点击sayHello控制台就会有sayHello的输出

image.png


点击vueApp页面展现的就是vue-app中写的内容啦。

image.png

总结


上面的示例中其实一直都有一个问题,就是css的样式隔离并不能行,而且js的模块加载也只是远程模块加载,会不会带来一些属性的污染?这里我只是学习阶段,了解并不深,需要继续探索。


其次就是课程中内容,写到这里我想说,如果只是想入门看我的笔记,跟着写就够了,其他的就不多说了。


demo地址:MF


目录
相关文章
|
18天前
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
31 3
|
15天前
|
监控 前端开发 JavaScript
探索微前端架构:构建可扩展的现代Web应用
【10月更文挑战第29天】本文探讨了微前端架构的核心概念、优势及实施策略,通过将大型前端应用拆分为多个独立的微应用,提高开发效率、增强可维护性,并支持灵活的技术选型。实际案例包括Spotify和Zalando的成功应用。
|
19天前
|
缓存 监控 前端开发
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第26天】前端工程化是现代Web开发的重要趋势,通过将前端代码视为工程来管理,提高了开发效率和质量。本文详细对比了Webpack和Gulp两大主流构建工具的选择与配置优化,并提供了具体示例代码。Webpack擅长模块化打包和资源管理,而Gulp则在任务编写和自动化构建方面更具灵活性。两者各有优势,需根据项目需求进行选择和优化。
48 7
|
19天前
|
Rust 前端开发 JavaScript
前端性能革命:WebAssembly在高性能计算中的应用探索
【10月更文挑战第26天】随着Web应用功能的日益复杂,传统JavaScript解释执行模式逐渐成为性能瓶颈。WebAssembly(Wasm)应运而生,作为一种二进制代码格式,支持C/C++、Rust等语言编写的代码在浏览器中高效运行。Wasm不仅提升了应用的执行速度,还具备跨平台兼容性和安全性,显著改善了Web应用的响应速度和用户体验。
31 4
|
18天前
|
前端开发 数据管理 测试技术
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第27天】本文介绍了前端自动化测试中Jest和Cypress的实战应用与最佳实践。Jest适合React应用的单元测试和快照测试,Cypress则擅长端到端测试,模拟用户交互。通过结合使用这两种工具,可以有效提升代码质量和开发效率。最佳实践包括单元测试与集成测试结合、快照测试、并行执行、代码覆盖率分析、测试环境管理和测试数据管理。
35 2
|
18天前
|
缓存 前端开发 JavaScript
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第27天】在现代前端开发中,构建工具的选择对项目的效率和可维护性至关重要。本文比较了Webpack和Gulp两个流行的构建工具,介绍了它们的特点和适用场景,并提供了配置优化的最佳实践。Webpack适合大型模块化项目,Gulp则适用于快速自动化构建流程。通过合理的配置优化,可以显著提升构建效率和性能。
31 2
|
19天前
|
前端开发 安全 应用服务中间件
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第26天】随着互联网的快速发展,前端性能调优成为开发者的重要任务。本文探讨了HTTP/2与HTTPS在前端性能优化中的应用,介绍了二进制分帧、多路复用和服务器推送等特性,并通过Nginx配置示例展示了如何启用HTTP/2和HTTPS,以提升Web应用的性能和安全性。
17 3
|
19天前
|
前端开发 JavaScript 数据可视化
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第26天】前端自动化测试在现代软件开发中至关重要,Jest和Cypress分别是单元测试和端到端测试的流行工具。本文通过解答一系列问题,介绍Jest与Cypress的实战应用与最佳实践,帮助开发者提高测试效率和代码质量。
28 2
|
19天前
|
前端开发 JavaScript API
前端框架新探索:Svelte在构建高性能Web应用中的优势
【10月更文挑战第26天】近年来,前端技术飞速发展,Svelte凭借独特的编译时优化和简洁的API设计,成为构建高性能Web应用的优选。本文介绍Svelte的特点和优势,包括编译而非虚拟DOM、组件化开发、状态管理及响应式更新机制,并通过示例代码展示其使用方法。
33 2
|
20天前
|
前端开发 JavaScript 开发者
“揭秘React Hooks的神秘面纱:如何掌握这些改变游戏规则的超能力以打造无敌前端应用”
【10月更文挑战第25天】React Hooks 自 2018 年推出以来,已成为 React 功能组件的重要组成部分。本文全面解析了 React Hooks 的核心概念,包括 `useState` 和 `useEffect` 的使用方法,并提供了最佳实践,如避免过度使用 Hooks、保持 Hooks 调用顺序一致、使用 `useReducer` 管理复杂状态逻辑、自定义 Hooks 封装复用逻辑等,帮助开发者更高效地使用 Hooks,构建健壮且易于维护的 React 应用。
28 2