wepback知识点总结

wepback知识点总结。

图片

1、webpack的基本配置

entry,output,mode

2、非js文件是怎么配置处理的

webpack 默认支持处理 js 文件,其他类型都处理不了,这里必须借助 Loader 来对不同类型的文件的进行处理。比如安装css-loader 来处理 CSS文件。

另一类是处理图片的loader。

3、webpack打包时候的一些优化方式

压缩文件(js\css)、去除无用的css、tree-shaking、include\exclude等。

optimization:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
chainConfig.optimization.splitChunks({
  maxInitialRequests: 6, // 最多打包出6个js文件 因为浏览器一次可最多发出6个请求
  cacheGroups: {
    react: {
      name: "react",
      test: /react|redux/,
      chunks: "all",
      priority: 1
    },
    antd: {
      name: "antd",
      test: /antd|rc-|@ant-design/,
      chunks: "all",
      priority: 2
    },
    antv: {
      name: "antv",
      test: /antv/,
      chunks: "all",
      priority: 3
    },
    monacoEditor: {
      name: "monaco-editor",
      test: /monaco-editor/,
      chunks: "all",
      priority: 4
    },
    // cytoscape: {
    //   name: "cytoscape",
    //   test: /cytoscape/,
    //   chunks: "all",
    //   priority: 5
    // },
    allVendors: {
      name: "all-vendors",
      test: /[\/]node_modules[\/]/,
      priority: -5,
      chunks: "all"
    },
    // ...chainConfig.optimization.get("splitChunks").cacheGroups
  }
});

4、为什么会用到Sourcemap

SourceMap 是一种映射关系,当项目运行后,如果出现错误,我们可以利用 SourceMap 反向定位到源码位置。

推荐使用:eval-cheap-module-source-map。

理由:

  • 本地开发首次打包慢点没关系,因为 eval 缓存的原因,rebuild 会很快
  • 开发中,我们每行代码不会写的太长,只需要定位到行就行,所以加上 cheap
  • 我们希望能够找到源代码的错误,而不是打包后的,所以需要加上 modele

5、webpack的作用

