为会么要用webpack?

  1. 首先是编译loader:针对jsx,ts等的js通过babel编译。针对less,sass等的css编译.
  2. 文件打包:一般通过打包压缩ugliyJS
  3. 模块化:依赖,网络请示
    image.png
    webpack是一个前端资源动态加载/打包工具,会分析模块的依赖,并将模块根据指定规则生成静态资源,同一个文件的代码会打包成一个Bundle文件。

模块打包运行原理

  1. 读取webpack的配置参数
  2. 启动webpack,创建compiler对象并开始解析项目
  3. 从入口文件entry开始解析,并找到对应导入的依赖模块,递归分析,形成依赖关系树
  4. 对不同文件类型的依赖模块文件使用对应的loader进行编译,最终转为js文件
  5. 整个过程中webpack会通过发布订阅模式,向外抛出一些hooks,而webpack的插件会通过监听这些关键的事件节点,执行插件任务达到干预输出结果的目的。
    其中文件解析与构建是一个比较复杂的过程,在webpack源码中主要依赖于compilercompilation2个核心对象实现。
    compiler对象是一个全局单例,它负责把控整个webpack打包的构建流程,compilation对象是每一次构建的上下文对象,它包含了当次构建所需要的所有信息,每次热更新和重新构建compiler都会重新生成一个新的compilation对象,负责此次更新的构建过程。
    而每个模块间的依赖关系,则依赖于AST语法树,每个模块文件在loader解析完后,会通过acorn库生成模块代码的AST语法树,通过语法树就可以分析这个模块是否还有依赖的模块,进而继续循环执行下一个模块的编译解析。
    最终webpack打包出来的bundle文件是一个立即执行函数。

webpack配置,webpack.config.js

image.png

首先webpackjs代码,js是需要在运行环境下才能运行的,那我们的webpack就是在nodejs(后端服务器)中运行的。

配置开头的require,用的就是node的内置模块,require是运行webpack时调用.
为什么不用import是因为,import是编译时调用,是解构过程,它也是es6,需要转换成es5再执行,import会转码成require.
webpack的配置文件内容是不经过编译的。

loader

loader是用来编译处理源文件的,比如es6,ts,less等都要通过loader编译成浏览器识别的语言。

loader的执行顺序:从下往上,从右往左。
use:['style-loader','css-loader'];
loader可以链式调用,链中的每个loader都会对资源进行转换,第一个loader会将结果(被转换后的资源)传递给下一个loader的入参,最后的loader返回js;
loader的其它配置:
image.png

plugin

plugin主要是对webpack功能的扩展。
插件可以携带参数/选项,所以要在webpack配置中,向Plugin传入new实例。

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

plugins: [ 
    new HtmlWebpackPlugin({ title: '管理输出'}),//生成新的html文件,并把打包好的js文件引入
    new CleanWebpackPlugin(),//清理dist文件夹
]
 

plugin的机制基于事件流框架tapable,这个小型librarywebpack的一个核心工具,也用于以提供类似的插件接口,webpack中许多对象扩展自tapable类,这个类暴露taptapAsynctapPromise方法,使用这些方法,注入自定义的构建步骤,这些步骤将在整个编译过程中不同时机触发。(可以理解成一个生命周期,通过它在编译时期来执行方法);
image.png
compileruncompilation等都是变异的不同周期,不同的周期内部,又提供更加细分的hooks.
image.png
compilercompilation暴露的事件钩子总数超过30个,在特定的阶段钩入想要添加的自定义功能。

根据官方文档说明,一个自定义的plugin需要包含:

  • 一个js命名函数
  • 插件函数的prototype上要有一个apply方法
  • 指定一个绑定到webpack自身的事件钩子
  • 注册一个回调函数来处理webpack实例中的指定数据
  • 处理完后调用webpack提供的回调

SplitChunksPlugin分离包 小即是快
image.png

总结

打包过程:

  1. 从一个文件入口,基于代码文件中所有的importexportrequire构建依赖树
  2. 编译JS/CSS等模块
  3. 使用算法排序、重写、连接代码
  4. 优化。

开发环境的webpack:

  • 打包所有的代码
  • 启动webpack-dev-server托管打包好的代码
  • 启动websocket处理热更新HMR
    应用规模越大,启动和热更新代码越慢。即时启动了热更新,每次代码变更也要重新生产Bundle文件,再走一遍

Waxiangyu
670 声望30 粉丝