2

记录:Webpack5把微前端qiankun的配置文件干没了

 2 years ago
source link: https://segmentfault.com/a/1190000040842378
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

故事的开头

从一个快要下班的BUG开始,由于原部门同事想要基于一个项目再拆分出几个项目,我们本来用的是qiankun(基座模式)的微前端模式,再拆分其实是比较简单的

只是这次顺便在拆分之前升级了webpack5,升级也是比较简单,这里一笔带过

实施的过程没有亲自操作

问题来了,在子应用升级了webpack5以后,本地通过基座加载调试时候,突然启动不了了

临近下班,这个事情要解决,先复现

发现network面板通过基座加载子应用时候,出现了一个js文件404

这里面很蹊跷,因为子应用单独可以启动,子应用被基座家加载时候只有一个js文件404了,而且是一个异步加载的js,那么可以判断,肯定是加载逻辑这块出了问题

在子应用中调试,打开public-path文件:

if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

发现这些代码在通过微前端基座模式加载时候,竟然没有运行!!!是整个代码都没有被执行

这个js文件是通过入口index.tsx文件顶部引入的

已经定位到了问题,就不怕。

核心问题是:当时发现子应用的__webpack_publicPath__这个变量没有被修改,所以造成了请求的host不对,异步加载的js文件404了

由于在排查这个问题之前,我在群里说了一句,有问题大家要一起看,这样都能学到一些东西,还好我说了这句话,拉上几个同事一起来听。

其中一个同事说了一句,会不会是被webpack5给tree sharking了

我感觉是,然后让他们看看自己是怎么配置这块的,于是同事提出建议

package.json中的sideEffects字段,加上这个文件

然后再次启动项目,就解决这个问题了,public-path正常被加载了


看似简单的解决

看似简单的解决,需要先定位问题,这会用到以下几点:

熟悉微前端qiankun的原理

熟悉webpack的原理以及webpack动态懒加载实现的原理

熟悉webpack的__webpack_pulicPath__属性的意义

知道tree sharking

了解webpack5的tree sharking配置

逐个原理讲解

微前端原理

可以看我之前的手写微前端文章+源码:https://github.com/JinJieTan/...

微前端最核心的原理就是:基座项目通过配置信息,发送fetch请求,将子应用的资源全部拿到后渲染成dom节点插入到容器节点中。然后劫持路由变化事件,先在基座触发,再派发给其他子应用

webpack异步代码分割原理

同步和异步代码都会被打包成不同的js文件,由于异步加载的js文件其实是通过网络请求拿到后插入到页面中,这个异步请求的前缀,其实是可以通过__webpack__pulicPath__这个变量来设置的

这也是最早的webpack5联邦模块实现思路,可以动态加载远程js文件,只要控制这个前缀变量__webpack_pulicPath__即可

微前端+异步代码分割,核心思想是:动态的设置__webpack__publicPath__

webpack5的tree sharking配置

tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块语法的 静态结构 特性,例如 import 和 export。这个术语和概念实际上是由 ES2015 模块打包工具 rollup 普及起来的。

webpack 2 正式版本内置支持 ES2015 模块(也叫做 harmony modules)和未使用模块检测能力。新的 webpack 4 正式版本扩展了此检测能力,通过 package.json 的 "sideEffects" 属性作为标记,向 compiler 提供提示,表明项目中的哪些文件是 "pure(纯正 ES2015 模块)",由此可以安全地删除文件中未使用的部分。

以上是官网文档介绍

sideEffects 和 usedExports(更多被认为是 tree shaking)是两种不同的优化方式。

sideEffects 更为有效 是因为它允许跳过整个模块/文件和整个文件子树。

usedExports 依赖于 terser 去检测语句中的副作用。它是一个 JavaScript 任务而且没有像 sideEffects 一样简单直接。而且它不能跳转子树/依赖由于细则中说副作用需要被评估。尽管导出函数能运作如常,但 React 框架的高阶函数(HOC)在这种情况下是会出问题的

现在回到刚才我们被tree sharking的代码:

if (window.__POWERED_BY_QIANKUN__) {
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;

这个代码在上下文中其实是没有被引用的,只有在代码编译后,异步的代码js文件被加载时才能用到__webpack_public_path__这个变量,所以就被清除了代码

那么为了解决这个问题,我们需要在 package.json 中添加 "sideEffects" 属性。

它类似于 /#__PURE__/ 但是作用于模块的层面,而不是代码语句的层面。它表示的意思是(指"sideEffects" 属性):“如果被标记为无副作用的模块没有被直接导出使用,打包工具会跳过进行模块的副作用分析评估。”。

跳过public-path文件到副作用分析评估,直接打包它,就解决了这个问题

webpack的tree-sharking文档:https://webpack.docschina.org...

小小的一个问题,看似解决起来简单,但是对于日常的各种实现原理是都要求很熟悉,才能快速定位问题并且解决,这就是学习源码和各种原理的意义

感兴趣的朋友可以去我的gitHub,这些源码+文章都在https://github.com/JinJieTan/Peter- 记得给个star

喜欢的朋友帮Peter来一波在看/赞吧~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK