webpack总结

45 阅读6分钟

juejin.cn/post/715799…

1. 什么是webpack?

现代JavaScript应用程序的静态模块打包工具。会在内部构建一个依赖图,映射项目所需的每个模块,并生成多个bundle。

webpack能利用模块生命的依赖信息构建依赖图,然后使用图生成一个优化过的bundle,并能保证以正确顺序执行

换言之,webpack能指定入口src/index.js文件,和dist/main.js文件作为输出。

2. webpack核心概念?

核心概念:入口、输出、loader、插件plugin、模式mode、浏览器兼容

a. 常见常用的loader?

image-loader(加载并压缩图片)、

file-loader(吧文件输出到一个文件夹中,在代码中提供相对路径去引用输出文件)、

svg-sprite-loader:

sass-loader:将scss、sass代码转为css

css-loader:加载css,支持模块化、压缩、文件导入等特性

babel-loader:把ES6转为ES5

tslint-loader、eslint-loader:通过TSLint、ESLint检查TS、JS代码

b. 常用的plugins

移动版用户中心中使用的有:

import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import Components from 'unplugin-vue-components/vite'
import { VantResolver } from 'unplugin-vue-components/resolvers'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import { createHtmlPlugin } from 'vite-plugin-html'
import postCssPxToRem from 'postcss-pxtorem'

vitejs/plugin-vue:支持vue3单文件组开发、及解析.vue文件

vitejs/plugin-vue-jsx:支持Vue3中的JSX语法

unplugin-vue-components/vite:按需引入vue组件,避免手动import

vite-plugin-svg-icons:svg图标插件,加载本地svg文件为图标

vite-plugin-html:动态注入环境变量到HTML文件中

postcss-pxtorem:将css中的px自动转换为rem

自定义插件-----

3. loader和plugin的区别

a. 概念不一样。

loader本质内容是函数。对函数中接收到的内容进行转换,返回转换后的结果。让webpack有加载和解析非JavaScript文件的能力。

plugin是插件。是为webpack拓展其他能力,让webpack更加灵活。在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

b. 配置方式不一样。

loader在modules.rules中配置,作为模块解析规则,类型为数组。每一项都是Object。

plugin在plugins中单独配置,类型为数组,每一项都是一个plugin实例,参数通过构造函数传入。

c. 运行时机不一样。

loader运行在打包文件之前(loader为在模块加载时的预处理文件

plugin在整个编译周期都起作用。可以监听webpack运行生命周期,并在合适的时机通过webpack提供的API改变输出结果。

4.webpack构建流程

总结:

初始化:启动构建,读取合并配置参数,加载plugin,实例化compiler;

编译:从入口文件出发,针对每个module串行调用对应的Loader去翻译文件内容,再找到该module依赖的module,递归地进行编译处理。

输出:将编译后的module组合成chunk,将chunk转化为文件,输出到文件系统中。

Webpack运行流程是一个串行过程,从启动到结束会经历以下过程:

  1. 初始化参数:从配置文件和shell语句中读取、合并参数,得出最终的参数
  2. 开始编译:用上一步得到的参数初始化compiler对象,加载所有配置的插件。执行对象的run方法开始编译。
  3. 确定入口:根据配置中的entry找出所有的入口文件
  4. 编译模块:从入口文件触发,调用loader对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经历了本步骤。
  5. 完成模块编译:在经历第4步翻译完所有模块后,得到了每个模块被翻译后的最终内容和它们之间的依赖关系。
  6. 输出资源:根据入口和模块之间的依赖关系,组装chunk,再把每个chunk转换成单独的文件加入输出列表,这步是可以修改输出内容的最后机会。
  7. 输出完成:确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入文件系统。

在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。

5. webpack热更新原理

webpack热更新又称为热替换,HMR。这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。

HMR的核心就是客户端从服务端拉去更新后的文件,准确的说是 chunk diff (chunk 需要更新的部分),实际上 WDS(无线分布式系统) 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。

zhuanlan.zhihu.com/p/30669007

6. 如何优化webpack打包

  1. gzip压缩代码

  2. 使用最新版本的webpack

  3. 分包:全局引入改按需加载(如element-plus分包)

  4. 去除map文件:productionSourceMap设置为false。

    productionSourceMap 在构建时生成完整的 SourceMap 文件,默认情况下开启。生产环境中启用 productionSourceMap 有助于开发者调试代码,可以在浏览器的调试工具中查看到源文件中错误的代码位置,而不是编译后的代码位置。这对于定位线上问题十分有帮助。

    然而,开启 productionSourceMap 会使得构建后的代码包含源代码映射关系,导致构建后的代码文件体积增大。体积增加会影响页面加载速度,而且源代码也存在泄漏的风险,因此有些开发者会选择在生产环境中禁用 productionSourceMap。

  1. 代码分割:js和css分开打包
  2. 使用合适的loader和plugins,比如用file-loader
  3. 使用缓存。如把一些静态资源放cdn
  4. 开启多进程

7. webpack解决跨域问题poxy

设置webpack poxy之后,相当于浏览器和服务器中添加一个代理者。

当本地发送请求,代理服务器响应该请求,并将请求转发到目标服务器,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地。

总的而言,是因为:在代理服务器传递数据给本地服务器过程中,两者同源,不存在跨域行为。 (服务器和服务器之间请求数据不会存在跨域行为)。