关于webpack替换文件hash的问题,有人有过这方面经验吗

关于webpack替换文件hash的问题,有人有过这方面经验吗,第1张

首次使用Webpack, 用CLI, 即Command Line Interface

→ 确认是否安装了NodeJS

npm -v

→ 安装 Webpack

npm install webpack -g

→ 创建一个简单的网站

.....webpacktest/

..........app.js

..........index.html

→ 导航到webpacktest所在文件

→ 对app.js文件使用webpack

webpack ./app.js bundle.js

→ 我们看到在webpacktest目录下多了一个bundle.js文件

→ 现在,可以在index.html中引用bundle.js文件,而不是app.js文件

■ 在项目中添加配置文件

→ 在项目根目录下创建名称为webpack.config.js文件

当设置好webpack.config.js文件后,每次我们导航到项目,只要使用webpack这一个命令就可以使用各项功能袜团了。

module.exports = {

entry: "./app.js",

output: {

filename: "bundle.js"

}

}

→ 命令行来到需要Webpack的网站下

→ 直接输入webpack命令

webpack

■ 启用Webpack观察者模式

当webpack.config.js的配置发生变化,如果每次都要手动输入webpack命令来生成js文件的话,显得相对麻烦一些。Webpack为我们提供了观察者模式,启用后,任何的webpack.config.js中的变化将接受观察,自动生成最终的js文件。

→ 命令行来到需要Webpack的网站下

→ 启用观察者模式

webpack --watch

→ 在webpack.config.js中添加watch字段,并设置成true

module.exports = {

entry: "./app.js",

output: {

filename: "bundle.js"

},

watch: true

}

→ 这样,每次修改保存webpack.config.js中引用文件,bundle.js的文件会自动更新。

■ 安装启用Webpack DevServer

→ 导航到目标网站目录

→ 输入npm命令安装Webpack DevServer

npm install webpack-dev-server -g

→ 输入弯模webpack-dev-server命令

webpack-dev-server

→ 看到大致如下内容

http://localhost:8080/webpack-dev-server

webpack result is served from /

cotent is served from D:\...

Hash:...

Version:webpack1.12.4

Time:94ms

...

webpack: bundle is now VALID.

→ 在浏览器中输入:http://localhost:8080/webpack-dev-server/

同时显示app.js文件中console.log和document.write的内容。

→ 修改webpack.config.js中依赖的文件并保存,浏览器中的内容就会自动更新

→ 如果不想显示console.log内容呢?

→ 在浏览器中输入:http://localhost:8080/

→ 此时,再修改webpack.config.js中依赖的文件并保存,浏览器的内容却不会更新?

→ 再次回到命令行,加入一个inline的flag

webpack-dev-server --inline

→ 此时,如果修改webpack.config.js中依赖的文件并保存,浏览器中的内容就会自动更新了☺

■ Bundling多个文件

→ 在项目下再添加一个login.js文件

console.log('login loaded')

→ app.js中引用login.js文件

require('./login')

document.write("Welcome to Big Hair Concerts!!Baby")

console.log('App loaded')

→ 在浏览器中输入:http://localhost:8080/

可以看到变化。

→告闹橘 在项目下再添加一个utils.js文件

console.log('logging from the utils.js file...')

→ 来到webpack.config.js下配置如下:

module.exports = {

entry: ["./utils","./app.js"],

output: {

filename: "bundle.js"

},

watch: true

}

→ 命令行导航到当前项目下

→ 重新启用Webpack DevServer

webpack-dev-server

→ 在http://localhost:8080/中体现了相应的变化

这个问题其实是因为webpack在每次执行的过程中都会生成一段带有模块标示的js真正被执行的时候会用到的脚本 官方称 runtime and module manifest 。这个是在真正使用打包后js的时候要用到的,所以不能干掉。这段文件打开看会发现,里扰渣面包含了app.js和vendor.js的md5戳,那么一旦app.js发生了修改,就意味着这个文件也会修改,因为app.js对应的md5变了。如果我们使用了CommonsChunkPlugin进行提取的时候,势必要运行webpack,那么在提取vendor的过程中,webpack就会把这个脚本插入到vendor里了。造成每次app.js变了,也会影响vendor.js。

