webpack 是一个打包模块化 JavaScript 的工具,它会从入口模块出发,识别出源码中的模块化导入语句,递归地找出入口文件的所有依赖,将入口和其所有的依赖打包到一个单独的文件中。是工程化、自动化思想在前端开发中的体现。
webpack 安装
环境准备
在开始之前,请确保安装了 Node.js 的最新版本。使用 Node.js 的最新版本,可以提升 webpack 的打包速度。
安装方式
局部安装 (推荐)
npm init -y # 初始化npm配置⽂件npm install --save-dev webpack # 安装核⼼库npm install --save-dev webpack-cli # 安装命令⾏⼯具# 安装最新的4.x稳定版本npm i -D webpack@4.44.0# 安装指定版本npm i -D webpack@<version>
全局安装 (不推荐)
# 安装webpack V4+版本时,需要额外安装webpack-clinpm install webpack webpack-cli -g# 检查版本webpack -v# 卸载npm uninstall webpack webpack-cli -g
以全局的方式安装 webpack,会将项目中的 webpack 锁定到指定的版本,会造成不同的项目中因为 webpack 版本不同而导致冲突,构建失败,因此推荐以局部的方式将 webpack 安装到项目中。
启动 webpack
1、webpack 默认配置
- webpack默认支持 JS 模块和 JSON 模块
- 支持 CommonJS、ES module、AMD 等模块类型
- webpack4 支持零配置使用,但是很弱,稍微复杂些的场景都需要额外扩展
2、执行构建前的准备
- 新建工程目录 webpack-demo
- 在 webpack-demo 根目录中新建 src 文件夹
在 webpack-demo 根目录中新建 webpack.config.js 文件,添加默认配置
const path = require("path");module.exports = {// 必填 webpack执⾏构建⼊⼝entry: "./src/index.js",output: {// 将所有依赖的模块合并输出到main.jsfilename: "main.js",// 输出⽂件的存放路径,必须是绝对路径path: path.resolve(__dirname, "./dist")}};
在 src 文件夹中新建 index.js、index.json、other.js 文件
index.js
// index.jsconst json = require("./index.json"); // commonJS 模块类型import { add } from "./other.js"; ES module 模块类型
index.json
{name: "JSON"}
other.js
export function add(num1, num2) {return num1 + num2}
3、执行构建
执行 webpack 构建有两种方式: npx 方式和 npm script 方式
npx 方式
npx webpack
npm script 方式
使用这种方式执行 webpack 构建需要修改 package.json 文件中的 scripts 属性:
"scripts": {"test": "webpack"}
4、构建成功
构建成功后我们会发现根目录下多出一个 dist 目录,该目录就是 webpack 构建后的文件输出目录。目录里面会有一个 main.js 文件,该文件的名称是我们在 webpack.config.js 的 output 中定义的。main.js 文件是一个可执行的 JavaScript 文件,里面包含 webpackBootstrap 启动函数。
webpack 配置核心概念
chunk:是指代码块,一个 chunk 可能由多个模块组合而成,也用于代码合并与分割
bundle:webpack构建成功后的输出文件
entry:webpack 执行构建任务的入口文件
output:webpack 执行构建后,配置资源的输出位置和名称等
loader:模块转换器,让webpack可以支持转换更多的模块类型
plugin:webpack的功能扩展,借助 plugin,可以让 webpack更加强大
mode:打包构建模式,每种模式都会对应开启webpack自带的plugin
配置基础结构
一个 webpack 配置的基础结构如下:
module.exports = {entry: "./src/index.js", //打包⼊⼝⽂件output: "./dist", //输出结构mode: "production", //打包环境module: {rules: [//loader模块处理{test: /\.css$/,use: "style-loader"}]},plugins: [new HtmlWebpackPlugin()] //插件配置};
entry
指定 webpack 打包的入口文件,webpack 执行构建的第一步将从 entry 开始,可抽象成输入。webpack会根据 entry 递归的去寻找依赖,每个依赖都将被它处理,最后输出到打包成果中。
entry 的配置方式有三种方式:
字符串类型
入口模块的文件路径,可以是相对路径
entry: "./src/index.js"
数组类型
入口模块的文件路径,可以是相对路径
entry: ['./src/index.js', './src/main.js']
Object 类型
配置多个入口,每个入口生成一个 chunk
// 单入口 其本质是个字符串entry: {main: "./src/index.js"}// 上面的单入口配置方式相当于entry: "./src/index.js"// 多入口entry: {index: "./src/index.js",login: "./src/login.js"}
output
配置 webpack 打包转换后的文件输出到磁盘的位置,即配置如何输出 webpack 处理后的代码
output 是一个对象,必须有 filename 属性和 path 属性
- filename:输出文件的文件名
- path:输出文件到磁盘的目录,必须是绝对路径
单入口的输出
output: {filename: "bundle.js",//输出⽂件的名称path: path.resolve(__dirname, "dist")//输出⽂件到磁盘的⽬录,必须是绝对路径},
多入口的输出
多入口的输出需要使用占位符来区分输出的文件名
output: {filename: "[name][chunkhash:8].js",//利⽤占位符,⽂件名称不要重复path: path.resolve(__dirname, "dist")//输出⽂件到磁盘的⽬录,必须是绝对路径},
webpack 内置的占位符变量如下:
| 变量 | 描述 |
|---|---|
| [id] | chunk的唯一标识符,从 0 开始 |
| [name] | chunk 的名称 |
| [hash] | chunk 的唯一标识符的 hash |
| [chunkhash] | chunk 内容的 hash |
| [query] | chunk 的query,例如:文件名 ?后面的字符串 |
[hash] 和 [chunkhash] 的长度可以使用 [hash:16](默认为20)来指定。或者,通过指定output.hashDigestLength 在全局配置长度。
mode
用来指定当前的构建环境,mode 有三个值;
- production
- development
- none
| 选项 | 描述 |
| —- | —- |
| production | 会将
process.env.NODE_ENV的值设为production。启用FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin,OccurrenceOrderPlugin,SideEffectsFlagPlugin和UglifyJsPlugin. | | development | 会将process.env.NODE_ENV的值设为development。启用NamedChunksPlugin和NamedModulesPlugin| | none | 退出任何默认优化选项 |
设置mode可以⾃动触发webpack内置的函数,达到优化的效果;
如果没有设置,webpack 会将 mode 的默认值设置为 production;
记住,只设置
NODE_ENV,则不会自动设置mode
loader
模块转换器,用于把模块的源内容按照需求转换成新的内容。
webpack 默认只支持 JS 和 JSON 模块的解析,其他格式的模块例如 css、图片等则需要相应的 loader 来处理。
module: {rules: [{// 用正则取匹配要用该 loader 准换的 css 文件test: /\.css$/,use: ["style-loader", "css-loader"]}]}
loader 的另外两个配置选项 include 和 exclude:
include 包含哪些目录
module: {rules: [{// 用正则取匹配要用该 loader 准换的 css 文件test: /\.css$/,use: ["style-loader", "css-loader"],// 只包含 src 目录里的 css 文件,加快 webpack 的搜索速度include: path.resolve(__dirname, "src"),}]}
exclude 排除哪些目录
module: {rules: [{// 用正则取匹配要用该 loader 准换的 css 文件test: /\.css$/,use: ["style-loader", "css-loader"],// 排除 node_modules 目录下的文件exclude: path.resolve(__dirname, 'node_modules'),}]}
常用 loader
- style-loader
- css-loader
- sass-loader
- ts-loader 将 ts 转换成 js
- babel-loader 转换 ES6、ES7等 JavaScript 新特性语法
- file-loader 处理非文本文件,如图片、字体文件、PDF文件等
- eslint-loader
module
module 用于配置如何处理模块。在 webpack 里一切皆模块,一个模块对应着一个文件。webpack 会从 entry 开始递归找出所有依赖的模块。当 webpack 处理到不认识的模块时,就会去 module 里寻找对应的 loader 来处理其不认识的模块。因此我们需要在 module 里配置 loader,让webpack可以支持转换更多的模块类型。
module:{rules:[{test:/\.xxx$/,//指定匹配规则use:{loader: 'xxx-load'//指定使⽤的loader}}]}
在 module 的 rules 里配置模块的读取和解析规则,通常是用来配置 loader。其类型是一个数组,数组里的每一项都描述了如何去处理部分文件。
module:{rules:[{test:/\./,use: ["style-loader", "css-loader"]}]}
在上面的 loader 中:
- css-loader 分析css模块之间的关系,并合成⼀个css
- style-loader 会把css-loader⽣成的内容,以style挂载到⻚⾯的head标签里
plugins
plugins 用于扩展 webpack 功能,plugin的职责则是让webpack可以控制其构建流程,从⽽执⾏⼀些特殊的任务。插件的功能⾮常强⼤,可以完成各种各样的任务。
plugins 的配置很简单,plugins 配置项接受一个数组,数组里每一项都是一个要使用的 plugins 实例,plugins 需要的参数通过构造函数传入。
以 HtmlWebpackPlugin 为例:
module.exports = {plugins: [new htmlWebpackPlugin({title: "My App",filename: "app.html",template: "./src/index.html"})]};
htmlwebpackplugin会在打包结束后,⾃动⽣成⼀个html⽂件,并把打包⽣成的js模块引⼊到该html 中
npm install --save-dev html-webpack-plugin
htmlwebpackplugin 配置
title: ⽤来⽣成⻚⾯的 title 元素filename: 输出的 HTML ⽂件名,默认是 index.html, 也可以直接配置带有⼦⽬录。template: 模板⽂件路径,⽀持加载器,⽐如 html!./index.htmlinject: true | 'head' | 'body' | false ,注⼊所有的资源到特定的 template 或者templateContent 中,如果设置为 true 或者 body,所有的 javascript 资源将被放置到 body元素的底部,'head' 将放置到 head 元素中。favicon: 添加特定的 favicon 路径到输出的 HTML ⽂件中。minify: {} | false , 传递 html-minifier 选项给 minify 输出hash: true | false, 如果为 true, 将添加⼀个唯⼀的 webpack 编译 hash 到所有包含的脚本和CSS ⽂件,对于解除 cache 很有⽤。cache: true | false,如果为 true, 这是默认值,仅仅在⽂件修改之后才会发布⽂件。showErrors: true | false, 如果为 true, 这是默认值,错误信息会写⼊到 HTML ⻚⾯中chunks: 允许只添加某些块 (⽐如,仅仅 unit test 块)chunksSortMode: 允许控制块在添加到⻚⾯之前的排序⽅式,⽀持的值:'none' | 'default' |{function}-default:'auto'excludeChunks: 允许跳过某些块,(⽐如,跳过单元测试的块)
htmlwebpackplugin 使用案例
const path = require("path");const htmlWebpackPlugin = require("html-webpack-plugin");module.exports = {plugins: [new htmlWebpackPlugin({title: "My App",filename: "app.html",template: "./src/index.html"})]};
//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" /><title><%= htmlWebpackPlugin.options.title %></title></head><body><di v id="root"></div></body></html>
