# Webpack 基础概念
# 前端的 "模块化"
随着前端变得越来越复杂和庞大, 传统的通过直接编写 JavaScript、CSS、HTML 开发 Web 应用的方式已经无法应对当前 Web 应用的发展。随之各种为了优化开发, 提升效率的新思想, 新技术也涌现出来. 其中最重要的理念之一就是 "模块化". "模块化" 是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程. 当项目变大时这种方式将变得难以维护,需要用模块化的思想来组织代码。模块化思想被很多新的前端框架所应用, 但是这些东西都有一个共同点:源代码无法直接运行,必须通过转换后才可以正常运行。
这个时候构建工具就派上了用场, 构建工具把源代码转换成发布到线上的可执行 JavaScrip、CSS、HTML 代码.
# 什么是 Webpack
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(static module bundler)。webpack 把项目中的一切文件都看作是模块, 并内部理清各个模块之间的依赖关系,然后将模块打包构建成项目运行所需的静态文件.
# 基本概念
# 入口 Entry
如上图所示,在多个代码模块中会有一个起始的 .js
文件,这个便是 webpack 构建的入口。webpack 会读取这个文件,并从它开始解析依赖. 任何时候,一个文件依赖于另一个文件,webpack 就把此视为文件之间有依赖关系。 从入口起点开始,webpack 递归地构建一个依赖图,这个依赖图包含着应用程序所需的每个模块.
默认的入口文件就是 ./src/index.js
。
在 webpack 配置文件中, 入口可以使用 entry
字段来进行配置:
module.exports = {
entry: './path/to/my/entry/file.js'
};
# 出口
output
属性告诉 webpack 在哪里输出它打包模块后生成的静态文件,以及如何命名这些文件,主输出文件默认为 ./dist/main.js
,其他生成文件的默认输出目录是 ./dist
。
通过配置文件中的 output
字段可以进行配置:
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'
}
};
# loader
loader 用于对模块的源代码进行转换
前面说, 在 webpack 中一切文件都被视为模块. loader 为 webpack 提供了一种处理多种文件格式的机制. 能够让 webpack 处理那些非 JavaScript 文件,并且先将它们转换为有效模块,然后添加到依赖中.
可以把 loader 理解为是一个转换器,负责把某种文件格式的内容转换成 webpack 可以支持打包的模块。
假如我们要让 webpack 加载 CSS 文件. 就需要配置相对应的 loader.
首先安装对应的 loader
npm install --save-dev css-loader
然后在 module.rules
字段下来配置相关的规则:
module.exports = {
module: {
rules: [
{
test: /\.css$/, // 匹配文件路径的正则表达式
use: 'css-loader' // 指定使用的 loader
}
]
}
};
# plugin
插件目的在于解决 loader 无法实现的其他事。通过添加我们需要的 plugin,可以满足更多构建中特殊的需求。例如,使用 uglifyjs-webpack-plugin
插件可以压缩 JS 代码.
# 一个简单的 webpack 配置
我们把上述涉及的几部分配置内容合到一起,就可以创建一个简单的 webpack 配置了,webpack 运行时默认读取项目下的 webpack.config.js
文件作为配置。
下面是一个配置示例:
const path = require('path')
const UglifyPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.jsx?/,
include: [
path.resolve(__dirname, 'src')
],
use: 'babel-loader',
},
],
},
// 代码模块路径解析的配置
resolve: {
modules: [
"node_modules",
path.resolve(__dirname, 'src')
],
extensions: [".wasm", ".mjs", ".js", ".json", ".jsx"],
},
plugins: [
new UglifyPlugin(),
// 使用 uglifyjs-webpack-plugin 来压缩 JS 代码
// 如果你留意了我们一开始直接使用 webpack 构建的结果,你会发现默认已经使用了 JS 代码压缩的插件
// 这其实也是我们命令中的 --mode production 的效果,后续的小节会介绍 webpack 的 mode 参数
],
}
webpack 的配置其实是一个 Node.js 的脚本,这个脚本对外暴露一个配置对象,webpack 通过这个对象来读取相关的一些配置。