Webpack 记录,各种反复压缩操作,以后不要再来一遍了。
注意把项目结构留一留。
配置分析:
模块打包器,构建依赖关系图,打包成一个或多个 bundle。
- entry:入口。单入口或多入口、第三方库入口。
- output:输出目录及命名。
- loader:模块解析,在 module 中配置 rules。处理非 js 文件,将所有类型的文件转换为 webpack 能够处理的有效模块。
- mode:development/production。
- plugins:打包、优化、压缩等等等等。
webpack 内置模块: - webpack.optimize.OccurenceOrderPlugin:优化插件,优化 module id
- webpack.optimize.DedupePlugin:有些 JS 库有自己的依赖树,并且这些库可能有交叉依赖,DedupePlugin 可以找到他们删除重复依赖
- webpack.optimize.UglifyJsPlugin:代码丑化
- webpack.DefinePlugin:给代码注入全局标识符
- webpack.BannerPlugin:给代码添加 banner 信息
- webpack.ProvidePlugin:调用模块的别名
- webpack.NoErrorsPlugin:报错但不退出 webpack 进程
- webpack.ProgressPlugin:显示构建进度
其他常见模块: - :查看构建 bundle 的构成
- html-webpack-plugin:生成 html 文件
- copy-webpack-plugin:拷贝文件或者文件夹
- clean-webpack-plugin:清理文件或者文件夹(rimraf 模块)
- webpack-shell-plugin:给 shell 提供运行时机
- case-sensitive-paths-webpack-plugin: 路径大小写敏感问题
- friendly-errors-webpack-plugin:友好报错信息
- extract-text-webpack-plugin:将文本内容生成抽取成独立文件
使用 webpack 的站点中有三种代码类型: - 自己编写的源码
- 依赖的第三方 libary 或 vender 代码
- webpack 的 runtime 和 manifest:runtime 根据 manifest 中的映射数据来查询和解析模块
runtime 包含:浏览器运行时,webpack 用来连接模块化的应用程序的所有代码。在模块交互时,连接模块所需的加载和解析逻辑。包括浏览器中的已加载模块的连接,以及懒加载模块的执行逻辑。
manifest:当编译器(compiler)开始执行、解析和映射应用程序时,它会保留所有模块的详细要点。
构建流程:
- 解析 webpack 配置参数,合并 shell 传入和 webpack.config.js 文件里配置的参数,生成最后的配置结果
- 注册所有配置的插件,让插件监听 webpac 构建生命周期的事件节点,以便做出对应的反应
- 从配置的 entry 入口文件开始解析文件构建 AST 语法树,找出每个文件所依赖的文件,递归下去
- 在解析文件 递归的过程中根据文件类型和 loader 配置找出合适的 laoder 用来对文件进行转换
- 递归完后得到每个文件的最终结果,根据 entry 配置生成代码块 chunk
- 输出所有 chunk 到文件系统
缓存要点:
1、合理划分模块。在 entry 入口中,制定 vender、libs 等。
- 代码分割,一般引入第三方库更新频率低,利于缓存
2、提取频繁共用的公共模块。利用 commonsChunkPlugin 将公共的模块抽离出来,生成一个或多个依赖文件。通过 minchucks 指定最少依赖次数(为 infinity 表示不包含任何模块)。(在多页面/多入口很有优势,单入口无法抽离文件中的公共模块)
- 频繁模块的抽离,压缩代码体积
3、抽离清单。一般 manifest 打包在 vender 文件中,在 commonsChunkPlugin 中的 names 中增加 manifest(放在 libs 之前,可用其他名字代替)可以抽离出 manifest。为了减少请求,也可以使用 inline-manifest-webpack-plugin 配合 html-webpack-plugin 内联至 html 中 - 如果 webpack 打包生成的 hash 变了之后,manifest 会改变,则 vender 也会变化,而 vender 通常比较大。因此需要分离 manifest。
左图使用修改 booking.vue 前,右图修改 booking.vue 后
使用 inline-manifest-webpack-plugin 写入 html 后
4、稳定的 chunk id(webpack 内部对文件的引用)。默认的 chunk id 是 webpack 根据依赖的收集顺序递增的正整数。
当修改 app 或者增删文件时,chunk id 会变化导致许多模块(文件的 chunckhash 没有变化而 id 变了)的缓存不能使用,manifest(webpack 的 runtime 中包含 chunk id 及其对应的 chunckhash 对象)也改变了,我们需要 chunk id 最好稳定。
1)OccurrenceOrderPlugin:让 webpack 以依赖模块出现的次数决定 id 的值,次数越多 id 越小。缺点:但依赖变动大,chunk id 会大幅变动。
2)NamedModulesPlugin:将 chunk id 替换为相对路径。缺点:文件增大+filename 导致安全问题
3)HashedModuleIdsPlugin:NamedModulesPlugin 进阶,将路径进行 MD5 摘要。
左图使用 HashedModuleIdsPlugin 前,右图使用 HashedModuleIdsPlugin 后,booking.vue page
5、稳定的 hash 值。
- 【hash】:在 webpack 构建中会产生一个 compilation 对象,hash 是对该对象内的所有内容计算而来。当使用了 extract 时,由于其抽取的异步流程,有时即使没有改动,也会存在 hash 异动情况。
- 【chunkhash】:每一个 chunkhash 都根据自身的内容计算而来。
1)webpack-md5-hash:使 chunkhash 与该 chunk 内的代码相关联,让 chunck 与其依赖的 chunk id 无关(子改变与父无关)。缺点:当修改 app 时,app 的 chunk id 改变,因此 vender 中对应的 app 模块的 ID 改变,所以 vender 的 hash 理应改变(这时子与父有关)。但是由于 vender 实际包含模块没变,webpack-md5-hash 根据 chunk 内实际包含的模块生成的 chunckhash,因此 vender 的 hash 不会变,导致引入的 vender 是旧的。
2)webpack-chunk-hash
6、其他资源缓存
- Image/Fonts 的【hash】由 webpack/file-loader 计算。
- 提取 CSS(写在 js 中的 style 里的样式无法被抽离,仍打包在 js 中)的【contenthash】由 webpack/extract-text-webpack-plugin 计算。
其他问题:
- 无法抽离单入口多路由页面的公共模块组件,可以自己指定写死。
- 在不同的电脑下 chunkhash change
- module 的版本问题