本文已参与「新人创作礼」活动,一起开启掘金创作之路。
在 webpack 的官网中,它是这么描述的:
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler) 。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph) ,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
我们可以看看 webpack 解决了哪些问题,从而分析为什么我们在平时需要使用 webpack 构建项目,当然目前也出现了很多可以替代 webpack 的竞品,比如 vite 。
传统开发
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>标题</title>
</head>
<body>
<div>html 内容</div>
<!-- 第三方库 -->
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- 自己的库 -->
<script src="./scripts/common.js"></script>
<script src="./scripts/product.js"></script>
<script src="./scripts/payment.js"></script>
</body>
</html>
如上述代码所示,传统开发需要遵循一些规则,比如先引入第三方的库,再引入自己的库;自己写的一些脚本,如果相互有依赖关系,需要注意引入顺序,这就会导致代码扩展性非常困难。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>标题</title>
</head>
<body>
<div>html 内容</div>
<!-- 第三方库 -->
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- 自己的库 -->
<script src="./scripts/bundle.233abc233a.js"></script>
</body>
</html>
如果是把自己的代码都整合到一个文件里,又会导致4个问题:
- 作用域问题(污染全局变量)
- 文件过大(网络加载慢,白屏)
- 可读性差
- 可维护性弱
作用域问题
Grunt 和 Gulp 作为任务执行器,利用 IIFE (Immediately Invoked Function Expression) 的机制拼接组合文件,这样就不用担心作用域的问题了。
;(function(){
var myName = "Tom"
})()
console.log(myName) // undefined
如何拆分大文件
node.js 是一个 javascript 的运行环境,我们可以在非浏览器中运行 js 代码,特别是 npm 的出现,引发了 Web 开发的革命, webpack 其实就是运行在 node.js 中的。 common js (cjs) (一种 js 规范)中引入了 require 方法,可以加载模块代码。在浏览器中,不支持 cjs 的写法,除非使用 Browserify 或 RequireJS。
// math.js
const add = (a, b) => (a + b)
const minus = (a, b) => (a - b)
module.exports = {
add,
minus
}
// main.js
const math = require("./math.js")
math.add(4, 5) // 9
不过,随着 es6 module 的出现, cjs 已经过时。如果要在 script 标签中如果需要使用的话,需要添加属性 type="module"。目前大多数浏览器和 node.js 中已支持 esm ,逐渐成为标准。需要注意的是 esm 是编译时加载,因此不支持变量、表达式,而 cjs 时运行时动态加载
// math.js
const add = (a, b) => (a + b)
const minus = (a, b) => (a - b)
export {
add,
minus
}
// main.js
import math from './math.js'
math.add(4, 5) // 9