面试复习题 - 工程化webpack、vite

285 阅读5分钟

✊不积跬步,无以至千里;不积小流,无以成江海

常见 loader 和 plugin 的区别是什么

常见 loader

  1. babel-loader 把 JS/TS 变成 JS

  2. ts-loader 把 TS 变成 JS,并提示类型错误

  3. markdown-loader 把 markdown 变成 html

  4. html-loader 把 html 变成 JS 字符串

  5. sass-loader 把 SASS/SCSS 变成 CSS

  6. css-loader 把 CSS 变成 JS 字符串

  7. style-loader 把 JS 字符串变成 style 标签

  8. postcss-loader 把 CSS 变成更优化的 CSS;5678如果一起用,最好的顺序是5867

  9. vue-loader 把单文件组件(SFC)变成 JS 模块

  10. thread-loader 用于多进程打包

常见 plugin

  1. html-webpack-plugin 用于创建 HTML 页面并自动引入 JS 和 CSS

  2. clean-webpack-plugin 用于清理之前打包的残余文件

  3. mini-css-extract-plugin 用于将 JS 中的 CSS 抽离成单独的 CSS 文件

  4. SplitChunksPlugin 用于代码分包(Code Split)

  5. DllPlugin + DllReferencePlugin 用于避免大依赖被频繁重新打包,大幅降低打包时间

  6. eslint-webpack-plugin 用于检查代码中的错误

  7. DefinePlugin 用于在 webpack config 里添加全局变量

  8. copy-webpack-plugin 用于拷贝静态文件到 dist

二者的区别

  1. loader 是文件加载器

◦ 功能:能够对文件进行编译、优化、混淆(压缩)等,比如 babel-loader / vue-loader

◦ 运行时机:在创建最终产物之前运行

  1. plugin 是 webpack 插件

◦ 功能:能实现更多功能,比如定义全局变量、Code Split、加速编译等

◦ 运行时机:在整个打包过程(以及前后)都能运行

webpack 如何解决开发时的跨域问题?

在开发时,我们的页面在localhost:8080,JS 直接访问后端接口(如https://yiqilaiwan.comhttp://localhost:3000 )会报跨域错误。

为了解决这个问题,可以在 webpack.config.js 中添加如下配置:

module.exports = {

    //...

    devServer: {
        proxy: {
        '/api': {
        target: 'http://yiqilaiwan.com',
        changeOrigin: true,
        },
    },},

};

此时,在 JS 中请求 /api/users 就会自动被代理到 https://yiqilaiwan.com/api/users

如果要访问的是 HTTPS API,那么就需要配置 HTTPS 证书,否则会报错。不过,如果在 target 下面添加 secure: false ,就可以不配置证书且忽略 HTTPS 报错。

如何实现 tree-shaking?

是什么

tree-shaking 就是让没有用到的 JS 代码不打包,以减小包的体积。

怎么做

背下文档说的这几点:

  1. 怎么删

    a. 使用 ES Modules 语法(即 ES6 的 import 和 export 关键字)

    b. CommonJS 语法无法 tree-shaking(即 require 和 exports 语法)

    c. 引入的时候只引用需要的模块

    • 要写 import {cloneDeep} from 'lodash-es' 因为方便 tree-shaking
    • 不要写 import from 'lodash' 因为会导致无法 tree-shaking 无用模块
  2. 怎么不删:在 package.json 中配置 sideEffects,防止某些文件被删掉

    a. 比如我 import 了 x.js,而 x.js 只是添加了 window.x 属性,那么 x.js 就要放到sideEffects 里

    b. 比如所有被 import 的 CSS 都要放在 sideEffects 里

  3. 怎么开启:在 webpack config 中将 mode 设置为 production(开发环境没必要tree-shaking)

    a. mode: production 给 webpack 加了非常多。

如何提高 webpack 构建速度?

  1. 使用 DllPlugin 将不常变化的代码提前打包编程一个动态链接库,并复用,如 vue、react

  2. 使用 thread-loader 或 HappyPack(过时)进行多线程打包,即同时放在4/8..个cpu上同时打包

  3. 处于开发环境时,在 webpack config 中将 cache 设为 true,也可用 cache-

loader(过时)

  1. 处于生产环境时,关闭不必要的环节,比如可以关闭 source map

webpack 与 vite 的区别是什么?

开发环境区别

  1. vite 自己实现 server,不对代码打包,充分利用浏览器对 <script type=module> 的支持

    i. 假设 main.js 引入了 vue

    ii. 该 server 会把 import { createApp } from 'vue' 改为 import {createApp } from "/node_modules/.vite/vue.js" 这样浏览器就知道去哪里找 vue.js 了

  2. webpack-dev-server 常使用 babel-loader 基于内存打包,比 vite 慢很多很多很多

    i. 该 server 会把 vue.js 的代码(递归地)打包进 main.js

生产环境区别

  1. vite 使用 rollup + esbuild 来打包 JS 代码

  2. webpack 使用 babel 来打包 JS 代码,比 esbuild 慢很多很多很多

    i. webpack 能使用 esbuild 吗?可以,你要自己配置(很麻烦)。

  3. 文件处理时机

    i. vite 只会在你请求某个文件的时候处理该文件

    ii. webpack 会提前打包好 main.js,等你请求的时候直接输出打包好的 JS 给你

目前已知 vite 的缺点有:

  1. 热更新常常失败,原因不清楚

  2. 有些功能 rollup 不支持,需要自己写 rollup 插件

  3. 不支持非现代浏览器

webpack 怎么配置多页应用?

截屏2024-03-11 13.17.18.png

  1. 先定义路径
  2. 然后用html-webpack-plugin指定名字
  3. 用chunks指定js路径,通过chunks name和js进行了关联
  4. 这样配置会有一个「重复打包」的问题:假设 app.js 和 admin.js 都引入了vue.js,那么 vue.js 的代码既会打包进 app.js,也会打包进 admin.js。
  5. 需要使用optimization.splitChunks 将共同依赖单独打包成 common.js(HtmlWebpackPlugin会自动引入 common.js)

万一思考无限多页面的情况。

  1. 获取指定路径下的所有文件
  2. filter只以js结尾的文件
  3. 对每个js结尾文件的js去掉
  4. 然后对应上面的生成多个entry对象 & plugins数组
  5. 最后把生成的路径扩展过来

swc、esbuild 是什么?

swc

实现语言:Rust

功能:编译 JS/TS、打包 JS/TS

优势:比 babel 快很多很多很多(20倍以上)

能否集成进 webpack:能

使用者:Next.js、Parcel、Deno、Vercel、ByteDance、Tencent、Shopify……

做不到:

  1. 对 TS 代码进行类型检查(用 tsc 可以)

  2. 打包 CSS、SVG

esbuild

实现语言:Go

功能:同上

优势:比 babel 快很多很多很多很多很多很多(10~100倍)

能否集成进 webpack:能

使用者:vite、vuepress、snowpack、umijs、blitz.js 等

做不到:

  1. 对 TS 代码进行类型检查

  2. 打包 CSS、SVG