31.说一说 webpack 的构建流程是什么?
⚫ 初始化流程:
 
 ◼  
 从配置文件和 Shell 语句中读取与合并参数  
 
 
 ◼  
 初始化需要使用的插件和配置插件等执行环境所需要的参数  
 
⚫ 编译构建流程:
 
 ◼  
 从 Entry 发出,针对每个 Module 串行调用对应的 Loader 去翻译文件内容  
 
 
 ◼  
 再找到该 Module 依赖的 Module,递归地进行编译处理  
 
⚫ 输出流程:
 
 ◼  
 对编译后的 Module 组合成 Chunk,  
 
 
 ◼  
 把 Chunk 转换成文件,输出到文件系统 
 
 
32.如何优化 webpack 打包速度
⚫ 并行编译:
 
  ◼  
  thread-loader: 
  利用多个 CPU 内核并行运行加载器。  
 
 
  
  ◼  
  HappyPack : 
  将模块转换任务分解到多个 worker 进程中并行处理。  
 
 
 ⚫ 代码拆分:
 
  ◼  
  splitChunksPlugin  
  代码分割,将公共代码、第三方库等抽离到单独的 chunk,减  
 
 
  
  少重复编译的工作量。  
 
 
 ⚫ 动态导入(import()):
 
  ◼  
  根据路由或其他条件按需加载代码,避免一次性打包所有代码。  
 
 
 ⚫ Tree Shaking:
 
  ◼  
  确保你的 ES 模块使用的是静态导入导出, Tree Shaking 移除未使用的代码。  
 
 
 ⚫ DllPlugin/DllReferencePlugin:
 
  ◼  
  不经常变动的依赖(如 React, Vue 库)提前打包成  
  DLL(动态链接库) 
  ,避免每次  
 
 
  
  构建都重新打包这些库。  
 
 
 ⚫ 减少 Loader 和 Plugin 的数量:
 
  ◼  
  只使用必要的 loader 和 plugin,每个额外的处理都会增加构建时间。  
 
 
 ⚫ 提升 Loader 性能:
 
  ◼  
  Babel 等慢速 loader,使用针对性的配置优化,比如@babel/preset-env 的  
 
 
  
  useBuiltIns 和 targets 选项,减少不必要的 polyfill。  
 
 
 ⚫ Excluding node_modules:
 
  ◼  
  不需要转译的 node_modules 模块,可以在.babelrc 或 webpack 配置中排除它们。  
 
 
 ⚫ Cache:
 
  ◼  
  利用 Webpack 的持久化缓存特性,如 cacheDirectory 选项,或使用 hard-source 
 
 
  
  webpack-plugin 等第三方插件来缓存编译结果。  
 
 
 ⚫ 优化 Resolving 配置:
 
  ◼  
  减少模块解析的搜索范围,通过 resolve.modules, resolve.alias 等配置项提高模块 
  查找速度。  
 
 
 ⚫ Source Map 优化:
 
  ◼  
  开发环境使用 cheap-module-eval-source-map 或更快的 source-map 选项,生产  
 
 
  
  环境考虑是否需要 source map 或使用更简洁的格式。  
 
 
 ⚫ 升级 Webpack 和其他依赖:
 
  ◼  
  保持 Webpack 及其相关 loader、plugin 的版本是最新的,新版本往往带来性能改  
 
 
  
  进。  
 
 
 ⚫ 分析和监控:
 
  ◼  
  使用 webpack-bundle-analyzer 分析包大小,找出可以进一步优化的地方。 
 
 
  
 33.说说 webpack 中常见的 Loader?解决了什么问题?
 
   ⚫  
   loader 对模块的"源代码"进行转换,  
  
 
   
   ⚫  
   在 import 或"加载"模块时预处理文件  
  
 
   
   ⚫  
   webpack 分析各种模块依赖关系,然后形成资源列表,最终打包生成到指定的文件中。  
  
 
   
   ⚫  
   babel-loader  
   :用 babel 来转换 ES6 文件到 ES5  
  
 
   
   ⚫  
   html-minify-loader:  
   压缩 HTML  
  
 
   
   ⚫  
   style-loader:  
   将 css 添加到 DOM 的内联样式标签 style 里  
  
 
   
   ⚫  
   css-loader : 
   允许将 css 文件通过 require 的方式引入,并返回 css 代码  
  
 
   
   ⚫  
   less-loader:  
   处理 less 
   → 
   css  
  
 
   
   ⚫  
   sass-loader:  
   处理 sass 
   → 
   css  
  
 
   
   ⚫  
   postcss-loader:  
   用 postcss 来处理 CSS  
  
 
   
   ⚫  
   autoprefixer-loader:  
   处理 CSS3 属性前缀,已被弃用,建议直接使用 postcss  
  
 
   
   ⚫  
   file-loader:  
   分发文件到 output 目录并返回相对路径  
  
 
   
   ⚫  
   url-loader:  
   和 file-loader 类似,但是当文件小于设定的 limit 时可以返回一个 Data Url 
  
 
   
  34.说说 webpack 中常见的 Plugin?解决了什么问题?
 
    ⚫  
    Plugin(Plug-in)是一种计算机应用程序,它和主应用程序互相交互,以提供特定的功  
   
 
    
    能  
   
 
    
    ⚫  
    是一种遵循一定规范的应用程序接口编写出来的程序,只能运行在程序规定的系统下,  
   
 
    
    因为其需要调用原纯净系统提供的函数库或者数据  
   
 
    
    ⚫  
    webpack 中的 plugin 也是如此,plugin 赋予其各种灵活的功能,例如打包优化、资源  
   
 
    
    管理、环境变量注入等,它们会运行在 webpack 的不同阶段(钩子 / 生命周期),贯穿  
   
 
    
    了 webpack 整个编译周期  
   
 
    
    ⚫  
    HtmlWebpackPlugin  
   
 
    
            ◼ 在打包结束后,自动生成一个 html 文文件,  
   
 
    
            ◼ 并把打包生成的 js 模块引入到该 html 中  
   
 
    
    ⚫  
    clean-webpack-plugin  
    删除(清理)构建目录  
   
 
    
    ⚫  
    mini-css-extract-plugin  
    提取 CSS 到一个单独的文件中  
   
 
    
    ⚫  
    DefinePlugin  
    允许在编译时创建配置的全局对象,是一个 webpack 内置的插件,不需  
   
 
    
    要安装 
   
 
    
    ⚫  
    copy-webpack-plugin  
   
 
    
            ◼ 复制文件或目录到执行区域,  
   
 
    
            ◼ 如 vue 的打包过程中,如果我们将一些文件放到 public 的目录下,那么这个目录  
   
 
    
                    会被复制到 dist 文件夹中 
   
 
    
   35.请详细说说 webpack 中的 plugin 和 loader 之间的区别是什么?
