webpack常见的plugin和loader以及webpack打包优化和原理解析

具体webpack的配置,戳这里

常见的loader和plugin

1、loader

  • css-loader:解析css文件中的@import和url语句,处理css-modules,并将结果作为一个js模块返回
  • style-loader:将css-loader解析后的内容以style标签的方式插入DOM树中
  • less-loader:将less编译为css,常搭配style-loader使用
  • sass-loader:将sass编译为css,常搭配style-loader使用

将 css-loader、style-loader 和 less-loader 链式调用,可以把所有样式立即应用于 DOM。

2、plugin

  • html-webpack-plugin:可以根据模板自动生成html代码,并自动引用css和js文件
  • HotModuleReplacementPlugin:热更新
  • compression-webpack-plugin :生产环境可采用gzip压缩JS和CSS
  • happypack:通过多进程模型,来加速代码构建

前提

首先我们得了解
webpack常见的plugin和loader以及webpack打包优化和原理解析_第1张图片

打包流程

1、我们打包的时候,会先合并 Webpack config 文件和命令行参数,合并为options
2、将 options 传入Compiler构造方法,生成compiler 实例,并实例化了 Compiler上的 Hooks
3、compiler 对象执行run方法,并自动触发beforeRunrunbeforeCompilecompile 等关键 Hooks。
4、调用 Compilation构造方法创建 compilation对象,compilation负责管理所有模块和对应的依赖,创建完成后触发 make Hook
5、执行compilation.addEntry() 方法,addEntry 用于分析所有入口文件,逐级递归解析,调用 NormalModuleFactory 方法,为每个依赖生成一个 Module 实例,并在执行过程中触发 beforeResolveresolverafterResolvemodule等关键 Hooks
6、将第 5 步中生成的 Module 实例作为入参,执行 Compilation.addModule()Compilation.buildModule() 方法递归创建模块对象和依赖模块对象。
7、调用seal方法生成代码,整理输出主文件和 chunk,并最终输出。

优化

1. 缩小文件的搜索范围
  1. 优化loader配置:尽量让少的文件被loader处理
  • test:正则匹配规则
  • include:包括需转换的文件目录
  • exclude:除去该目录下的文件,其余都需要被转换
    webpack常见的plugin和loader以及webpack打包优化和原理解析_第2张图片
  1. 优化resolve.modules配置【找到所有的模块包】
  • 使用绝对路径去寻找模块
    在这里插入图片描述
    webpack常见的plugin和loader以及webpack打包优化和原理解析_第3张图片
  1. 优化resolve.mainFields配置【指定某个模块下package.json的入口文件】
  • 当taget属性为webworkser或web时,该字段的默认值为:
module.exports = {
  resolve: {
    mainFields: ['browser', 'module', 'main']
  }
};
  • 当target属性为node或其他环境时,该字段默认值为:
module.exports = {
  resolve: {
    mainFields: ['module', 'main']
  }
};

为了减少搜索步骤,在明确第三方模块的入口文件描述字段时,我们可以将它设置得尽
量少。 由于大多数第三方模块都采用 main 宇段去描述入口文件的位置

resolve: {
	mainFields: ['main'],
}
  1. 优化resolve.alias配置
    起别名来配置模块的入口地址,跳过递归解析文件的操作,比如react有两套代码,一个是已经打包好的react.min.js,另一个是common.js下所有的模块文件,以react.js为入口文件,在我们使用时,可以直接将文件入口配置到react.min.js,省去递归的过程。
    webpack常见的plugin和loader以及webpack打包优化和原理解析_第4张图片
  2. 优化 resolve.extensions 配置
    在导入文件没有后缀名时,webpack会自动添加后缀名去查找文件。
resolve: {
	extensions: ['js', 'jsx','json'],
}

比如 require(’./data’),webpack会先去寻找data.js,如果美哟查找到,再去寻找data.jsx,再没有找到data.json后就会报错,没有该模块。
6. 优化 module.noParse 配置
让webpack忽略没有采用模块化的文件进行递归处理,提高构建性能。
webpack常见的plugin和loader以及webpack打包优化和原理解析_第5张图片

2. 使用自动刷新
  1. 文件监听
    原理
  • 定时获取文件的最后编辑时间,每次都存下最新的最后编辑时间,如果当前获取的和最后一次编辑的时间不一致就认为文件发生了变化,watchOptions.poll用于定义检查周期,也就是每秒检查多少次。
  • 当发现文件已经发生了变化以后并不会立刻告诉监听者,而是先缓存起来,手机一段时间后,watchOptions.aggregateTimeout配置等待时间。目的是编辑代码的过程中高频输入文字,导致文件变化一直发生,每次重新构建就会卡死。
  • 对于多个文件来说,其原理相似,对列表中的每个文件都会定时检查。在默认情况下,webpack会从entry配置的文件出发,递归解析出entry依赖的文件,将所有文件都加入监听列表中。
    优化
  • 不监听第三方模块,只监听自己建立的源码文件
