Vue 项目之 Webpack 的基础打包(6)

312 阅读3分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

1. webpack 的依赖图(dependency graph

准备工作:把之前项目目录(basic_webpack)下的 buildnode_modules 文件夹删了,然后拷贝一份 basic_webpack 目录,命名为 webpack_css。在 VS Code 的终端中进入 webpack_css 目录,再来执行 npm install 命令(这里 install 后面不需要再跟 webpack webpack-cli -D 了,因为 webpack_css 项目下已经有了 package.json 文件,并且里面已经写明了项目所需的开发时依赖有 webpackwebpack-cli,因此,只需运行 npm install 命令,就会自动来 package.json 中读取项目所需的所有依赖信息,然后进行安装)。

你会发现,这次安装依赖完成的速度很快,这其实就是因为项目下有 package-lock.json 文件,它会去使用缓存,所以依赖的安装速度很快。

安装完依赖后,我们在 webpack_css/src/js 目录下新建一个 element.js 文件,文件内容如下:

const el = document.createElement('div');

el.className = 'title';
el.innerHTML = "你好,同志!";

document.body.appendChild(el);

我们通过 JavaScript 创建了一个 div 元素,并给它添加了 title 类(后续希望通过这个类给这个 div 设置一些样式)和文本内容,最后把它添加进 DOM 中。

我们来思考一下:如果现在运行 npm run build 命令对项目代码进行打包,这个 element.js 文件中的代码会被打包吗?答案是不会。可以这样来验证:

  • 因为上一篇文章中我们已经重新指定了 webpack 打包的输出目录和文件名,所以这里先打开 index.html 文件,对里面的 <script> 元素进行修改:

    <script src="./build/bundle.js"></script>
    
  • 运行 npm run build 命令进行打包;

  • 通过 Live Server 插件在浏览器中打开 index.html 文件,查看效果:

    image-20211102074521301

    可以看到,页面上并没有出现我们在 element.js 文件中添加的 <div> 元素。这就说明 element.js 中的代码没有被打包。

那这个文件中的代码为什么没有被打包呢?这就涉及到 webpack 的一个概念:依赖图(Dependency Graph)。

  • webpack 到底是如何对我们的项目进行打包的呢?
    • 事实上,webpack 在处理应用程序时,会根据命令行中的命令(里面的 --entry)或者配置文件(里面的 entry)找到入口文件;
    • 从入口开始,会生成一个依赖关系图,这个依赖关系图会包含应用程序中所需的所有模块(比如 .js 文件、.css 文件、图片文件、字体文件等);
    • 然后遍历这个图结构,打包一个个模块(根据文件的不同使用不同的 loader 来解析);

再来看这个 element.js 文件,因为从我们项目的入口文件(./src/main.js)开始,往里寻找所有的依赖文件,最终是没有找到 element.js 这个文件的,也就是说它没有被加入到 webpack 的依赖图中,因此就不会被打包。

那如果我们想要对这个 element.js 文件进行打包,就可以在项目的任意一个已经被依赖的文件中引入 element.js,比如我们可以在 main.js 中引入:

import { sum } from './js/math.js';
const { formatPrice } = require('./js/format.js');

import './js/element'; // 导入 element.js 文件
...

这样一来,main.js 就对 element.js 产生了依赖,也就意味着从入口文件(main.js)开始生成的依赖图中已经有了 element.js 这个模块(文件),所以后续打包的时候也会把它打包进来。

现在,再来运行 npm run build 命令进行打包,页面上就能看到内容了:

image-20211102122514911

可见,现在 element.js 中的代码是有被打包的,所以才会在页面上看到这个 <div> 元素。