webpack

webpack 的作用:将前端代码模块编译打包成浏览器可以识别的 html + css + js

1. 有哪些常用的 loader

  • file-loader: 处理文件的 loader,处理文件导入地址并替换成其访问地址,并把文件输出到相应位置
  • babel-loader: 将 es6 转 es5
  • sass-loader: 将 sass 转 css
  • css-loader: 处理样式间的相互引用
  • ts-loader: 处理 TS 文件
  • vue-loader: 处理 .vue 文件
    ….

loader 的作用就是用于处理源文件代码,将它们转换成 webpack 可处理的模块,处理源码文件时,针对不同的源码模块使用 不同的 loader 处理

loader 的执行顺序是从右往左,从下往上,

modules: {
rules: [{
use: [
‘style-loader’
‘css-loader’, ‘postcss-loader’, ‘sass-loader’]
}]
}

2.常见的 Plugin

  • html-webpack-plugin: dist 下生成 html 文件,依赖于 html-loader
  • clean-webpack-plugin: 清除目录文件
  • mini-css-extract-plugin: 分离样式,提取css 文件,按需加载
  • webpack-bundle-analyzer: webpack打包分析插件
    ….

3.loader 和 plugin 间的区别

loader 是一个文件转换器,因为 webpack 只能识别 js 和 json 文件,所以其他类型的文件需要通过 loader 进行转换
比如: a.scss 转 b.css, 单纯的就是一个 文件转换的过程
loader 只运行在打包文件前

plugin 用于扩展 webpack 的功能,用于执行任意类型的任务,所有 loader 解决不了的事都可以使用 plugin 来解决。如:代码分割、代码压缩
plugin 在整个项目编译周期都起作用

4.plugin 的组成部分

  • plugin 本质是一个 node 模块,这个模块到处一个 js 类
  • 它的原型需要定义一个 apply 方法
  • 通过 compiler 来获取 webpack 内部钩子,获取打包阶段的各个流程。webpack 的内部钩子 分为 异步 构字 和同步构子,异步钩子需要执行对应回调
  • 通过 compilation 操作 webpack 内部实例特定的数据

webpack 和 gulp 的不同

  • webpack 基于入口,会自动解析入口所需加载的所有资源文件,用不同的loader 来处理不同的文件

  • gulp 是基于任务和流的,找到一个文件模块 对其做一系列的链式操作,更新流上的数据,整条链式操作构成了一个任务,多个任务就构成了web 的构建流程

  • gulp 需要将整个构建 拆成多个 task 并合理控制所有的 task 的调用关系

  • webpack 只需找到入口,并且清楚对不同资源应用什么 loader 进行加工处理

  • gulp 常见 api: gulp.src, gulp.dest, gulp.pipe, gulp.watch 等

npm、yarn、pnpm

1. npm 3.0之前

在 npm 3.0 之前,安装项目的 node_modules 包,会出现嵌套结构

1
2
3
4
5
6
7
8
9
10
11
12
13
node_modules
|--- foo
|-- index.js
|-- package.json
|-- node_modules
|-- bar
|-- index.js
|--- zoo
|-- index.js
|-- package.json
|-- node_modules
|-- bar
|-- index.js

这种嵌套结构会出现 2 个问题

  1. 层级嵌套太深,导致文件路径过长
  2. 重复安装包,导致项目体积变大

为了解决这些问题,于是 yarn 横空出世

yarn

yarn采用 扁平化依赖项来解决 npm 的问题

扁平化依赖项就是将所有依赖铺平,放在同一级的依赖目录下

1
2
3
4
5
6
7
8
node_modules
|-- foo
|-- index
|-- bar
|-- index
|-- zoo
|-- index
...

在这种层级依赖的管理下, node_modules 中不会有层级深的情况,并且在安装依赖时,会先查找当前 node_modules 中是否有这个包,所有也解决了重复安装包 体积变大的问题。
解决了 npm 3.0 之前的问题,后续npm 也延用了 yarn 的方案。

但同时引进了新的问题 – 幽灵依赖

幽灵依赖依赖

幽灵依赖指的是:当前项目中的package.json 并没有该依赖,在代码中确可以引用。
这个原因是因为 npm 包被铺平了,依赖中的依赖也被安装了,所以在当前项目 package.json 没有声明该依赖也可以引用。

pnpm

pnpm 中解决了幽灵依赖的问题。
使用 pnpm 管理项目依赖,pnpm 不允许安装 package.json 中没有声明的依赖。

同时 pnpm 还做了另一个优化,使用 软链接和硬链接 来管理依赖,减少了磁盘空间。

什么是软链接

软链接: 相当于一个符号链接,指向目标文件地址,类似 window 电脑的快捷方式。
修改软链接,不会影响到目标文件

什么是硬链接

硬链接:链接符号存储了引用地址,类似 js 中的对象引用。
修改硬链接的内容,引用的目标文件会受到影响

1
2
3
4
5
6
const a = {
age: 1
}
const b = a

b.age = 20

pnpm 原理

根据软硬链接实现的
使用 pnpm 安装依赖时,在 node_modules 中会出现一个.pnpm 的文件和其他依赖文件

1
2
3
4
node_modules
|-- .pnpm/
|-- element/
|-- and

此时,依赖文件 如 element 中实际是一个软链接,指向了 .pnpm 中的 element
即 真实路径是 .pnpm/element.3.2.1/node_modules/element
.pnpm/<name>@<version>/node_modules</name>

在由 pnpm/@/node_modules 硬链接到 .pnpm/store 中去

所以 pnpm 通过这种方式 不仅解决了幽灵依赖的问题,还减少了磁盘空间,下载速度快。

CSS 预处理器

CSS 预处理器本质是为 CSS 增加一些可编程的特性,使 CSS 更加强大。

  1. postcss
    提供了可以用 JS 代码来处理 CSS,负责把 CSS 代码解析成 AST,再由插件对 AST 进行处理,插件可以实现多样化,如:支持变量和混入,增加浏览器前缀等

    postcss 的作用

    • 将 css 解析为 JS 可操作的 AST
    • 调用差距处理 AST 并等到结果

postcss 一般配合 构建工具使用
常用的有:
auto prefixer
postcss-px-to-viewport
cassnano 压缩css 等

  1. sass 在完全兼容 css 的前提下,提供变量、嵌套、混合 自定义函数等编程能力,less 同理

  2. sass 和 less 的区别

    • sass 和 less 在语法上有些共性,如:嵌套规则、运算、作用域等
    • 主要的不同在于它们的实现方式
      less 基于 js, sass 基于 ruby
      变量的区别: less 用 @, sass 用 $
      sass 支持条件语句 if{} else{} for{},less 不支持