读书笔记 - Webpack实战

Webpack

Webpack.png

1. Webpack简介

为什么需要Webpack

  • Webpack默认支持多种模块标准,包括AMD、CommonJS以及最新的ES6模块
  • Webpack有完备的代码分割解决方案
  • Webpack可以处理各种类型的资源
  • Webpack有庞大的社区支持

安装

  • npm install webpack webpack-cli --save-dev

打包第一个应用

  • 注意点: 直接使用Webpack开发和使用webpack-dev-server又一个很大的区别,前者每次都会生成budnle.js,而weboack-dev-server只会将打包结果放在内存中,并不会写入实际的bunde.js

2. 模块打包

CommonJS与ES6 Module的区别

    1. CommonJS 与ES6 Module最本质的区别在于前者对模块依赖的解决是动态的,而后者是静态的。在这里动态的含义是,模块依赖关系的建立发生在代码运行阶段,而静态则是模块依赖关系的建立发生在代码编译阶段。
    1. require的模块路径可以动态指定,支持传入一个表达式,我们甚至可以通过if语句判断是否加载某个模块,因此,在CommonJS模块被执行钱,并没有办法明确依赖关系,模块的导入、导出发生在代码的运行阶段;ES6 Module的导入、导出语句都是声明式的,它不支持导入的路径是一个表达式,并且导入导出语句必须位于模块的顶层作用域,因此ES6 Module是一种静态的模块结构,在ES6代码的编译阶段就可以分析出模块的依赖关系
  • ES6 Modue的优势

    • 死代码检测和排除
    • 模块变量类型检查
    • 编译器优化
  • 在导入一个模块时,对于CommonJS来说获取的是一份导出值的拷贝;而在ES6 Module中则是值的动态映射,并且这个值只是可读的。

模块打包原理

  • bundle结构

    • 最外层立即执行函数,它用来包裹整个bundle,并构成自身的作用域
    • installedModules对象。每个模块只在第一次被加载的时候执行,之后其导出值就被存储到这个对象里面,当再次被加载的时候直接从这里取值,而不会重新执行。
    • webpack_require函数。对模块加载的实现,唉浏览器中可以通过调用webpack_require(module_id)来完成模块的导入。
    • modules对象。工程中所有产生了依赖关系的模块都会以key-value的形式放在这里。key可以理解为一个陌路爱的id,由数字活着一个很短的hash字符串构成;value则是又一个匿名函数包裹的模块实体,匿名函数的参数则赋予了每个模块导出和导入的能力
  • bundle执行

    • 最外层的匿名函数中会初始化浏览器执行环境,包括定义installedModules对象、webpack_require函数等,为模块的加载和执行做一些准备。
    • 加载入口模块。
    • 执行模块代码。如果执行到了module.exports则记录下陌路爱的导出值;如果中间遇到require函数(准确地说是webpack_require),则会暂时交出执行权,进入webpack_require函数体内进行加载其他模块的逻辑。
    • webpack_require中会判断即将加载的模块是否存在与installedModules中。如果存在则直接取值,否则回到上述步骤,执行该模块的代码来获取导出值。
    • 所有依赖的模块都已经执行完毕,最后执行权又回到入口模块。

3. 资源输入输出

配置资源入口

  • context

    • 资源路口的标识前缀,在配置时要求必须使用绝对路径的形式
    • 配置context的主要目的时让entry的编写更加简洁。context可以省略,默认值为当前工程的根目录。
  • entry

    • 注意点:当一个bundle大于250kb时(压缩前)会认为这个bundle已经过大了,会在打包时发生警告。

      • 提取vendor
    1. 确定了入口模块的位置,告诉webpack从哪里开始打包。 2. 定义chunk name。如果工程只有一个入口,那么默认其chunk name为main,如果工程有多个入口,我们需要为每个入口定义chunk name,来作为chunk的唯一标识。

配置资源出口

  • filenam

    • 【hash】:指代webapck此次打包所有资源生成的hash

    • 【chunkhash】: 指代当前chunk内容的hash

    • 【id】:指代当前chunk的id

    • 【query】: 指代filename配置项的query

    • 上述变量主要有两种作用

      • 控制客户端华缓存
      • 当有多个chunk存在时对不同的chunk进行区分。如【chunk】、【chunkhash】、【id】,它们对于每个chunk来说都是不同的。
  • path

    • 指定资源输出位置,要求值必须为绝对路径
  • publicPath

    • 与path的差异

      • 从功能上来说,path用来指定资源输出的位置,而publicPath则用来指定资源请求的位置。

        • 输出位置: 打包完成后资源产生的位置
        • 请求位置: 由JS活着CSS所请求的间接资源路径
    • HTML

    • Host

    • CDN相关

4. 预处理器

loader概述

  • 每个loader本质上都是一个函数

    • webpack4之前,函数的输入和输出都是字符串
    • webpack4之后,loader也同时支持抽象语法树AST的传递,以减少代码的重复解析。

