WEBPACK 新手指南
在 Node 环境中,我们有一个“CommonJS”模块系统,它使用 module.exports/require 来隔离每个文件(或“模块”)的各个部分。在 ES6 之前,浏览器代码中没有内置的“模块”。*默认情况下,HTML 文档中的每个脚本按顺序执行,并共享一个作用域。
来自Webpack 5 文档:
Webpack 是一个模块打包工具。它的主要目的是打包 JavaScript 文件以供浏览器使用,但它也能够转换、打包几乎任何资源或资产。
这是什么意思?让我们通过在 Node 中构建一个小型 JavaScript 程序来了解 Webpack 的实际作用。
设置
使用 npm 创建一个新项目并webpack
安装webpack-cli
。
mkdir hello-webpack && cd hello-webpack
npm init -y
npm install --save-dev webpack webpack-cli
现在,在你的根文件夹中,创建目录src
和public
。该src
文件夹将保存我们未处理的源代码,我们将指示 Webpack 将转译后的代码输出到该public
文件夹中。你还需要创建一个名为 的文件webpack.config.js
——稍后会详细介绍。你的项目应该如下所示:
hello-webpack/
├── src/
├── public/
├── webpack.config.js
└── package.json
包.json
{
"name": "hello-webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
公共/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="../src/game.js" defer></script>
<script src="../src/main.js" defer></script>
<link rel="stylesheet" href="style.css" />
<title>Click Me</title>
</head>
<body>
<button id="button">Click Me!</button>
</body>
</html>
公共/style.css
button {
height: 300px;
width: 300px;
font-size: 40px;
background-color: goldenrod;
color: white;
border-radius: 50%;
cursor: pointer;
}
src/game.js
let numTimesClicked = 0;
function win() {
alert('You win!');
reset();
}
function reset() {
numTimesClicked = 0;
}
function click() {
numTimesClicked++;
console.log(`You've been clicked!`);
if (numTimesClicked === 10) win();
}
src/main.js
const button = document.getElementById('button');
button.addEventListener('click', function() {
click();
});
为什么需要 Webpack?
在命令行中运行open public/index.html
。你应该会看到一个黄色按钮。点击后,该按钮会将一条消息记录到控制台。如果你点击该按钮 10 次,就会弹出一个警告,告诉你——你赢了!太棒了!大功告成!
开个玩笑。看看你的index.html
文件。如果你在第 7 行和第 8 行没有包含 defer 关键字,会发生什么?如果你重新排序你的 JavaScript 文件,会发生什么?
<!-- remove 'defer' from lines 7 and 8 -->
<!-- re-order 'game.js' and 'main.js' -->
<script src="../src/main.js"></script>
<script src="../src/game.js"></script>
你在控制台里看到过类似的东西吗? 哦哦。**还记得我一开始说的脚本按顺序执行吗?该属性告诉浏览器在 HTML 文件加载完成后才运行特定的 JavaScript 文件。如果没有,JavaScript 会在 HTML 加载完成后立即执行。如果“main.js”文件中的代码在“game.js”文件中的代码之前运行,你的程序就会在“click()”函数定义之前尝试运行它。defer
defer
这就是为什么您的控制台现在出现错误。
使用 Webpack 捆绑模块
现在我们知道了为什么需要 Webpack,让我们看看它的实际作用。
Webpack 是一个模块打包器。它的目的是通过追踪应用程序的依赖项来处理它,然后将它们打包成一个或多个可以在浏览器中运行的文件。就像 Node 应用通过 进行通用配置一样package.json
,你也可以在文件中配置 Webpack webpack.config.js
。
webpack.config.js
Webpack 基于几个关键组件:入口点、输出位置、加载器和插件。我只会关注入口点和输出位置,但在为大型项目配置 Webpack 时,你肯定会用到另外两个。
入口:Webpack 开始构建的 JavaScript 文件。
module.exports = {
entry: './path/to/my/entry/file.js'
};
输出:捆绑的 JavaScript 的名称和路径。
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js', // the starting point for our program
output: {
path: path.resolve(__dirname, 'directory_name'), // the absolute path for the directory where we want the output to be placed
filename: 'my-first-webpack.bundle.js' // the name of the file that will contain our output - we could name this whatever we want, but bundle.js is typical
}
};
您的webpack.config.js
文件可能看起来像这样:
const path = require('path');
module.exports = {
mode: "development", // could be "production" as well
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js'
}
};
NPM 脚本
现在我们已经有了 Webpack 配置,我们需要在 package.json 文件中添加一个 npm 脚本。我们可以选择任何单词,但“build”是常规用法。我们可以直接使用“webpack”。如果我们想让 Webpack 监听文件更改并进行热重载,可以在末尾添加“--w”标志。(如果不执行此步骤,每次运行 Webpack 时都必须从命令行运行本地副本。)
您的 NPM 脚本应如下所示:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --w"
},
现在...继续并激发她!
这就是你的第一个包。控制台中的元数据会告诉你包的大小。哇!现在你已经完成了,你可以使用 ES 模块了。这意味着随着程序越来越大,你可以在 JavaScript 文件之间导入和导出函数。太棒了!
将其带到网络上
快完成了!我们已经配置好了 Webpack,用来打包“main.js”文件,并在 /public 目录中输出一个“bundle.js”文件。
现在,我们可以在 JavaScript 中使用 ES 模块了。还记得click
函数在浏览器端存在之前是如何被调用的吗?现在,我们可以使用export
和import
语法将其导出game.js
并在 中调用main.js
,从而完全避免这个问题。就像这样:
游戏.js
// below the click() function
export default click;
main.js
// at the top of main.js
import click from './game'
最后,我们需要对 HTML 文件进行一些小改动。在了解 Webpack 之前,我们index.html
需要加载两个单独的 JavaScript 文件。现在,这两个文件中的所有代码都已打包到bundle.js
js 文件中,因此我们只需将 script 标签指向 即可bundle.js
。
继续并将您的脚本标签替换为以下内容bundle.js
:
<!-- <script src="../src/game.js" defer></script>
<script src="../src/main.js" defer></script> -->
<script src="bundle.js" defer></script>
现在,运行open public/index.html
。
你的程序看起来和功能跟以前完全一样吗?太棒了!你一切都做对了。
查看你的 DevTools,然后导航到“Sources”选项卡。你应该能够点击bundle.js
并观察你打包好的 JavaScript 代码。太棒了!
我们学到了什么?
Webpack 是一个打包工具,它可以将所有 JavaScript 文件打包成一个简洁的文件。我们了解到:
- Webpack 捆绑你的 JS 代码并帮助支持 ES 模块
- 两个主要概念是入口和输出
- 如何设置 webpack.config.js
干得好!你已经学到了很多,但还有更多东西需要学习。从这里开始,你可能想了解一下一个名为Babel的编译器。Webpack 通常与 Babel 一起使用,在旧版浏览器之间转换最新的 JavaScript 语法。你还可以了解 Webpack 如何处理 CSS 文件、代码拆分以及其他一些有趣的功能。它并非同类工具中唯一的一个——你可以看看grunt、gulp或browserify。