欲学 webpack,必会这几个核心概念:
- entry(入口)
- output(输出)
- loader
- plugin(插件)
- mode(模式)
entry
entry 是用来指定 webpack 的打包入口。
entry 是 webpack 中一个很重要的概念,从 webpack 的构建机制来看,webpack 是一个模块打包器,也就是说它会将所有的资源(除了 js、css 等代码资源,也包括图片、字体依赖等非代码资源)都当成一个个的模块,而模块之间会存在一个依赖关系。所以,webpack 需要一个 入口文件 来进入这棵 依赖树(如下图):
用法
entry
的默认值是 ./src/index.js
,我们可以 webpack 的配置文件中修改它。entry
会有两种情况:单入口 和 多入口。
单入口
单入口适用于 SPA(单页应用)的场景,值是一个字符串:
module.exports = {
entry: "./src/index.js",
};
多入口
多入口适用于多页应用的场景,值是一个对象:
module.exports = {
entry: {
app: "./src/app.js",
adminApp: "./src/adminApp.js",
},
};
output
output 用于告诉 webpack 将编译后的文件存放到哪里,主要输出文件的默认值是 ./dist/main.js
,其他生成文件默认放置在 ./dist
文件夹中。
用法
单入口
在单入口的场景下,output 只需要简单指定一下文件名称( filename
)和路径( path
):
const path = require('path');
module.exports = {
//...
output: {
filename: "bundle.js",
path: path.resolve(__dirname, 'dist'),,
},
};
多入口
不管是多少个入口文件( entry
),都只有一个 output
,那么怎么确保文件名称的唯一性呢?利用占位符,比如 [name]
。
const path = require('path');
module.exports = {
//...
output: {
filename: "[name].js",
path: path.resolve(__dirname, 'dist'),,
},
};
这里来举一个 🌰:
接上一篇文章的项目,我们改造为一个多页面应用。
-
添加一个新入口
./src/admin.js
document.write("hello admin !");
-
修改 webpack.config.js
const path = require("path"); module.exports = { entry: { index: "./src/index.js", admin: "./src/admin.js", }, // 多入口 output: { filename: "[name].js", // 使用占位符 path: path.resolve(__dirname, "dist"), }, mode: "production", };
-
删除原来的 dist(如果存在的话)
rm -rf ./dist
-
webpack 打包
npx webpack
我们在 dist 文件夹中可以看到打包后的结果:
Loader
原生的 webpack 仅支持 JS 和 JSON 两种文件类型(这是 webpack 开箱可用的自带能力),这对于现代的前端项目肯定是不够用的,那么对于 CSS、LESS、JSX、vue 等类型的文件该怎么办呢?
Loader 就是来帮助我们扩展 webpack,通过 Loader 可以支持 webpack 不支持的其他文件类型并且把它们转化为有效的模块,然后添加到依赖关系图中。
Loader 的本身是一个函数,接受源文件作为参数,最终返回转化的结果。
常见的 Loader
名称 | 描述 |
---|---|
babel-loader | 转换 ES6、ES7 等 JS 新特征语法 |
css-loader | 支持.css 文件的加载和解析 |
less-loader | 将 less 文件转换成 css 文件 |
ts-loader | 将 ts 文件转换成 js 文件 |
file-loader | 进行图片、字体等打包 |
raw-loader | 将文件以字符串的形式导入 |
thread-loader | 多进程打包 JS 和 CSS |
用法
loader 的配置,我们放在一个单独的 module 对象的 rules 中,rules 作为一个数组可以添加多个 loader,通过两个属性配置 loader:
test
属性,指定匹配规则,识别出哪些文件会被转换。use
属性,指定使用的 loader 名称,即在进行转换时,应该使用哪个 loader。
webpack.config.js:
const path = require("path");
module.exports = {
// ...
module: {
rules: [{ test: /\.txt$/, use: "raw-loader" }],
},
};
Plugin
Loader 用于处理 webpack 无法解析的文件,而 Plugin 则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。Plugin 就像是帮 Loader 完成了无法完成的事情,他可以作用于整个构建过程。
常见的 Plugin
名称 | 描述 |
---|---|
CommonsChunkPlugin | 多个页面打包,将 chunks 相同的模块代码提取成公共 js |
CleanWebpackPlugin | 清理构建目录 |
ExtractTextWebpackPlugin | 将 CSS 从 bundle 文件中提取成一个独立的 CSS 文件 |
CopyWebpackPlugin | 将文件/文件夹拷贝到构建的输出目录去 |
HtmlWebpackPlugin | 创建 html 文件去承载输出的 bundle |
UglifyjsWebpackPlugin | 压缩 JS |
ZipWebpackPlugin | 将打包后的资源生成 zip 包 |
用法
在 webpack 配置中使用插件是简单直接的,想要使用一个插件,你只需要 require()
它,然后把它的实例(通过使用 new 操作符)添加到 plugins
数组中。
webpack.config.js:
const HtmlWebpackPlugin = require("html-webpack-plugin"); // 通过 npm 安装
const webpack = require("webpack"); // 用于访问内置插件
module.exports = {
// ...
plugins: [new HtmlWebpackPlugin({ template: "./src/index.html" })],
};
Mode
Mode 是用来指定当前的构建环境是:production
、development
或 none
,默认值为 production
。设置 mode 可以自动触发 webpack 的内置函数,比如 mode 为 development
,那么 webpack 会自动开启在开发阶段更实用的参数/功能等,如果设置为 none
,webpack 将不做任何操作。
Mode 的内置函数
选项 | 描述 |
---|---|
development | 设置 process.env.NODE_ENV 为 development ,开启 NamedChunksPlugin 和 NamedModulesPlugin (在热更新中,可以看到具体更新的模块) |
production | 设置 process.env.NODE_ENV 为 production ,开启 FlagDependencyUsagePlugin 、FlagIncludedChunksPlugin 、ModuleConcatenationPlugin 、NoEmitOnErrorsPlugin 、OccurrenceOrderPlugin 、SideEffectsFlagPlugin 和 TerserPlugin |
none | 不开启任何优化选项 |