解决办法就是,把运行webpack生成一段带有模块标示的脚本这件事单独再运行一次,让这段脚本生成到自己的文件里,自己去改变。如下自缓斗悄己再提取一次,生成最后的一个js文件,那销做么这次的执行产生的带有模块标示的脚本就会加入到这里面了。

这个manifest 负责webpack产生的文件的模块封装。如果干掉这些脚本,就会报错啦。

此篇博客紧承上一篇,上片讨论了我们的webpack整个处理单个文件的流程,这一节主要说一说webpack的文件打包问题,其实本身是比较简单的,但是有异步块和html-plugin的加入,使这个步骤变得尤为复杂,这里先介绍几个重要的概念:

上一节中,我们成功的对每个文件进行了处理,并通过了process的方法对所有入口文件以及他们的依赖文件进行了处理,获得了最初的依赖文件列表,现在我们就可以对资源的依赖进行优化处理,本片的内容将从webpack/lib/Compiler.js:510的断点开始逐步的对源码进行分析

在seal之前,由于一轮compilition已经执行完成,先调用finish方法进行收尾处理与之对应的是我们注册的finish-modules事件,

这里我们首先看到的又是index.ejs这个老朋友,由于他是单独的文件经过了loader处理没有获得额外的处理函数的依赖,所以最终这里看到的module实际上是它的js外壳包起来的ejs文件,此阶段也还没有进行资源hash的注入等等

这里有一个FlagDependencyExportsPlugin进行了 *** 作,听名字可能就听出来了,他是对我们资源中的export使用进行一个标志的作用, 和我们最终做出的tree shaking效果可能是相关的

调用seal事件处理

处理我们的preparedChunk,这个东西是我们刚好在进行addEntry的时候添加上的不知道你们还记不记得,中途就没有添加过新的,所以讲道理,一个entry是只用一个的,但是这里使用了一个数组不知道有什么用意

然后把这个入口模块添加到了block里面,过后打包也是从block里面拿数据,block里面的东西会被打包成为单独的文件,但是还是工作在之前的上下文中,这里可以通过看一下这里的import即是我们之前在路由文件中通过import函数设置引入的动态加载路由资源

进入到processDependenciesBlockForChunk函数,就开始处理我们之前做好准备的block了,这里这是一个不断处理依赖的过程,但是没有使用递归的做法,毕竟文件太多了,不断的进行递归会浪费很多空间,取而代之的是使用queue进行记录,处理过程中不断把新的需要处理的模块放到queue里面等待下一步处理

在每一步的处理中

处理完这一波循环依赖旅历过后,本身的依赖树结构变得扁平化,之前一层一层的模块通过dependency连接起来作为一个树的结构,而现在变成了顶层最终的几个chunk

可拆正搜以看到我们最终在这个入口(entry)设置清穗中拿到了9个chunk,她们都有_modules属性,我们的所有依赖都是放到这里面的,是用的一个Set进行存储,其中的依赖关系则是通过origins和reason等标识进行模块间关系的连接的

还可以将我们的入口chunk和异步加载的chunk进行一些对比(上面的是入口文件),下面的chunk中出现的origins就是指向我们之前的router那个module

这个图里也可以看到,两个chunk实际上按照自己的路子搜集了所有的依赖,结果导致了_modules的文件数量都达到了一千多个,这就是我们常使用的CommonChunk插件需要处理的地方了,稍后进行讨论

这轮处理我们成功的把主要的入口module和异步加载的模块区分开了,然后开始按照类似的逻辑处理我们的第一个入口模块

这个时候拿到chunkDependencies进行处理,这就是之前那个存储block的东西,但是有个很奇怪的地方,就是这里面居然只有三个chunk,而不是和上面的一样是9个也不是只有一个入口模块,这就让人无从下手了(我异步加载的模块并不是一样的,而且这些模块之间没有没相互依赖)

