Webpack使用(入门篇)
Webpack是什么
本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容
静态模块:指的是编写代码过程中的,html,css,js,图片等固定内容的文件
注意: 只有和入口有直接/间接的引入关系的模块,才会被打包
webpack 主要是用于前端工程化。主要功能是:把静态模块内容压缩、整合和转义等。例如,把 less / sass 转成 css 代码,把 ES6+ 降级成 ES5,支持多种模块文件类型,多种模块标准语法。目前很多项目依旧基于 webpack 进行构建,webpack 目前仍是前端工程师必须掌握的工具之一
本文将通过一个简单的示例介绍Webpack的五大核心模块:
entry
(入口):入口提示webpack以哪个文件为起点开始打包,分析构建内部依赖图output
(出口):输出提示webpack打包后的资源输出到哪,以及如何命名module
(loader加载器):让webpack能够处理非 JS 文件(webpack自身只能理解js/json,不能处理css/img等其他资源)plugin
(插件):插件可以用于执行范围更广的任务。插件范围包括:从打包优化到压缩,一直到重新定义环境中的变量等mode
(模式):
- 开发模式:能让代码本地调试的环境
process.env.NODE_NEV = development
- 生产模式:能让代码优化上线运行的环境
process.env.NODE_NEV = production
Webpack初使用
我们用一个实际例子来体会 webpack 使用全过程:
- 封装 utils 包,校验用户名和密码长度,在 index.js 中使用,使用 Webpack 打包
步骤:
-
新建项目文件夹,初始化包环境
npm init -y # 注意,项目文件夹不能为中文,只能为小写字母和小横杠(-)
在新文件夹中输入cmd打开终端(当然,也可以使用 vscode 自带的终端):
初始化后,项目结构如下:
-
新建
src
源代码文件夹(书写代码)包括 utils/check.js 封装用户名和密码长度函数,引入到 src/index.js 进行使用项目结构如下:
JavaScript 文件的引入使用 ES6 语法:
export default {}
、import 变量名 from '模块名或路径'
export 修饰定义语句
、import {同名变量} from '模块名或路径'
-
下载 webpack webpack-cli 到项目(版本独立)
npm i webpack webpack-cli --save-dev # 此处的 --save-dev 等同于 -D 开发时的依赖。里面的模块是开发时用的,发布时用不到它
注意:虽然 webpack 是全局软件包,封装的是命令工具,但是为了保证项目之间版本分别独立,推荐使用局部安装。因为每个项目使用的 webpack 版本可能不一致,所以全局安装会导致之前项目用的老版本webpack 被覆盖掉
随后把 webpack 命令配置到 package.json 中的 scripts 自定义命令,作为局部命令使用
-
项目中运行工具命令,采用自定义命令的方式(局部命令)
npm run build
npm run
自定义命令名字
注意:实际上在终端运行的是 build 右侧的具体命名
如图所示,即为打包成功:
-
自动产生 dist 分发文件夹(压缩和优化后,用于最终运行的代码)
打包后项目结构如下:
Webpack 默认入口和出口分别为:
src/index.js
和dist/main.js
整个过程如下图所示:
Webpack出入口修改
入口(entry ) 属性指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。默认值是 ./src/index.js
,但你可以通过在 webpack configuration 中配置 entry
属性,来指定一个(或多个)不同的入口起点
出口(output) 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js
,其他生成文件默认放置在 ./dist
文件夹中。你可以通过在配置中指定一个 output
字段,来配置这些处理过程
path.join
方法将多个路径片段拼接在一起,并根据操作系统的规则生成正确的路径
path.resolve
方法根据参数生成一个绝对路径。如果传入的路径是绝对路径,则直接返回该路径;如果传入的是相对路径,则根据当前工作目录生成绝对路径
操作步骤:
-
在项目根目录,新建 Webpack.config.js 配置文件。此处建议使用 vscode-icon/Material Icon Theme 插件,此插件能让项目结构更加清晰
-
导出配置对象,配置入口,出口文件路径
const path = require('path') module.exports = { // 入口: 可以使用相对路径 entry: './src/main.js', // entry: path.resolve(__dirname, 'src/main.js'), // 入口 // 出口 output: { // 路径必须是绝对路径 path: path.join(__dirname, 'dist'), // 在该路径下输出什么文件名 filename: 'app.js', clean: true // 先清空 dist,然后再输出最新内容 }, }
打包前的项目结构如下图所示:
-
重新打包观察
注意:此时由于我们更改了入口为
main.js
,因此我们要把index.js
重命名为main.js
,或者新建一个main.js
文件也可,这里我们采用重命名的形式打包后项目结构如下(此时的出入口已经更改成功):
webpack打包出入口更多配置项请查阅官网:webpack中文文档
Webpack自动生成html文件
webpack本身是不能自动生成html文件的,但我们可以使用 webpack 的 html-webpack-plugin 插件,该插件主要作用是在 Webpack 打包时生成 html 文件,并引入其他打包后的资源
该插件安装步骤如下:
-
下载 html-webpack-plugin 本地软件包到项目中
npm i html-webpack-plugin --save-dev
与上文一样,此处的 --save-dev 等同于 -D 开发时的依赖。里面的模块是开发时用的,发布时用不到它。webpack插件都应该带上 -D,只有开发时才用到
-
配置 webpack.config.js 让 Webpack 拥有插件功能
// ... const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // ... plugins: [ // 插件列表 new HtmlWebpackPlugin({ // 以指定的 html 文件作为生成模板 template: path.resolve(__dirname, 'public/index.html') }) ] };
此插件指定以 public/index.html 为模板复制到 dist/index.html,并自动引入其他打包后资源
如果设置后打包时报错,很有可能是plugins中的p大写了,建议直接官网复制,避免不必要的麻烦
此处指定 public 文件夹下的 index.html文件,我们在项目中新建该文件夹,并引入 index.html 文件:
<!-- index.html网页骨架 --> <div class="img-wrap"> <img class="logo-img" src="" alt=""> </div> <div class="login-wrap"> <form action="javascript:;"> <div class="form-item"> <span>用户名:</span> <input type="text" class="username"> </div> <div class="form-item"> <span>密码:</span> <input type="password" class="password"> </div> <div class="form-item"> <button class="login-btn">注 册</button> </div> </form> </div>
-
运行打包命令,观察打包后 dist 文件夹下内容(js 逻辑写到 main.js 中)
项目结构如下:
成功在 dist 文件夹中生成了压缩后的 index.html 文件,并且会自动把输出的 js 文件自动引入到 html 中
Webpack打包css代码
webpack 默认只识别 JS 和 JSON 文件内容,所以想要让 webpack 识别更多不同内容,需要使用加载器。 webpack 支持使用 loader 对文件进行预处理。你可以构建包括 JavaScript 在内的任何静态资源。并且可以使用 Node.js 轻松编写自己的 loader
webpack 需要两个加载器来辅助才能打包 css 代码:
- 加载器 css-loader:解析 css 代码
- 加载器 style-loader:把解析后的 css 代码插入到 DOM(style 标签之间)
使用步骤如下:
-
准备 css 文件引入到 src/main.js 中(压缩转译处理等)
import './css/index.css'
注意:这里只是引入代码内容让 Webpack 处理,不需定义变量接收在 JS 代码中继续使用,所以没有定义变量接收。引入 css 模块后,webpack 会帮我们去加载 css 文件并解析
-
下载 css-loader 和 style-loader 本地软件包
npm i css-loader style-loader --save-dev
-
配置 webpack.config.js 让 Webpack 拥有该加载器功能
// ... module.exports = { // ... module: { // 加载器 // 匹配规则, 遇到什么文件, 用什么 loader 加载, webpack 没有加载各种文件的能力, 它只能交给不同的loader 去帮忙加载 rules: [ { test: /\.css$/i, // 匹配 .css 结尾的文件 // 交给两个 loader 帮忙解析 // loader 的执行顺序是从右到左的 // webpack 先读取了 css 文件, 交给 css-loader 帮忙解析 css 语法, 解析完毕后交给 style-loader, 帮忙将解析完毕的 css 插入到网页的 style 标签中 use: ['style-loader', 'css-loader'], } ] } };
-
打包后运行 dist/index.html 观察效果,看看准备好的样式是否作用在网页上
项目结构如下:
配置好重新打包后,css 样式被合并到了 app.js 中,此时样式已经引入到 html 页面中
Webpack打包less代码
加载器 less-loader:把 less 代码编译为 css 代码,还需要依赖 less 软件包。与 css 加载器功能类似,让 Webpack 拥有打包 less 代码功能
使用步骤如下:
-
准备 less 样式引入到 src/main.js 中
import './less/index.less'
-
下载 less 和 less-loader 本地软件包
npm i less less-loader --save-dev
-
配置 webpack.config.js 让 Webpack 拥有功能
// ... module.exports = { // ... module: { // 加载器 rules: [ // 规则列表 // ... { // 打包 less 需要安装 less 和 less-loader 两个包, 其他配置和 css-loader 差不多 test: /\.less$/i, use: [ // compiles Less to CSS 'style-loader', 'css-loader', 'less-loader', ], }, ] } };
-
打包后运行 dist/index.html 观察效果,此处与 css 类似,不再赘述。此外,最好是把 easy less 插件禁用或者卸载,以免引起不必要的麻烦
Webpack打包图片
资源模块:Webpack 内置了资源模块的打包,无需下载额外 loader
使用步骤:
-
准备图片素材到 src/assets 中(存放资源模块 - 图片/字体图标等)
项目结构如下:
-
在 index.less 中给 body 添加背景图
body{ background: url(../assets/background.png) no-repeat center center; }
-
在 main.js 中给 img 标签添加 logo 图片
/** 目标:要给 img 标签设置一个 logo 图片 注意:再赋予给 img 的 src 属性图片的时候,需要把图片数据对象引入过来 */ import imgObj from './assets/logo.png' document.querySelector('.logo-img').src = imgObj
-
配置 webpack.config.js 让 Webpack 拥有打包图片功能
// ... module.exports = { // ... module: { // 加载器 rules: [ // 规则列表 // ... { // 针对资源模块(图片,字体文件,图标文件等)处理 test: /\.(png|jpg|jpeg|gif)$/i, type: 'asset', // 根据文件大小(8KB)小于:把文件转成 base64 打包进 js 文件中(减少网络请求次数)大于:文件复制到输出的目录下 // webpack 的 asset 类型, 自动帮我们区分图片大小来决定是否要转换成 BASE64 格式的字符串 // 8KB 是判断标准, 超过了就不转, 没超过就转换成 BASE64 // 转 BASE64 // 好处: 少发一次请求 // 坏处: 文件体积会增大 33.4% generator: { // 输出文件时,路径 + 名字 // [] 内置变量 // [hash] 自动生成随机的唯一字符串, 避免冲突 // [ext] 后缀名 filename: 'assets/[hash][ext]' } } ] } };
-
打包后运行 dist/index.html 观察效果
注意:
- 小于 8KB 文件会被转成 data URI(base64 字符串)打包进 JS 文件中(好处:可以减少网络请求次数,缺点:增加 30% 体积)
- 大于 8KB 文件会被复制到 dist 下,自动替换使用代码的图片名字
Webpack集成 babel 编译器
babel 定义:是一个 JavaScript 语法编译器,将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中
babel-loader:让 Webpack 可以使用 babel 转译 JavaScript 代码
使用步骤:
-
下载 babel babel-loader core 本地软件包
npm i babel-loader @babel/core @babel/preset-env -D
-
配置 webpack.config.js 让 Webpack 拥有功能
// ... module.exports = { // ... module: { // 加载器 rules: [ // 规则列表 // ... { test: /\.m?js$/, exclude: /(node_modules|bower_components)/, // 排除指定目录里的 js (不进行编译降级) use: { loader: 'babel-loader',// 使用 babel-loader 来加载文件 options: { presets: ['@babel/preset-env'] // 预设规则 } } } ], } };
-
打包运行 dist/index.html 观察效果
各个软件包的作用表格:
模块 | 作用 |
---|---|
@babel/core | Js 编译器,分析代码 |
@babel/preset-env | babel 预设,规则 |
babel-loader | 让 webpack 翻译 js 代码 |
Webpack开发服务器
每次改动代码,都要重新打包,十分不便,所以这里给项目集成 webpack-dev-server 开发服务器
作用:启动 Web 服务,打包输出源码在内存,并会自动检测代码变化热更新到网页
使用步骤:
-
下载 webpack-dev-server 软件包到当前项目
npm i webpack-dev-server --save-dev
-
配置自定义命令,并设置打包的模式为开发模式
"scripts": { // ... "dev": "webpack serve --mode=development" },
-
使用 npm run dev 来启动开发服务器,访问提示的域名+端口号,在浏览器访问打包后的项目网页,修改代码后,试一试热更新效果
可以使用 http://localhost:8080/ 或者 http://192.168.80.94:8080/ 访问。在 js / css 文件中修改代码保存后,会实时反馈到浏览器
Webpack打包模式
打包模式:提供 mode
配置选项,告知 Webpack 使用相应模式的内置优化
分类:
模式名称 | 模式名字 | 特点 |
---|---|---|
开发模式 | development | 调试代码,实时加载,模块热替换等 |
生产模式 | production | 压缩代码,资源优化,更轻量等 |
如何设置影响 Webpack
-
方式1:在 webpack.config.js 配置文件设置 mode 选项
// ... module.exports = { // ... mode: 'production' }
-
方式2:在 package.json 命令行设置 mode 参数
"scripts": { "build": "webpack --mode=production", "dev": "webpack serve --mode=development" },
注意:命令行设置的优先级高于配置文件中的,推荐用命令行设置
Webpack开发环境调错source map
代码被压缩和混淆,无法正确定位源代码位置(行数和列数),source map 为我们解决了这个问题。source map 可以准确追踪 error 和 warning 在原始代码的位置
设置:webpack.config.js 配置 devtool 选项
// ...
module.exports = {
// ...
devtool: 'inline-source-map'
}
//inline-source-map 选项:把源码的位置信息一起打包在 JS 文件内
注意:source map 适用于开发环境,不要在生产环境使用(防止被轻易查看源码位置)
Webpack设置解析别名路径
设置 Webpack 如何设置路径别名,方便我们引入目标模块。解析别名:配置模块如何解析,创建 import 或 require 的别名,来确保模块引入变得更简单
例如:
-
原来路径如下:
import { checkUsername, checkPassword } from '../src/utils/check.js'
-
配置解析别名:在 webpack.config.js 中设置
// ... module.exports = { // ... resolve: { alias: { MyUtils: path.resolve(__dirname, 'src/utils'), '@': path.resolve(__dirname, 'src') } } }
-
这样我们以后,引入目标模块写的路径就更简单了
import { checkUsername, checkPassword } from 'MyUtils/check.js' import { checkUsername, checkPassword } from '@/utils/check.js'
转载自:https://juejin.cn/post/7276281005743390761