⚫ loader
 
     ◼  
     是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩  
    
 
     
     等,最终一起打包到指定的文件中  
    
 
    ⚫ plugin
 
     赋予了 webpack 各种灵活的功能,例如打包优化、资源管理、环境变量注入等,目的是解决 loader 无法实现的其他事 
    
 
     
     
   
 
   
 
   
36.说说你对 promise 的了解
 
 Promise 承诺 
 ,异步编程的一种解决方案,比传统解决方案(回调函数)更合理和更加强大  
 
 
 回调函数 
 形成了经典的回调地狱  
 
promise 解决异步操作的优点:
 
 ⚫  
 链式操作减低了编码难度  
 
 
 ⚫  
 代码可读性明显增强  
 
 
 ⚫  
 状态  
 
promise 对象仅有三种状态
 
 ⚫  
 pending(进行中)  
 
 
 ⚫  
 fulfilled(已成功)  
 
 
 ⚫  
 rejected(已失败)  
 
 
 对象的状态不受外界影响,只有异步操作的结果,可以决定当前状态  
 
用法
 
 ⚫  
 Promise 对象是一个构造函数,用来生成 Promise 实例  
 
 
 const promise = new Promise(function(resolve, reject) {});  
 
 
 ⚫  
 Promise 构造函数接受一个函数作为参数,函数的两个参数分别是 resolve 和 reject  
 
 
 ⚫  
 resolve 函数: 
 将 Promise 对象的状态从“未完成”变为“成功”  
 
 
 ⚫  
 reject 函数: 
 将 Promise 对象的状态从“未完成”变为“失败”  
 
