Webpack 入门 1

目前版本第一的打包工具 Webpack 其之一


点我下载本章代码

什么是 Webpack

首先贴出 webpack 的官网

webpack

webpack 中文文档

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。构建过程是拓扑排序的一种

说到底,webpack 基本的功能,其实就是把高版本 js 转换成 js,以及把非 js 的文件转换成 js

安装

先安装一下吧

我们可以看到,官方文档的指南里给出了如下命令行

1
2
3
mkdir webpack-demo && cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev

那我们也照做一下,完成后目录结构如下

开始

指南里还要求我们首先建一个新目录,里面包含一个 src 的一个 index.js,以及一下 index.html

index.html 中记得连接到 index.js

然后让我们试试高版本 js 转换成低版本 js 的功能。一般是 ES6 转换成 ES5

让我们先从文档里找一个能用的 webpack 配置

1
2
3
4
5
6
7
8
9
const path = require('path');

module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};

就他了!

建立一个 webpack.config.js 文件用来保存配置

然后试试运行

1
npx webpack

npx 命令指示 node 从当前目录下的 node_modules 中寻找webpack

然后发现报错了?!怎么回事呢

看看报错说什么

报错说他不能识别 ./path/to/my/entry/file.js 这个文件是什么

这个字符串在哪里提到了呢?在配置中的 entry

entry 这个词很明显是入口的意思,加上是 js 结尾,我们试试看用我们现在目录中唯一的 js 替换

现在配置变成这样,再试试打包吧!

这次很顺利的成功了

检查目录,发现目录下多了个 dist 文件夹,里面多了个 my-first-webpack.bundle.js 文件

打开内容一看,就是和我们的 index.js 里面是一样的内容!甚至还自己分析了语义,省去了不必要的代码

这就是 webpack 的基本功能 js 转换

入口

entry 除了上文提到的单入口指定

1
2
3
4
5
6
7
8
9
const path = require('path');

module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};

也可以指定多个入口,传入一个 hashtable 即可

1
2
3
4
5
6
7
8
9
10
11
12
const path = require('path');

module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};

传入的入口 js 会分别打包,有兴趣的朋友可以自己尝试一下

模式

显然代码一般都有开发和部署两种状态,webpack 也有不同的对应代码

在配置中可以添加 mode 字段来指示 webpack 模式,有两种选择

  1. production,部署模式,默认
  2. development,开发模式

具体来说,打包出来的东西会有区别,比如刚才的代码

1
2
let string = 'hello'
console.log(string)

在部署模式会被打包成上图样式

1
console.log("hello");

在开发模式会打包成如下样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is not neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
/******/ (() => { // webpackBootstrap
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
eval("let string = 'hello'\r\nconsole.log(string)\n\n//# sourceURL=webpack://webpack-demo/./src/index.js?");
/******/ })()
;

多了很多不必要的代码,为了方便程序员查看

输出哈希

从配置信息中可以看出,配置里不仅指示了入口文件,还指示了 output——输出文件的配置

上述配置中令输出文件夹命名为 dist,这也是大部分构建工具的配置

还指示了 filename,可以猜出是输出的 js 文件的文件名

在刚才尝试不同模式的构建中,我们已经发现不同的构建会覆盖旧有的文件,但输出文件名仍然是同一个

根据以前学习的浏览器缓存知识可以了解到,浏览器发现你在 html 文件中的连接 js 名称没变,那就会认为现在的页面还是使用原有的缓存,显然不利于页面的更新

于是我们要为新构建的 js 指定一个每次都不一样的名称

但是总不能手动配置吧?那也太烦了

还好 webpack 提供了 filename 模板

可以通过 [name].[contenthash].js 来指定随机的新 filename,其中的 contenthash 是依据文件内容进行哈希,也就是说只要文件内容有变化,新打包出来的文件一定不同名

让我们试试吧

更换了新配置之后发现生成了一个 main.xxxxx.js 文件!成功了!

快捷构建

每次构建都产生一个不同名文件,虽然有利于浏览器更新,但是不利于本地……毕竟总不能每次都手动删除一下 dist 吧2333

这时候我们可以考虑修改 node 默认的配置

可以向 package.json 文件中的 scripts 字段加入如下内容

1
2
3
"scripts": {
"build": "webpack"
}

与命令行不同,写在此处的命令可以不加 npx,默认是在本目录下查找

接下来我们运行 npm run build 就等同于运行 npx webpack

于是我们就可以把 rm 语句也加进去

1
2
3
"scripts": {
"build": "rm -rf ./dist && webpack"
}

&& 表示前项执行成功才执行后项

现在就可以在运行 npm run build 的时候同时删除旧文件了

注:有的不能用 rm 命令的时候,可以用 rimraf 命令代替

下集预告

只有 js 怎么够?!我要完整的三剑客!

点我查看下集


感谢阅读

--It's the end.Thanks for your read.--