webpack4.15.1 学习笔记(一) — 基本概念
终终终终于下定决心,对你下手了,系统的学习一下。
webpack是一个应用程序的静态模块打包器(module bundler)。处理应用程序时,会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
入口(entry)
指示应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出入口起点直接和间接依赖的 模块和库。
webpack.config.js
// 单个入口
module.exports = {
entry: {
main: './main.js'
}
};
// 单个入口 简写语法
module.exports = {
entry: './main.js'
};
// 多页面应用程序,
module.exports = {
entry: { // 告诉 webpack 需要 3 个独立分离的依赖图
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
};
在多页应用中,每当页面跳转时服务器将获取一个新的 HTML 文档。页面重新加载新文档,并且资源被重新下载。每个 HTML 文档只使用一个入口起点。
出口(output)
可以控制 webpack 如何向硬盘写入编译文件。输出webpack所创建的 bundles,以及如何命名这些文件,默认值为 ./dist
。即使可以存在多个入口
起点,但只指定一个输出配置
。基本上,整个应用程序结构,都会被编译到指定的输出路径的文件夹中。
const path = require('path');
module.exports = {
// ...
output: {
path: path.resolve(__dirname, 'dist'), // 目标输出目录的绝对路径。
filename: 'my-first-webpack.bundle.js' // 输出文件的文件名。
}
};
多入口起点
如果配置创建了多个单独的 "chunk"(例如,使用多个入口起点或使用像 CommonsChunkPlugin 这样的插件),则应该使用占位符来确保每个文件具有唯一的名称。
{
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
}
// 写入到硬盘:./dist/app.js, ./dist/search.js
加载器 Loaders
处理非 JavaScript 文件(webpack 自身只理解 JavaScript)。将所有类型的文件转换为 webpack 能够处理的有效模块,然后就可以利用 webpack 的打包能力,对它们进行处理。
本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块,能够 import
导入任何类型的模块(例如 .css
文件),是 webpack 特有的功能。
loader 支持链式传递。能够对资源使用流水线。一组链式的 loader 将按照相反的顺序执行。
有三种使用 loader 的方式:
- 一、配置(推荐):在 webpack.config.js 文件中指定 loader。
- 二、内联:在每个
import
语句中显式指定 loader。 - 三、CLI:在 shell 命令中指定它们。
一、webpack 配置中定义 loader 时,要定义在 module.rules
中
test
属性:标识需要 loader 转换的某个或某些文件。use
属性:转换时使用的 loader。
module.exports = {
// ...
module: {
rules: [
{
test: /\.less/, // require()/import 解析路径为 '.less' 时,打包之前,先使用下方loader转换一下
use: ["style-loader", "css-loader", "less-loader"],
}
]
}
};
二、内联
可以在 import
语句或任何等效于 "import" 的方式中指定 loader。使用 !
将资源中的 loader 分开。分开的每个部分都相对于当前目录解析。
import Styles from 'style-loader!css-loader?modules!./styles.css';
通过前置所有规则及使用 !
,可以对应覆盖到配置中的任意 loader。
尽可能使用 module.rules
,因为这样可以减少源码中的代码量,并且可以在出错时,更快地调试和定位 loader 中的问题。
三、CLI
对 .jade
文件使用 jade-loader
,对 .css
文件使用 style-loader
和 css-loader
。
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
插件 Plugins
插件可以用于执行范围更广的任务。包括:打包优化、压缩、重新定义环境中的变量。通过 require()使用一个插件,然后把它添加到 plugins
数组中。多数插件可以自定义选项(option)。可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new
操作符来创建它的一个实例。
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件
module.exports = {
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
webpack 插件是一个具有
apply
属性的 JavaScript 对象。apply
属性会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问。
ConsoleLogOnBuildWebpackPlugin.js
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler) {
compiler.hooks.run.tap(pluginName, compilation => {
console.log("webpack 构建过程开始!");
});
}
}
compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它可以在所有 hook 中复用。
模式
通过选择 development
或 production
之中的一个,来设置 mode
参数,可以启用相应模式下的 webpack 内置的优化
module.exports = {
mode: 'production'
};
或者从CLI 参数中传递:
webpack --mode=production
webpack.config.js 配置
- 通过
require(...)
导入其他文件 - 通过
require(...)
使用 npm 的工具函数 - 使用 JavaScript 控制流表达式,例如
?:
操作符 - 对常用值使用常量或变量
- 编写并执行函数来生成部分配置
- 调用 webpack 两次应该产生同样的输出文件
- 编写很长的配置时,应该将配置拆分为多个文件