工程化之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-loader、url-loader、raw-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 "新的缓存路径"
相关推荐
福兮说4 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理5 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆6665 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
Dovis(誓平步青云)6 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan6 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_7 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒7 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技7 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
yivifu8 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub
默_笙9 小时前
🛴 从散件到整机:DeepAgents 与 Agent 身上预留的那些"插槽"(前置介绍)
前端·javascript