watchoption: {
	ignored: /node_modules/,
}
  • watchOption.aggregateTimeout的值越大性能越好,降低重构频率
  • watchOption.poll的值越小越好,降低检查的频率
  1. 自动刷新浏览器
    webpack模块负责监听文件,webpack-dev-server负责刷新浏览器。

  2. 开启模块热替换
    原理

3. 压缩代码
4. 提取公共代码

将多个页面的公共代码抽离为单独的文件,加入用户访问了某网站中的一个网页,那么访问其他网页的概率将非常大,在用户第一次访问后,这些页面的公共代码就会被浏览器缓存起来,在用户切换到其他页面时,就不会再重新加载存放公共代码的文件,而是从缓存中获取。

优点:

  • 减少网络的传输流量,降低服务器的成本
  • 虽然用户在第一次打开网页的速度得不到优化,但之后访问其他页面的速度将大大提升

webpack常见的plugin和loader以及webpack打包优化和原理解析_第6张图片

  1. webpack的配置文件中加入,使用CommonsChunkPlugin插件
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonChunkPlugin');
new CommonsChunkPlugin({
    //从哪些chunk中提取
    chunk: ['a', 'b'],
    //提取后形成一个新的chunk
    name: 'common'
});
  1. 需要自己手动写一个chunk,例如写base.js来描述依赖的模块。内容是所有页面都依赖的基础库
  2. 修改webpack配置文件,在Entry中加入base
  3. 为了从common中提取base也包含的内容,配置webpack
new CommonsChunkPlugin({
    //从哪些chunk中提取
    chunk: ['common', 'base'],
    //提取后形成一个新的chunk
    name: 'base'
});

webpack常见的plugin和loader以及webpack打包优化和原理解析_第7张图片
引入文件是应该是
在这里插入图片描述

5. 分割代码以按需加载

用户当前需要什么就只加载这个功能对应的代码。

1)将整个网站划分为一个个小功能,再按照每个功能的相关程度将它们分为几类。
2)将每一类合并为一个chunk,按需加载对应的chunk
3)不要按需加载用户首次打开网站时需要看到的画面所对应的功能将其放到执行入口所在的chunk中,以减少用户能感知的网页加载时间
4)对于不依赖大量代码的功能点,例如依赖Char.js去画图表,可再去对齐进行按需加载。
被分割出去的代码加载需要在一定的时机去触发,即当用户操作到了或者即将操作到对应的功能时再去加载对应的代码。被分割出去的代码的加载时机需要开发者根据网页的需求去确定。由于被分割出去的代码按需加载的过程也需要耗时,所以可以预估用户接下来可能会进行的操作,并提前加载对应的代码,让用户感受不到网络的加载。
例如在react-router中使用按需加载:
webpack常见的plugin和loader以及webpack打包优化和原理解析_第8张图片
webpack常见的plugin和loader以及webpack打包优化和原理解析_第9张图片

6. HappyPack

由于有大量文件需要解析和处理,所以构建是文件读写和计算密集型的操作, 特别是当章优化文件数量变多后, Webpack 构建慢的问题会显得更为严重。运行在 node. 之上的 Webpack 是单线程模型的,也就是说 Webpack 需要一个一个地处理任务,不能同时处理多个任务。
happy能够让Webpack做到这一点,它将任务分解给多个子进程去并发执行,子进程处理后将结果返回给主进程。
webpack常见的plugin和loader以及webpack打包优化和原理解析_第10张图片
原理


原理

运行机制

下图是内部的运行机制
webpack常见的plugin和loader以及webpack打包优化和原理解析_第11张图片

模块解释:

Compiler:包含了所有webpack的所有配置信息,包含option|loaders|plugins,该对象有一个方法run,执行该方法开始编译,全局只有一个
Compilation:只要文件被修改,便有compilation被创建,包含当前模块的资源、编译生成资源、变化文件

流程:

webpack常见的plugin和loader以及webpack打包优化和原理解析_第12张图片

为什么经webpack打包后的文件可以直接在浏览器中运行?

原来一个独立的模块文件被合并到了一个个单独的bundle.js文件中,浏览器不能像node快速加载本地文件,所以就将所有的模块放在一个数组中,执行一次网络请求。被加载过的文件不会执行第二次,执行结果会缓存在内存中。
还需要了解_webpack_require_函数,定义在浏览器中执行的加载函数(模拟node.jsrequire

为什么运行在node(遵循CommonJs)的环境,但webpack引入模块可以使用es6的import xxx from 'xxx'呢?

webpack内部的babel可以将es6的语法转换为CommonJs的语法。

你可能感兴趣的:(前端小知识,webpack,原理)