# Webpack

# webpack作用

# 模块打包

可以将不同模块的文件打包整合在一起,并且保证它们之间的引用正确,执行有序。

# 编译兼容

通过webpack的Loader机制,不仅仅可以帮助我们对代码做polyfill,还可以编译转换诸如.less, .vue, .jsx这类在浏览器无法识别的格式文件,让我们在开发的时候可以使用新特性和新语法做开发,提高开发效率。

# 能力扩展

通过webpack的Plugin机制,我们在实现模块化打包和编译兼容的基础上,可以进一步实现诸如按需加载,代码压缩等一系列功能,帮助我们进一步提高自动化程度。

# 基本使用

# 拆分配置和merge

# 处理ES6

# 处理样式

# 处理图片

# 高级配置

# 多入口

  1. 在entry配置多个入口文件。

    image-20220419151200443

  2. output配置文件名

    image-20220419151316740

  3. 针对每个入口都创建一个HtmlWebpackPlugin

    image-20220419151510854

# 抽离并压缩css文件

  1. 配置css后缀文件的loader,使用MiniCssExtractPlugin

    image-20220419200002055

  2. 配置相关插件

    image-20220419200830490

# 抽离公共代码

  1. 在optimization中配置分割代码块

    image-20220420140904993

  2. 在HtmlWebpackPlugin中配置需要加载的chunks image-20220420140501341

# 异步加载JS(懒加载)

直接使用import语法即可(使用import语法引入,会为其单独生成一个chunk)

image-20220420142706558

# webpack打包原理

# 运行流程

  1. 读取webpack的配置参数
  2. 启动webpack,创建Compiler对象并开始解析项目
  3. 从入口文件(entry)开始解析,并且找到其导入的依赖模块,递归遍历分析,形成依赖关系树
  4. 对不同文件类型的依赖模块文件使用对应的Loader进行编译,最终转为Javascript文件
  5. 整个过程中webpack会通过发布订阅模式,向外抛出一些hooks,而webpack的插件即可通过监听这些关键的事件节点,执行插件任务进而达到干预输出结果的目的

# 具体原理

webpack主要依赖于compilercompilation两个核心对象实现文件的解析和构建。

compiler对象是一个全局单例,他负责把控整个webpack打包的构建流程。 compilation对象是每一次构建的上下文对象,它包含了当次构建所需要的所有信息,每次热更新和重新构建,compiler都会重新生成一个新的compilation对象,负责此次更新的构建过程。

而每个模块间的依赖关系,则依赖于AST语法树。每个模块文件在通过Loader解析完成之后,会通过acorn库生成模块代码的AST语法树,通过语法树就可以分析这个模块是否还有依赖的模块,进而继续循环执行下一个模块的编译解析。

# Babel

core-js 是除了处理「生成器」相关语法的兼容性集合

regenerator是处理「生成器」相关语法的兼容性集合

babel-polyfill是core-js和regenerator的集合

# loader和plugin区别

# Loader

  1. Loader本质就是JS一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。
  2. Loader在module.rules中配置,类型为数组,里面每一项都是一个对象。对象里面包括test(类型文件)、loader、option(参数)等属性
{
    test: /\.css$/,
    use: ['style-loader','css-loader']
},

# Plugin

  1. plugin就是一个webpack插件,它主要用来扩展webpack的功能的。在wepack运行的生命周期过程中会广播出很多事情,plugin可以监听这些事件从而调用webpack的api改变输出的结果。
  2. 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。
//webpack.config.js
module.exports = {
    mode: "development",
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                use: ['babel-loader'],
                exclude: /node_modules/ //排除 node_modules 目录
            }
        ]
    },
    plugins: [
        //数组 放着所有的webpack插件
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html', //打包后的文件名
            minify: {
                removeAttributeQuotes: false, //是否删除属性的双引号
                collapseWhitespace: false, //是否折叠空白
            },
            // hash: true //是否加上hash,默认是 false
        })
    ]
};