⚫ 实例方法 then() catch() finally()
⚫ then()
 
 ◼  
 实例状态发生改变时的回调函数  
 
 
 ◆  
 第一个参数是 resolved 状态的回调函数,  
 
 
 ◆  
 第二个参数是 rejected 状态的回调函数  
 
 
 ◼  
 then 方法返回的是一个新的 Promise 实例,也就是 promise 能链式书写的原因  
 
⚫ catch()
 
 .then(null, rejection)或.then(undefined, rejection) 
 的别名,  
 
 
 ◼  
 用于指定发生错误时的回调函数  
 
 
 ◼  
 Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止  
 
 
 ◼  
 一般来说,使用 catch 方法代替 then()第二个参数  
 
⚫ finally()
 
 ◼  
 用于指定不管 Promise 对象最后状态如何,都会执行的操作  
 
构造函数方法 all() race() allSettled() resolve() reject()
⚫ all()
 
 ◼  
 Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例  
 
 
 const p = Promise.all([p1, p2, p3]);  
 
 
 ◼  
 接受一个数组作为参数,数组成员都为 Promise 实例  
 
 
 ◼  
 实例 p 的状态由 p1、p2、p3 决定,分为两种: 
 ◆  
 只有 p1、p2、p3 的状态都变成 fulfilled,p 的状态才会变成 fulfilled,此时 p1、  
 
 
 p2、p3 的返回值组成一个数组,传递给 p 的回调函数  
 
 
 ◆  
 只要 p1、p2、p3 之中有一个被 rejected,p 的状态就变成 rejected,此时第  
 
 
 一个被 reject 的实例的返回值,会传递给 p 的回调函数  
 
 
 ◼  
 注意,如果作为参数的 Promise 实例,自己定义了 catch 方法,那么它一旦被  
 
 
 rejected,并不会触发 Promise.all()的 catch 方法  
 
⚫ race()
 
 ◼  
 Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例  
 
 
 const p = Promise.race([p1, p2, p3]);  
 
 
 ◼  
 只要 p1、p2、p3 之中有一个实例率先改变状态,p 的状态就跟着改变  
 
 
 ◼  
 率先改变的 Promise 实例的返回值则传递给 p 的回调函数  
 
⚫ allSettled()
 
 ◼  
 Promise.allSettled()方法接受一组 Promise 实例作参数,包装一个新 Promise 实例  
 
 
 ◼  
 只有等到所有这些参数实例都返回结果,不管是 fulfilled 还是 rejected,包装实例  
 
 
 才会结束  
 
 
 const promises = [  
 
 
 fetch('/api-1'),  
 
 
 fetch('/api-2'),  
 
 
 fetch('/api-3'),  
 
 
 ];  
 
 
 await Promise.allSettled(promises);  
 
 
 removeLoadingIndicator();  
 
⚫ resolve()
 
 ◼  
 将现有对象转为 Promise 对象  
 
 
 Promise.resolve('foo')  
 
 
 // 等价于  
 
 
 new Promise(resolve => resolve('foo'))  
 
 
 ◼  
 参数可以分成四种情况:  
 
 
 ◆  
 参数是一个 Promise 实例,promise.resolve 将不做任何修改、原封不动地返  
 
 
 回这个实例  
 
 
 ◆  
 参数是一个thenable对象,promise.resolve会将这个对象转为 Promise对象,  
 
 
 然后就立即执行 thenable 对象的 then()方法  
 
 
 ◆  
 参数不是具有 then()方法的对象,或根本就不是对象,Promise.resolve()会返  
 
 
 回一个新的 Promise 对象,状态为 resolved  
 
 
 ◆  
 没有参数时,直接返回一个 resolved 状态的 Promise 对象  
 
⚫ reject()
 
 ◼  
 Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为  
 
 
 rejected  
 
 
 const p = Promise.reject('出错了');  
 
 
 // 等同于  
 
 
 const p = new Promise((resolve, reject) => reject('出错了'))  
 
使用场景
 
 ⚫  
 将图片的加载写成一个 Promise,一旦加载完成,Promise 的状态就发生变化 
 ⚫  
 通过链式操作,将多个渲染数据分别给个 then,让其各司其职。或当下个异步请求依  
 
 
 赖上个请求结果的时候,我们也能够通过链式操作友好解决问题  
 
 
 ⚫  
 通过 all()实现多个请求合并在一起,汇总所有请求结果,只需设置一个 loading 即可  
 
 
 ⚫  
 通过 race 可以设置图片请求超时 
                


















