写点什么

给 webpack 提了一个 pr 之后......

作者:虎妞先生
  • 2023-02-10
    北京
  • 本文字数:3364 字

    阅读完需:约 11 分钟

前言

我不是标题党啊,是真的给 webpack 提了一个 pr,提交之后,脑子里就是一句话:“纸上学来终觉浅,绝知此事要躬行”。


欲知来龙去脉,听我娓娓道来。



pr 如下,https://github.com/webpack/webpack/pull/16292,目前还是 unreviewed 状态。



阅读此文章你将会了解以下知识点,


  • webstrom 调试 webpack 源码过程

  • webpack 优化->deterministic 属性作用

  • 如何提给开源仓库 pr

  • 如何修改 commit 信息

  • 如何合并 commit 信息

  • EasyCLA 开源协议签署遇到的问题


看到 = 学会,如果对屏幕前的大帅比大漂亮有帮助的话,点个赞什么的就太好了!


背景

那是一个周五的晚上,11.左右,大部分人都准备休息了,我正在做山月的 linux 训练营,赶巧,山月在 webpack 训练营里,圈出一处 webpack 的源码,8 行左右吧。说到,此处有优化空间,可以提 pr。



盯着这段代码,我看了半天,没有上下文,一脸懵圈。大部分人,没有看过源码,直接看肯定看不出毛病,我也是这部分人的一部分。


后来找了一个做前端的朋友一起看,寻取帮助,他刚刚团建完到家,毫无学习状态。


我知道有些路注定要一个人走,自己调试 webpack 源码吧。

调试

我是用的工具是 webstorm。


首先我在 node_modules 中 webpack 目录下,全局搜索,迅速定位到图示函数。


不得不说,webstorm 的搜索功能真是嘎嘎强!


定位到文件,lib/ids/DeterministicModuleIdsPlugin.js 下,看代码不一定知道是什么逻辑,不过看名字却很清楚了,是处理 DeterministicModuleIds 的一个插件函数。


先简单说说 Deterministic

deterministic

正巧,最近刚刚在 webpack 训练营学习了 Deterministic


正好复习一遍。


这是一个 webpack 优化项


optimization: {    moduleIds: 'deterministic',    chunkIds: 'deterministic'}
复制代码


在生产环境下,二者将被 webpack 默认配置为 deterministic。


这说明这个配置项非常 nice,webpack 已经帮我们用了,那聪明的你肯定要问了,它是干什么的呢?


告知 webpack 当选择 moduleId 和 chunkId 时需要使用哪种算法


deterministic 在不同的编译中不变的短数字 id(最少三位)。有益于长期缓存。


翻译翻译就是=>


生成确认的 id,这样可以有效避免由于模块引入的顺序改变而导致的产物大面积更改的问题,每个 module/chunk 都有自己确定的 id。

举例说明

比如在某项目某文件中,引入 A 模块,第一行 import(A)过了一段时间,需要引入 B,新的模块,一般来说我们会放在模块引入最下面,但是有个菜鸟,他在第一行增加 import(B),import(A)就放在了第 2 行,并提交构建。


那么新增 B,导致 A,以及以前原有模块(我叫它们 A+),引入顺序都发生了变化,导致模块 id 发生变化,进而导致文件打包出来的文件名发生变化。


聪明的你,肯定要问了,这有问题吗。其实没啥大问题!不会有任何异常。


但是有没有更好的解决方案,有!


deterministic 这个配置项就可以帮助我们,无论新增或者减少模块,把原有的模块对应的 moduleId 和 chunkId 每次打包出来都一样。


这样我们就可以有效的利用浏览器缓存了。


当然了,不做也可以,大不了新增模块,所有 chunk 都发现了变化,打开页面慢一点而已。



现在其实也已经可以不关心了,因为 webpack 已经是默认配置了。


我只是大概说了下 deterministic 的作用,关于 deterministic 的原理,等后面有余力了,再整一篇。

开始调试

说了这么多,就是为了铺垫,现在我们开始调试。


在 webpack 训练营的 demo 中,有这么一个例子,正好用到了 deterministic。


//build.jsconst path = require('path')const webpack = require('webpack')const normalConfig = {  entry: './index.js',  mode: 'none',  output: {    filename: '[name].[id].[contenthash].js',    chunkFilename: '[name].[id].[contenthash].chunk.js',    path: path.resolve(__dirname, 'dist/normal'),  },  optimization: {    runtimeChunk: {      name: entrypoint => `runtime-${entrypoint.name}`,    },    chunkIds: 'deterministic',    moduleIds: 'deterministic'  }}
f1().run((err, stat) => { console.log(JSON.stringify(stat.toJson(), null, 2))})
复制代码


我使用的开发工具是 webstorm,调试代码特别的方便。


在 f1 函数处,点击一下打上断点。



进入到 node_modules 的 webpack/lib/ids/DeterministicModuleIdsPlugin.js