# 常用loader

  1. image-loader:加载并且压缩图片文件
  2. babel-loader:把ES6转换成ES5
  3. ts-loader:将TypeScript转成JavaScript
  4. sass-loader:将将SCSS/SASS代码转换成CSS
  5. css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
  6. style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS
  7. postcss-loader: 浏览器兼容性
  8. eslint-loader:通过ESLint检查JavaScript代码
  9. vue-loader:加载Vue单文件组件

# 常用的plugin

  1. mini-css-extract-plugin:分离样式文件,CSS 提取为独立文件,可以按需加载
  2. terser-webpack-plugin:压缩ES6代码
  3. web-webpack-plugin:可方便地为单页应用输出 HTML
  4. clean-webpack-plugin:目录清理
  5. webpack-dashboard:更好的展示相关打包信息
  6. webpack-merge:提取公共配置,减少重复配置代码
  7. size-plugin:监控资源体积变化,尽早发现问题
  8. webpack-bundle-analyzer:生成bundle的模块组成图,可以显示所占的体积
  9. html-webpack-plugin:创建入口html文件,并且把打包的内容引入HTML中。

# 各种区别

# module、chunk、bundle

# module

可以理解为各个源码文件,在Webpack中一切皆模块

# chunk

由多个模块合并而成的,如import() splitChunk

# bundle

最终输出的文件

# 热更新和自动刷新

# 热更新

只更新配置的部分,状态会保留。

# 自动刷新

整个网页都会刷新,状态会丢失,配置简单。

# file-loader和url-loader区别

# file-loader

file-loader将文件(图片、音频、字体等)解析为url,并将该文件复制到输出目录中。

# url-loader

url-loader可以识别图片的大小,然后把图片转换成base64,从而减少请求的次数,如果图片超过设定的范围,就还是用file-loader来处理。

# babel-runtime和babel-polyfill

# webpack如何实现懒加载

# 性能优化

# 优化构建速度

# 优化babel-loader

image-20220420150113409

# IgnorePlugin

忽略第三方包指定目录,让这些指定目录不要被打包进去

# noParse

该引入还是会引入,只是不参与loader或webpack的解析及打包

# happyPack多线程打包

  1. 在loader那里配置happypack

    image-20220420151415232

  2. 在plugin中配置HappyPack

    image-20220420151254789

# 使用ParallelUglifyPlugin多线程压缩优化JS

虽然Webpack内置了Uglify工具压缩JS,但是JS是单线程的,开启多线程压缩会更快。

image-20220420161928653

# 热更新

  1. 配置HotModuleReplacementPlugin

    image-20220420175358973

  2. 在plugins中配置插件

    image-20220420175459656

  3. 在devServer设置hot: true

  4. 配置需要热更新的模块

image-20220420181153462

# DllPlugin动态链接库

webpack已内置DllPlugin支持

# 先使用DllPlugin打包出dll文件
# 然后使用DllReferencePlugin使用dll文件
  • 先使用webpack-bundle-analyzer进行体积分析,然后再根据实际的情况进行相应的优化
  • 多进程/多实例构建:使用thread-loader
  • 缓存
    • babel缓存。cacheDirectory:true
    • 文件资源缓存。hash名
    • babel-loader 开启缓存
    • terser-webpack-plugin 开启缓存
  • 使用高版本的webpack

# 优化产出代码

# 小图片使用base64编码

使用base64编码,减少请求的次数

# bundle加hash

通过文件内容计算出hash,合理使用缓存

# 懒加载

# 提取公共代码

# IngorePlugin

# CDN加速

# Scope Hosting

# 优点
  1. 代码体积更小
  2. 创建函数作用域更少
  3. 代码可读性更好
# 配置方式

image-20220427212937657

# webpack热更新原理

服务端与浏览器之间维持着一个websocket。当资源发生变化的时候,服务端会向浏览器推送更新信息,并且带上更新的hash。浏览器根据这个hash与旧的资源对比,如果发现有差异就发起Ajax去获取更新的内容。

# Tree-Shaking

# 开启方式

webpack中,mode设置为“Production”就会自动开启。

Last Updated: 5/24/2022, 10:02:52 AM