ArthurWangCN / notepad

reading notepad
0 stars 2 forks source link

webpack篇 #43

Open ArthurWangCN opened 2 years ago

ArthurWangCN commented 2 years ago

loader

webpack 默认支持处理 JS 与 JSON 文件,其他类型都处理不了,这里必须借助 Loader 来对不同类型的文件的进行处理。

Loader 就是将 Webpack 不认识的内容转化为认识的内容

如 安装 css-loader 来处理 CSS

plugins

如果我想打包后的资源文件,例如:js 或者 css 文件可以自动引入到 Html 中,就需要使用插件 html-webpack-plugin

ArthurWangCN commented 2 years ago

Webpack 配置中用过哪些 Loader ?都有什么作用?

webpack做的事情,仅仅是分析出各种模块的依赖关系,然后形成资源列表,最终打包生成到指定的文件中。 更多的功能需要借助loaders和plugins完成。比如说:在代码中有一张图片需要进行打包,webpack可以把图片读出来,但是不能将图片当做js代码来读,所以需要一个加载器loader来帮助我们把图片的二进制数据转变为js代码,loader的作用说白了就是将一种形式的代码通过逻辑转变成另一种形式的代码,转换后的代码webpack就能识别了。

Loader 就是将 Webpack 不认识的内容转化为认识的内容

常见的loader:

示例:

const config = {
  // ...
  module: { 
    rules: [
      {
        test: /\.css$/, //匹配所有的 css 文件
        use: ['style-loader','css-loader', 'postcss-loader']
      }
    ]
  },
  // ...
}

由示例得出,loader 支持链式传递,从右向左取值/执行

ArthurWangCN commented 2 years ago

Webpack 配置中用过哪些 Plugin ?都有什么作用?

ArthurWangCN commented 2 years ago

Loader 和 Plugin 有什么区别?

  1. 两者都是为了扩展webpack的功能。loader它只专注于转化文件(transform)这一个领域,完成压缩,打包,语言翻译; 而plugin不仅只局限在打包,资源的加载上,还可以打包优化和压缩,重新定义环境变量等
  2. loader运行在打包文件之前(loader为在模块加载时的预处理文件);plugins在整个编译周期都起作用
  3. 一个loader的职责是单一的,只需要完成一种转换。一个loader其实就是一个Node.js模块。当需要调用多个loader去转换一个文件时,每个loader会链式的顺序执行
  4. 在webpack运行的生命周期中会广播出许多事件,plugin会监听这些事件,在合适的时机通过webpack提供的API改变输出结果
ArthurWangCN commented 2 years ago

如何编写 Loader ? 介绍一下思路?

https://blog.csdn.net/Niall_Tonshall/article/details/123082976

ArthurWangCN commented 2 years ago

如何编写 Plugin ? 介绍一下思路?

ArthurWangCN commented 2 years ago

Webpack optimize 有配置过吗?可以简单说说吗?

ArthurWangCN commented 2 years ago

Webpack 层面如何性能优化?

ArthurWangCN commented 2 years ago

Webpack 打包流程是怎样的?

ArthurWangCN commented 2 years ago

tree-shaking 实现原理是怎样的?

功能:移除 JavaScript 上下文中未引用的代码。

CommonJS规范无法确定在实际运行前需要或者不需要某些模块,所以CommonJS不适合tree-shaking机制。

在JavaScript模块化方案中,只有ES6的模块方案:import()引入模块的方式采用静态导入,可以采用一次导入所以的依赖包再根据条件判断的方式,获取不需要的包,然后执行删除操作。

Tree-shaking的实现原理

利用ES6模块特性:

代码删除:

实现原理可以简单的概况:

ArthurWangCN commented 2 years ago

Webpack 热更新(HMR)是如何实现?

ArthurWangCN commented 2 years ago

Webpack 打包中 Babel 插件是如何工作的?

ArthurWangCN commented 2 years ago

Webpack 和 Rollup 有什么相同点与不同点?

他们都是JavaScript模块构建打包工具。

特性:

资源:

webpack 相对来说拥有更大的社区支持,资源更加齐全,文档更加完整,有更完整的插件库,如热更新及web-server等。

结论:

Webpack对于代码分割和静态资源导入有着“先天优势”,并且支持热模块替换(HMR),而Rollup并不支持,所以当项目需要用到以上,则可以考虑选择Webpack。但是,Rollup对于代码的Tree-shaking和ES6模块有着算法优势上的支持,若你项目只需要打包出一个简单的bundle包,并是基于ES6模块开发的,可以考虑使用Rollup。其实Webpack从2.0开始支持Tree-shaking,并在使用babel-loader的情况下支持了es6 module的打包了,实际上,Rollup已经在渐渐地失去了当初的优势了。但是它并没有被抛弃,反而因其简单的API、使用方式被许多库开发者青睐,如React、Vue等,都是使用Rollup作为构建工具的。而Webpack目前在中大型项目中使用得非常广泛。最后,用一句话概括就是:在开发应用时使用 Webpack,开发库时使用 Rollup

参考:https://www.cnblogs.com/zuobaiquan01/p/14452270.html

ArthurWangCN commented 2 years ago

Webpack5 更新了哪些新特性?

ArthurWangCN commented 2 years ago

编写loader

在编写 loader 前,我们首先需要了解 loader 的本质:

代码如下所示:

// 导出一个函数,source为webpack传递给loader的文件源内容
module.exports = function(source) {
  const content = doSomeThing2JsString(source);
  // 如果 loader 配置了 options 对象,那么this.query将指向 options
  const options = this.query;
  // 可以用作解析其他模块路径的上下文
  console.log('this.context');
  /** this.callback 参数:
      * error:Error | null,当 loader 出错时向外抛出一个 error
      * content:String | Buffer,经过 loader 编译后需要导出的内容
      * sourceMap:为方便调试生成的编译后内容的 source map
      * ast:本次编译生成的 AST 静态语法树,之后执行的 loader 可以直接使用这个 AST,进而省去重复生成 AST 的过程
  */
  this.callback(null, content); // 异步
  return content; // 同步 
}

一般在编写loader的过程中,保持功能单一,避免做多种功能。如less文件转换成 css文件也不是一步到位,而是 less-loader、css-loader、style-loader几个 loader的链式调用才能完成转换。

ArthurWangCN commented 2 years ago

编写plugin

由于webpack基于发布订阅模式,在运行的生命周期中会广播出许多事件,插件通过监听这些事件,就可以在特定的阶段执行自己的插件任务

在之前也了解过,webpack编译会创建两个核心对象:

如果自己要实现plugin,也需要遵循一定的规范:

实现plugin的模板如下:

class MyPlugin {
  // Webpack 会调用 MyPlugin 实例的 apply 方法给插件实例传入 compiler 对象
  apply (compiler) {
    // 找到合适的事件钩子,实现自己的插件功能
    compiler.hooks.emit.tap('MyPlugin', compilation => {
      // compilation: 当前打包构建流程的上下文
      console.log(compilation);
      // do something...
    })
  }
}

在 emit 事件发生时,代表源文件的转换和组装已经完成,可以读取到最终将输出的资源、代码块、模块及其依赖,并且可以修改输出资源的内容