打上断点



右键 build.js,选择调试 build.js,打开 webpack 调试界面,代码此时已经运行到我们的我们设置的第一个断点处




点击 >>| 按钮,直接运行到下一个断点处,可以看到圈出来的代码,usedIds 是一个 set,用来存放 moduleId


原代码逻辑是,先获取了原 usedIds 的长度 size,插入新的 id,如果发现 size 没变,说明 id 重复了,如果 size 变了,则说明 id 没有重复。



其实就是想判断 usedIs 中有没有 id,没有必要绕这么一大圈用 size 来判断,可以直接用 has 来判断 id 在不在 usedIds 中。时间复杂度一样,还不用额外声明变量。


所以对上述代码进行改写


改写前


(module, id) => {    const size = usedIds.size;    usedIds.add(`${id}`);        if (size === usedIds.size) {            conflicts++;            return false;        }                    chunkGraph.setModuleId(module, id);        return true;},
复制代码


改写后


(module, id) => {    if (usedIds.has(`${id}`) {        conflicts++;        return false;    }    usedIds.add(`${id}`);    chunkGraph.setModuleId(module, id);    return true;},
复制代码

创建提交 pr

  • fork,webpack 仓库到自己 github 仓库

  • git clone 到本地

  • 从 main 分支拉过来,新建一个靠谱的分支 feature

  • 修改代码

  • git add . 提交信息

  • git commit -m "XXXX" 填写靠谱的描述信息

  • git push --set-upstream origin feature

  • 此时登陆 github 就会看到自己 fork 的仓库出现一个 Compare & pull request

  • 点击,进入 webpack 仓库代码提交合并页面,仿照以前的提交的 git log 格式,填写信息,之后,点击 create pull request

  • 创建 pr 之后,就成功了,我们就可以在 webpack 源码仓库看到提交的 pr 了。


如何修改 commit

当我们提交之后,发现自己 commit 信息提交的不合适,或者有歧义,如何修改呢?


  • git log 之后,可以看到你之前提交过的 git 历史:

  • 接下来,在 bash 里输入 wq 退出 log 状态,执行:



  • git commit --amend


这时 bash 里会出现以下内容:



  • 键入 i 进入输出模式。修改 commit 信息

  • 修改完毕之后,:wq 保持修改

  • 此时 git log 已经能看到我们的修改了



  • git push -f 提交修改

如何合并 commit

因为是给源码提 pr,所以当时很慎重,我分几次提交,导致有 3 次 commit,山月老师建议合并成一次,自己开发随心所欲惯了,忽然要合并几次提交,就非常生疏,特意查了一下,所以记录一下。


  • git log,获取 commit id

  • 如果需要合并最近两个,需要获取倒数第 3 个 commitId\

  • git rebase -i e0108eeb2972553d



  • 按照默认顺序,可以将除第一个提交外,都使用 fixup 或 squash 进行标记,最终你将得到这些 commit 向上合并,最终变成一个,提交信息是 pick 标记的信息。


  • pick:使用此提交不做操作

  • squash:将指定的提交合并到上边的 pick 请求中,保留提交信息

  • fixup:与 squash 类似,但不保留提交信息


  • 把不需要的记录 改成 fixup ,:wq 保存

  • git push origin --force


完成上述操作之后,整个 git 提交记录就会完全改变了,而且是不可逆操作,当然这也意味着 rebase 操作是有一定风险的,如果你不太清楚需要做什么的话就不要做。

签署 EasyCLA

一个开源协议,承诺自己的代码可供开源使用



这里需要注意,自己提交信息中的邮箱作者信息,需要和签署的邮箱一致,如果不一致,即使签署依然显示无效。


而我这里遇到的问题就是邮箱作者信息用的是公司 gitLab 的邮箱信息,所以 github 识别不到。

如何修改邮箱作者信息

git commit --amend --author="otheruser <otheremail@qq.com>"git rebase --continuegit push -f origin
复制代码

总结

以上就是我提交 pr 的来龙去脉,至于提交 pr 的意义大家自己体会。


如果对屏幕前的大帅比大漂亮有帮助的话,点个赞什么的就太好了!


无论 pr 会不会被 merge,这都是 webpack 团队事情了,对于我而言,从这个过程中,其实用到的知识点很多,都会细碎,也很简单,一但连贯起来。我遇到了很多很多问题,所以才深深感觉到“纸上学来终觉浅, 绝知此事要躬行”。


看再多博客知识视频,不如自己动手操作一次!

参考

https://zhuanlan.zhihu.com/p/100243017


https://wangbjun.site/2022/coding/git-rebase.html


https://oschina.gitee.io/opensource-guide/

发布于: 刚刚阅读数: 3
用户头像

虎妞先生

关注

还未添加个人签名 2017-12-22 加入

还未添加个人简介

评论

发布
暂无评论
给webpack提了一个pr之后......_前端_虎妞先生_InfoQ写作社区