喜闻乐见进行第二次处理,首先取出一个chunk拿到对应的存储在value中的deps,对每一个项目添加上了他们的parent,但是有个组件就是用来removeParent的

在RemoveParentModulesPlugin这个插件中,针对每个module都做了处理,看看这些模块在哪些chunk之中有被使用到,把他们所存在的chunks按照id记录下来,并改变她们的reason为几种统一的chunk组合数组。这样就做到了每个module知道了自己被哪些chunk使用,但是从之前的单一reason到现在的多reason具体不知道有什么用(恩。。可能是为作用域提升做准备)

然后嘛,移除空的模块,不需要多解释

然后这层处理就算完啦,主要进行了模块的依赖梳理和拆分,并为他们添加上了指向父节点的指针(话说之前不是有origins吗)

对模块进行排序工作,不过只是按照索引进行排序罢了,那个按照出现概率进行排序处理的插件不是在这里工作的

又是那个flag的插件进行了处理,但是只是把所有模块的used设置为了true,还有为一些被依赖的module设置上他们的usedExports为true

ChunkConditions插件用于监视模块上是否有chunkCondition函数,并返回他的执行结果,如果有模块的此函数返回了false,那么将会重写这个模块(重写即是重新添加进入parent的链接以及reason等的设置)并且还会返回true,到至此过程不断执行直至condition全部OK

RemoveParentModulesPlugin这个插件的作用有点玄乎,看样子是对每个chunk进行处理,看对于多个chunk中都有的某一些module,会直接把他们的reason设置为主要的入口chunk,而后把当前chunk中的module移除掉(话说这个事情不是应该Common来做吗)

然后移除所有空的模块,再就是移除重复的模块了(话说一直用set神他妈还会有重复的)

然后进行各种优化,比如出现的概率大的放到前面,这里还是做了module和chunk两种优化,也是有毛病,就像我们的react项目中可以知道react的使用次数最多,那么他就被放到了最钱前面,紧随其后的是echart等

HashedModuleIdsPlugin插件为我们的模块计算出它的id,默认是通过md5进行计算,解出来的是base64的,而且计算的参数也仅仅只是通过模块的libId进行hash,而这个libhash只是相对位置,连绝对的都不是,所以算下来这个东西能够当成单个文件的hash了

applyModuleId,到这里你可能会想,诶之前不是已经设置好每个元素的id了吗,为什么还要搞这么个函数专门处理,我们在上一个生成id的时候实际上得到的id是根据我们的设置进行了截断的,实际上拿到的hash碰撞的概率非常大,我们看看下面这个筛选的处理就可以知道,1885个模块里面竟然又3个重复的id,这种时候就要特殊处理了

执行sortItemsWithModuleIds依据id进行排序,不只是最外面的chunk,就连reason里的id也会被重新排序,也是蛮逗的,这里直接用的是id做比较并没有判断类型,也就是说把数字和字符串会混到一起,就算你是class也会拿valueOf出来比较,想想还是蛮刺激的,不过其实比较完成也没有太特殊的用途就这么随意一点也好

中间一些处理recordId的我忽略掉了

然后开始处理hash了,这里的hash具体使用了哪些参数和长度是多少呢

可以在此阶段添加hashSalt即噪声,给hash值添加一些特征

进入mainTemplate的处理函数中,添加了一些字符串参数和数字参数,并且调用了mainTemplate的hash插件,但是她们的执行过程并不是保证我们最后生成的文件中能够有结果的hash值,便于请求对应的资源文件,而是仅仅在hash的过程中添加了一些干扰的路径参数等

最终一轮hash下来,chunk会得到自己的renderHash,而compilation会得到一个针对编译过程的hash,这个hash就跟我们的所有资源扯上关联啦,所以每次都是新的

创建模块资源咯~

这些文章写的都有点水,相当于是阅读源码时候做的笔记了,看看图个乐子吧


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/8216232.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-14
下一篇 2023-04-14

发表评论

登录后才能评论

评论列表(0条)

保存