loader的配置

  • 常用配置

    • test
    • use
    • options
  • 额外配置

    • exclude与include

    • resource与issuer

      • 在webpack中哦你,我们认为被加载模块是resource,而加载者是issuer。
    • enforce

常用loader介绍

  • babel-loader

    • babel-loader:是babel与webpack协同工作的模块

    • @babel/core:babel编译器的核心模块

    • @babel/preset-env:babel官方推荐的预置器,可根据用户设置的目标环境自动添加所需的插件和补丁来编译ES6+代码

    • 注意点

      • 由于babel-loader通常属于对所有JS后缀文件设置的规则,所以需要在exclude中添加node_modules,否则会令babel-loader编译其中所有的模块,这将严重拖慢打包的速度,并且有可能改变第三方模块的原有行为。
      • 对于babel-loader本身我们添加了cacheDirectory配置项,它会启用缓存机制,在重复打包未改变过的模块时防止二次编译,这个值也可以为true
      • 由于@babe/preset-env会将ES6 Module转化为CommonJS的形式,这回导致Webpack中的tree-shaking特性失效,将@babel/prset-env的modules配置项设置为false会禁用模块语句的转化,而将ES6 Module的语法交给Webpack本身处理
      • babel-loader支持从.babelrc文件中读取babel配置,因此可以将presets和plugins从Webpack配置文件中提取出来,也能达到相同的效果
  • ts-loader

  • html-loader

    • 用于将HTML文件格式化为字符串并进行格式化,这使得我们可以把一个HTML片段通过JS加载进来
  • handlebars-loader

    • 用于处理handlebars模版
  • file-loader

    • 用于打包摁键类型的资源,并返回其publicPath
  • url-loader

    • 与file-loader作用类似,唯一的不同在于用户可以设置一个文件大小的阈值,当大于该阈值时与file-loader一样放回publicPath,而小于则放回文件的base64形式编码
  • vue-loader

自定义loader

5. 样式处理

分离样式文件

  • extract-text-webpack-plugin

  • 多样式文件处理

  • mini-css-extract-plugin

  • extract-text-webpack-plugin 与 mini-css-extract-plugin的差异点

    • loader规则设置的形式不同,并且mini-css-extract-plugin支持配置publicPath,用来指定异步CSS的加载路径
    • 不需要shezhifallback
    • 在plugins设置中,除了指定同步加载的CSS资源名,还需要指定异步加载的CSS资源名

样式预处理

  • sass和scss
  • less

PostCss

  • PostCSS和Webpack
  • 自动前缀
  • stylelint
  • CSSNext

Css Module

10. 更多JavaScript打包工具

Rollup

Parcel

打包工具发展趋势

  • 子主题 1

9. 开发环境调优

Webpack开发效率插件

模块热替换

8. 打包优化

HappyPack

减少打包作用域

动态链接库与DllPlugin

tree shaking

7. 生产环境配置

环境配置的封装

开启production模式

环境变量

source map

资源压缩

缓存

6. 代码片段

通过入口划分代码

CommonsChunkPlugin

  • 使用commonschunkplugin的收益

    • 合理分片后的代码可以更有效地利用客户端缓存
    • 开发过程中减少了重复模块打包,可以提升开发速度
    • 减少整体资源体积
  • 配置

    • name:用于指定公共chunk的名字

    • filename:提取后的资源文件名

    • chunk: 设置提取范围

    • 设置提取规则

      • 数字
      • Infinity
      • 函数
  • 设置长缓存

    • 注意️:manifest的CommonsChunkPlugin必须出现在最后,否则Webpack将无法正常提取模块
  • 不足

    • 一个CommonsChunkPlugin只能提取一个vendor
    • manfifest实际上会使浏览器多加载一个资源,这对于页面渲染速度是不友好的
    • 由于内部设计缺陷,CommonChunkPlugin在提取公共模块的时候会破坏原有Chunk中模块的依赖关系,导致难以进行更多的优化。

optimization SplitChunks

  • 与CommonChunkPlugin的不同

    • 使用optimization.splitChunks代替额CommonsChunkPlugin,并指定了chunks值为all,这个配置项的含义是,SplitChunks将会对所有的chunk生效(默认只对异步生效)
    • mode是webpack4中新增的配置项,可以针对当前是开发环境还是生产环境自动添加对应的一些Webpack配置
  • 默认情形下的提取条件

    • 提取后的chunk可被共享或来自node_modules目录
    • 提取后的js代码体积大于30KB,css chunk体积大于50kb
    • 在按需加载过程中,并行请求的资源最大值小于等于5
    • 在首次加载时,并行请求的资源数最大值小于等于3
  • 配置

    • 匹配模式
    • 匹配条件
    • 命名
    • cacheGroups

资源异步加载

  • 资源异步加载主要解决的问题是,当模块数量过多、资源体积过大时,可以把一些暂时使用不到的模块延迟加载。这样使页面初次渲染的时候用户下载的资源尽可能小,后续的模块等到恰当的时机再去触发加载。因此一般也把这种方法叫作按需加载

你可能感兴趣的:(读书笔记 - Webpack实战)