是一个打包工具,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(ES6、ES7、Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。

6、什么是loader

将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

Loader 的执行顺序是固定从后往前,即以下代码中按 css-loader –> style-loader 的顺序执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    // ...
    module: { 
    rules: [ // 转换规则
      {
        test: /\.(css|less|scss|sass)$/, //匹配所有的 css 文件
        use: [
          MiniCssExtractPlugin.loader,
          'style-loader',
          'css-loader', 
          'postcss-loader', 
          'sass-loader'
        ]
      },
      //...
  • 1、style-loader:就是将处理好的 css 通过 style 标签的形式添加到页面上。

相当于:

1
2
3
4
    const content = `${样式内容}` ;
    const style = document.createElement('style'); 
    style.innerHTML = content; 
    document.head.appendChild(style);
  • 2、css-loader:用来编译 CSS文件。
  • 3、postcss-loader:自动添加 CSS3 部分属性的浏览器前缀。
  • 4、less-loader
  • 5、sass-loader:node-sass 或 dart-sass
  • 6、file-loader:解决图片引入问题,并将图片 copy 到指定目录,默认为 dist
  • 7、url-loader 依赖 file-loader,当图片小于 limit 值的时候,会将图片转为 base64 编码,大于 limit 值的时候依然是使用 file-loader 进行拷贝;还可以处理字体。
  • 8、img-loader 压缩图片。

7、什么是plugin;他们在什么时候运行?

与 Loader 用于转换特定类型的文件不同,插件(Plugin)可以贯穿 Webpack 打包的生命周期,执行不同的任务。

  • html-webpack-plugin:可以将js 或者 css 文件自动引入到 Html 中。
  • clean-webpack-plugin: 将打包目录清空。
  • mini-css-extract-plugin: 将样式通过CSS 文件的形式引入到页面上。

8、编写自定义的plugin和loader

plugin:

  • 一个 JavaScript 命名函数或 JavaScript 类。
  • 在插件函数的 prototype 上定义一个 apply 方法。
  • 指定一个绑定到 webpack 自身的事件钩子。
  • 处理 webpack 内部实例的特定数据。
  • 功能完成后调用 webpack 提供的回调。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 一个 JavaScript 类
class MyExampleWebpackPlugin {
  // 在插件函数的 prototype 上定义一个 `apply` 方法,以 compiler 为参数。
  apply(compiler) {
    // 指定一个挂载到 webpack 自身的事件钩子。
    compiler.hooks.emit.tapAsync(
      'MyExampleWebpackPlugin',
      (compilation, callback) => {
        console.log('这是一个示例插件!');
        console.log(
          '这里表示了资源的单次构建的 `compilation` 对象:',
          compilation
        );

        // 用 webpack 提供的插件 API 处理构建过程
        compilation.addModule(/* ... */);

        callback();
      }
    );
  }
}

loader可参考:(https://ty0225.github.io/technology/2019/03/25/webpack4.0%E8%BF%9B%E9%98%B6/)

9、externals

不需要依赖包的组件,比如用CDN引入的库,可以用externals配置,去掉它的依赖递归查找。

10、缓存

webpack4的策略是,通过一些loader或plugin来解决。

  • babel-loader:

babel 在转译 js 过程中时间开销比价大,将 babel-loader 的执行结果缓存起来,重新打包的时候,直接读取缓存。

1
2
3
4
5
6
7
8
9
    // ...
    { 
        loader: 'babel-loader', 
        options: { 
            cacheDirectory: 
            true // 启用缓存 
        } 
    },
    // ...
  • cache-loader:

缓存一些性能开销比较大的 loader 的处理结果。

  • hard-source-webpack-plugin:

为模块提供了中间缓存,重复构建时间大约可以减少 80%,但是在 webpack5 中已经内置了模块缓存,不需要再使用此插件。

  • webpack5内置缓存:

就是编译缓存。

1、持久化的是Webpack运行时存在于内存中的那些缓存,不是loader的产物,更不是dll。

2、持久化后存放到哪里:

  • IdleFileCachePlugin:持久化到本地磁盘
  • MemoryCachePlugin:持久化到内存

Webpack5的内置缓存方案无论从性能上还是安全性上都要好于cache-loade。

  • 性能上:由于所以被webpack处理的模块都会被缓存,缓存的覆盖率要高的多;
    1. 安全上:由于cache-loader使用了基于mtime的缓存验证机制(参考:juejin.cn/post/684490…),导致在CI环境中缓存经常会失效,但是Webpack5改用了基于文件内容etag的缓存验证机制,解决了这个问题。

参考文档:

https://juejin.cn/post/6847902218570432520

11、Tree-shaking

  • 作用:是剔除没有使用的代码,以降低包的体积。

利用 ES Module 可以进行静态分析的特点来检测模块内容的导出、导入以及被使用的情况,保留 Live Code 消除不会被执行和没有副作用(Side Effect) 的 Dead Code,即 DCE 过程。

  • 主要原理:去除dead code(无效代码:return后的语句、不会执行的if判断以及没有被引用的function等) 首先是根据ES module的静态化特点,代码在编译的过程中是确定的(Common js是不确定的,因此只有遵循ES Module规范的项目可以使用tree-shaking),和运行时的状态无关,可以进行可靠的静态分析。AST语法树是进行静态分析的基础,在编译过程中,代码会先被转义成语法树,之后就可以做一些dead code的判断。具体的操作就是扫描(递归遍历)AST语法树,找那些不会被调用和执行到的代码节点,将这些节点完全去除(babe转换l也是根据AST语法树)。(https://astexplorer.net/)

  • 与uglify-js的关系:???

12、Webpack运行的大致流程

1、先处理整个配置

2、注册好所有插件

3、从entry开始运行loader,把对应的文件转成module(webpack整个运行过程中是对这些模块做处理)

4、中间过程处理文件(splitChunk、treeShaking、组织代码结构,抽取公共代码,压缩代码之类的操作)

5、把所有文件按output输出

6、在整个流程中插件会按照注册的生命周期去执行

13、脚手架中的webpack

Muji提供了一套webpack的统一方案,通过引入webpack-chain的包,创建其实例并传递给特定配置function:chainWebpack。这样在每个项目里面就可以通过定义自己的chainWebpack进行个性化配置,也可以覆盖脚手架里的默认配置。(查看muji的webpack配置功能) muji默认的devtool模式:cheap-module-eval-source-map

14、webpack热加载主要流程

1.首先 webpack-dev-server 会建立一个服务器,并且和浏览器建立 websocket 通信。

2.服务器监听文件变化,当文件变化的时候,会重新打包相应的 chunk,然后向浏览器发射 hash 和 ok 事件,通知浏览器对应的 chunkid 等信息。

3.浏览器监听 hash 和 ok 事件,再接受信息之后,通过 jsonp 向服务端请求对应的热更新代码。

4.最后浏览器把 jsonp 获得的代码注入到 html 的 head 里面去执行,从而实现了对应的模块替换。

参考文档:

https://mp.weixin.qq.com/s/TNXO2ifPymaTxIqzBAmkSQ

https://juejin.cn/post/6955383260759195678

https://juejin.cn/post/6844904030649614349