工程化之webpack

为什么要学习webpack?

前端有很多打包工具,其中,webpack生态最完整、使用最广泛。

学习webpack的意义主要有以下几点:

  1. 理解前端开发中出现的常见问题,以及对应的解决办法
  2. 帮助理解常见的脚手架,如vue-cli、create-react-app、umi-js等
  3. 可以脱离脚手架搭建工程,甚至自己完成脚手架开发
  4. 应对工程化方面的进阶面试题

webpack学习哪个版本?

截止到2022-01-04,webpack的版本是webpack5,但目前使用的最广泛的是webpack4。

webpack的版本会不断更新,但它的核心原理是不变的,因此,学习webpack4成为了最好的选择。

webpack的更新

一丶清除输出目录

webpack5清除输出目录开箱可用,无须安装clean-webpack-plugin,具体做法如下:

js 复制代码
module.exports = {
  output: {
    clean: true
  }
}

top-level-await

webpack5现在允许在模块的顶级代码中直接使用await

js 复制代码
// src/index.js
const resp = await fetch("http://www.baidu.com");
const jsonBody = await resp.json();
export default jsonBody;

目前,top-level-await还未成为正式标准,因此,对于webpack5而言,该功能是作为experiments发布的,需要在webpack.config.js中配置开启

js 复制代码
// webpack.config.js
module.exports = {
  experiments: {
    topLevelAwait: true,
  },
};

打包后可自动在顶层上面添加async

打包体积优化

webpack5对模块的合并、作用域提升、tree shaking等处理更加智能

例子1:index.js

arduino 复制代码
console.log("index1.js没有依赖其他模块,也没有导出任何东西");

打包后:

arduino 复制代码
console.log("index1.js没有依赖其他模块,也没有导出任何东西");

可以对比看到,打包前后代码基本一样,因为这就是最简单的输出,但是在webpack4中,这段代码应该放在一个自执行函数中

例子2:index.js2

javascript 复制代码
import { f1 } from './modules/a';
import * as bFuncs from './modules/b';
f1();
bFuncs.f4();

分析以上代码,可以看到,我们引入了模块a,b中的依赖,我们再看看模块a,b a.js

javascript 复制代码
import { f3 } from './b';
export function f1() {
  console.log('f1');
}

export function f2() {
  console.log('f2');
  f3();
}

b.js

javascript 复制代码
export function f3() {
  console.log("f3");
}

export function f4() {
  console.log("f4");
}

可以看到,在a模块中又引入了b模块的东西,我们index2.js中其实只需要f1和f4,大家可以把这段代码拿到webpack4中看看,打包出来的东西是什么,但是在webpack5中对于模块合并和tree shaking的处理是更加智能的,我们看看webpack5打包后的代码

javascript 复制代码
(() => {
  'use strict';
  console.log('f1'), console.log('f4');
})();
//# sourceMappingURL=index2.js.map

打包缓存开箱即用

webpack4中,需要使用cache-loader缓存打包结果以优化之后的打包性能

而在webpack5中,默认就已经开启了打包缓存,无须再安装cache-loader

默认情况下,webpack5是将模块的打包结果缓存到内存中,可以通过cache配置进行更改

js 复制代码
const path = require("path");

module.exports = {
  cache: {
    // 缓存类型,支持:memory、filesystem
    type: "filesystem", 
    // 缓存目录,仅类型为 filesystem 有效
    cacheDirectory: path.resolve(__dirname, "node_modules/.cache/webpack"), 
  },
};

关于cache的更多配置参考:webpack.docschina.org/configurati...

资源模块

webpack4中,针对资源型文件我们通常使用file-loaderurl-loaderraw-loader进行处理

由于大部分前端项目都会用到资源型文件,因此webpack5原生支持了资源型模块

详见:webpack.docschina.org/guides/asse...

webpack scope hoisting(作用域提升)

详细介绍:webpack.docschina.org/plugins/mod...

scope hoisting 是 webpack 的内置优化,它是针对模块的优化,在生产环境打包时会自动开启。

在未开启scope hoisting时,webpack 会将每个模块的代码放置在一个独立的函数环境中,这样是为了保证模块的作用域互不干扰。

而 scope hoisting 的作用恰恰相反,是把多个模块的代码合并到一个函数环境中执行。在这一过程中,webpack 会按照顺序正确的合并模块代码,同时对涉及的标识符做适当处理以避免重名。

这样做的好处是减少了函数调用,对运行效率有一定提升,同时也降低了打包体积。

但 scope hoisting 的启用是有前提的,如果遇到某些模块多次被其他模块引用,或者使用了动态导入的模块,或者是非 ESM 的模块,都不会有 scope hoisting。

npm 模块安装机制是什么

  1. npm 会检查本地的 node_modules 目录中是否已经安装过该模块,如果已经安装,则不再重新安装
  2. npm 检查缓存中是否有相同的模块,如果有,直接从缓存中读取安装
  3. 如果本地和缓存中均不存在,npm 会从 registry 指定的地址下载安装包,然后将其写入到本地的 node_modules 目录中,同时缓存起来。
    npm 缓存相关命令:
shell 复制代码
# 清除缓存
npm cache clean -f

# 获取缓存位置
npm config get cache

# 设置缓存位置
npm config set cache "新的缓存路径"
相关推荐
wyiyiyi15 分钟前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip37 分钟前
vite和webpack打包结构控制
前端·javascript
excel1 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国1 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼1 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy1 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT2 小时前
promise & async await总结
前端
Jerry说前后端2 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
画个太阳作晴天2 小时前
A12预装app
linux·服务器·前端
7723892 小时前
解决 Microsoft Edge 显示“由你的组织管理”问题
前端·microsoft·edge