weback5新增特性

32 阅读3分钟

1、Module Federation# 模块联邦特性

  • 是什么 允许多个独立的webpack应用之间动态共享代码,一个应用可以在运行时从一个应用加载并使用其代码模块,仿佛这些模块是本地的一部分

  • 解决了什么问题 在模块联邦出现前,共享代码的方式只要存在以下几种

    • npm包,通过单独构建组件成npm包的形式在不同项目中引入;但是这种方式无法实现实时同步
    • git submodule的形式;管理复杂,同样需要更新主项目重新构建
    • 外部化+CDN形式,通过external将库(如react\lodash)排除,在运行时通过

    而模块联邦则解决上述问题: (1)去中心化,每个应用都是独立的,单独开发部署 (2)运行时动态加载,实现代码实时共享 (3)共享依赖,两个应用共享同一个库,可以协商使用其中一个版本,避免重复加载

  • 工作原理 主要是有两个角色来工作

    • remote远程应用,他暴露一些模块给其他应用使用
    • host主机应用,消费或引用remote模块
     // remote应用配置
     module.export = {
         //... 其他配置
         plugins: [
             new ModuleFederationPlugin({
               // 该应用的名称,作为唯一标识
               name: 'remote_app',
               // 暴露给外部使用的模块文件
               filename: 'remoteEntry.js',
               // 声明要暴露的模块
               exposes: {
                 // 键名:导入路径
                 // 值:本地模块的实际路径
                 './Button': './src/components/Button.jsx',
                 './Header': './src/components/Header.jsx',
               },
               // 声明共享的库
               shared: {
                 react: { singleton: true }, // singleton 确保只使用一个单例版本
                 'react-dom': { singleton: true },
               },
             })
         ]
     }
     
     // host应用配置
     module.exports = {
       // ... 其他配置
       plugins: [
         new ModuleFederationPlugin({
           name: 'host_app',
           // 配置需要引用的远程应用
           remotes: {
             // 键名:在代码中导入时使用的路径前缀
             // 值:远程应用的名称@远程Entry.js的URL
             remote_lib: 'remote_app@http://localhost:3001/remoteEntry.js',
           },
           // 同样可以声明共享依赖
           shared: {
             react: { singleton: true },
             'react-dom': { singleton: true },
           },
         }),
       ],
     };
     
     
     // 在 Host 应用的 React 组件中
     
     import React from 'react';
     // 动态导入 Remote 应用的 Button 组件
     const RemoteButton = React.lazy(() => import('remote_lib/Button'));
    
     function App() {
       return (
         <div>
           <h1>这是 Host 应用</h1>
           <React.Suspense fallback="Loading Button...">
             <RemoteButton />
           </React.Suspense>
         </div>
       );
     }
    
     export default App;
    
  • 应用场景

    • 微前端: 每个应用独立部署,主应用动态集成
    • 跨项目组件库,将通用业务组件通过联邦共享,任何项目中都可以实时使用最新版本
    • 巨型应用拆分:将一个庞大的单体项目拆分成多个独立,可联邦的部分,提升团队协作和构建速度
  • github关于这个模块的学习demo github.com/markz-demo/…

2、cache缓存特性

在webpack5之前,我们通常使用cache-loader和babel-loader的自带缓存来提升二次构建速度,但是这些方案配置比较繁琐,而且缓存力粒度不够理想,wepack5内置了持久化磁盘缓存,开箱即用,效果明显。

  • 解决问题 webpack构建报告多个阶段(模块解析、依赖分析、转化、优化等)。在没有持久化缓存的情况下,每次都需要重头开始,即使只改动了一点点代码,这将使得效率低下
  • 如何配置
 // 简单配置
 module.exports = {
   // ... 其他配置
   cache: {
     type: 'filesystem', // 使用文件系统缓存
   },
 };
 
 // 比较详细的配置
 module.exports = {
   cache: {
     type:'filesystem',
     // 自定义缓存目录,默认为 node_modules/.cache/webpack
     cacheDirectory: path.resolve(__dirname, 'node_modules/.cache/webpack'),
     // 构建依赖,当这些文件发生变化时,缓存会失效
     buildDependencies: {
       // 通常将项目配置文件加入,这样配置改变时缓存自动失效
       config: [__filename],
     },
     // 缓存版本,当内部缓存数据结构变化时,可更改此版本号来使旧缓存失效
     version: 'your-custom-version',
   },
 };
 ```