webpack:基本打包方法
@jarringslee
文章目录
webpack入门
webpack是一个用于现代js应用程序的 现代模块打包工具。当webpack处理应用程序时,它会在内部从一个或多个入口点构建一个依赖图(dependency graph),然后将项目中所需的每一个模块组合成一个或多个bundles,它们均为静态资源,用于展示内容。
静态模块指编写代码过程中的html css js 图片等固定内容的文件。
打包指将静态模块内容压缩、整合、转译等,即 前端工程化
- 把 less / sass 代码转成css代码
- 把 ES6+ 可降级成 ES5
- 支持多种模块标准语法

使用webpack进行打包
基本打包步骤
步骤:
-
新建并初始化项目,编写业务源代码
-
下载软件包: 下载
webpack webpack-cli到当前项目中,并配置局部自定义命令。一般下载全局软件包,也可以分别在各自项目文件夹中下载不同版本的软件包。bashnpm i webpack webpack-cli --save-dev下载后,在package.json字符串中输入以下命令:
json"scripts":{ "build": "webpack" },build是自定义的名字,表示在终端中输入npm run build就会执行冒号后的命令。
-
运行打包命令
bashnpm run buildwebpack打包并输送到当前项目文件夹中的dist目录中的main.js出口文件。
需求:封装utils包,校验手机号长度和验证码长度,在src/index.js中使用并打包观察
-
创建项目文件夹,并创建src文件夹
-
在src文件夹中创造utils文件夹并在里面创造js文件存放工具函数
js// check.js // 封装两个函数:校验手机号码长度和验证码长度 // 采用ECMAScript命名标准导出 export const checkPhone = phone => phone.length === 11 export const checkCode = code => code.length === 6 -
在src文件夹中创造index.js文件把函数打包过来(如果用ECMAScript方法的话,需要在后面json文件出来后在里面添加:"type": "module"),并使用该函数(可以用console.log())
js// index.js // 体验webpack打包过程 import { checkPhone, checkCode } from './utils/check.js' console.log(checkPhone('12312341234')) console.log(checkCode('12345678')) -
准备webpack打包环境:在项目所在终端中输入
npm i webpack webpack-cli --save-dev,随后在pack.json文件中找到"scripts":{}并添加"build": "webpack" -
运行自定义命令并观察效果:
npm run 自定义命令
命令成功后,会自动在总文件夹下创造dist文件夹并在其中创造main.js文件,在其中实现代码的压缩:
js
(()=>{"use strict";console.log(!0),console.log(!1)})();
修改打包入口和出口
有时候打包前端代码时,文件入口有可能不是src下的index.js文件,出口也有可能不是main.js文件
步骤:
- 在项目根目录中设置webpack.js配置文件
- 导出配置对象、配置入口、出口文件的路径
- 重新打包观察
注意:只有和入口产生直接 / 间接的引入关系,才会被一块打包。
参考文档:概念 | webpack入口配置
入口起点设置:
入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
默认值是
./src/index.js,但你可以通过在 webpack configuration 中配置entry属性,来指定一个(或多个)不同的入口起点。例如:创建项目配置文件
webpack.config.js,放在项目的根目录下
jsmodule.exports = { entry: './path/to/my/entry/file.js', };
出口起点设置:
output 属性告诉 webpack 在哪里输出它所创建的 bundle ,以及如何命名这些文件。主要输出文件的默认值是
./dist/main.js,其他生成文件默认放置在./dist文件夹中。你可以通过在配置中指定一个
output字段,来配置这些处理过程:webpack.config.js
javascript// commonjs 语法 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', clean:true // 生成新的打包内容之前先清空输出目录 }, };
js// ECMAScript 语法(ESM) import path from 'path'; import { fileURLToPath } from 'url'; // 在 ESM 中模拟 __dirname const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export default { // 入口路径,相对或绝对均可 entry: './path/to/my/entry/file.js', output: { // 只能导出一个对象 // 打包文件存放的目录(绝对路径) path: path.resolve(__dirname, 'dist'), // 打包出来的文件名(可含子目录) filename: 'my-first-webpack.bundle.js', clean:true // 生成新的打包内容之前先清空输出目录 }, };在上面的示例中,我们通过
output.filename和output.path属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成(emit)到哪里。可能你想要了解在代码最上面导入的 path 模块是什么,它是一个 Node.js 核心模块,用于操作文件路径。
小案例:用户登录-长度判断
需求:点击登录按钮,判断手机号和验证码长度
步骤:
- 准备用户登录界面
- 编写核心js逻辑代码
- 打包并手动复制网页到dist下,引入打包后的js并运行
核心:webpack打包后的代码,作用在前端网页中使用。
设置及打包其它文件
自动生成html文件
插件:html-webpack-plugin 在webpack打包时生成html文件,帮你把打包好的js和css等模块引入好。
步骤:
-
在当前项目中配置好webpack环境;
-
下载
html-webpack-plugin本地软件包bashnpm install --save-dev html-webpack-plugin -
配置 webpack.config.js 文件,让 webpack 拥有插件功能
ECMAScript方法:
js// webpack.config.js // 引入plugins对象 import HtmlWebpackPlugin from 'html-webpack-plugin'; // 在 ESM 里模拟 __dirname const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export default { // ......设置其他内容。如更改出入口文件 // 插件:给webpack提供更多的功能 plugins: [ new HtmlWebpackPlugin({ title: 'ljl', // 可去掉 template: path.resolve(__dirname, 'public/login.html'), //模版文件的路径 filename: path.resolve(__dirname, 'dist/login/index.html') //输出文件的路径 }) ] };commonJS方法:
js// webpack.config.js const path = require('path'); // 引入plugins对象 const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // ......设置其他内容。如更改出入口文件 // 插件:给webpack提供更多的功能 plugins: [ new HtmlWebpackPlugin({ title: 'ljl', // 可去掉 template: path.resolve(__dirname, 'public/login.html'), //模版文件的路径 filename: path.resolve(__dirname, 'dist/login/index.html') //输出文件的路径 }) ] }; -
重新打包并观察效果。
打包css代码
前情提要:webpack只识别js代码
加载器: css-loader 解析css代码
加载器:style-loader 把解析后的css代码插入到dom中
步骤:
-
准备css文件代码到 src/login/index.js 中(压缩转译处理等)
-
下载 css-loader 和 style-loader 本地软件包
jsnpm i --save-dev css-loaderbashnpm i --save-dev style-loader -
配置 webpack.config.js 文件,让webpack拥有加载器功能
js// webpack.config.js export default { // ...... // 加载器:让webpack识别更多模块文件的内容 module: { rules: [ { test: /\.css$/i, use: ['style-loader', 'css-loader'], }, ], } }; -
打包并观察效果
美化css样式
下载软件包: Bootstrap
步骤:
-
通过npm下载Bootstrap软件包
bashnpm i bootstrap -
在入口文件中引入下载好的特定的Bootstrap文件
js//index.js (入口文件) import 'bootstrap/dist/css/bootstrap.min.css' // 先引入Bootstrap文件 import './index.css' // 再引入css文件 -
打包并观察效果
提取css代码
这是一个优化的行为。将css代码单独提取成一个文件,因为css文件可以被浏览器缓存,让css文件和js文件同步下载到网页中,减少js体积
插件:mini-css-extract-plugin 提取css代码
注意 不能和style-loader一起使用
步骤:
-
下载 mini-css-extract-plugin 本地软件包
bashnpm i --save-dev mini-css-extract-plugin -
配置 webpack.config.js 让 webpack 拥有该插件功能
引入插件
js// commonjs const MiniCssExtractPlugin = require('mini-css-extract-plugin')js// ECMAScript import MiniCssExtractPlugin from 'mini-css-extract-plugin'修改配置
修改加载器部分:
js//把 use: ['style-loader', 'css-loader'], 改为: use: [MiniCssExtractPlugin.loader, 'css-loader'], -
打包后观察效果
压缩css代码
在使用minicssextractplugin提取css文件时,我们编写的css部分没有被压缩,只有bootstrap部分是压缩好的。
压缩所有css代码:使用 css-minimizer-webpack-plugin 插件
步骤:
-
下载 css-minimizer-webpack-plugin 本地软件包
bashnpm install css-minimizer-webpack-plugin --save-dev -
配置webpack.config.js
引入插件
js// commonjs const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');js// ECMAScript import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'修改配置
jsexport default { // ...... // css优化 optimization: { // 最小化 minimizer: [ // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释,即同样压缩js代码 `...`, new CssMinimizerPlugin(), ], }, }; -
打包并观察效果
打包less代码
加载器: less-loader 把less代码转换为css代码
less是增强版的css语言,支持在css中添加变量、嵌套、混合编写。
less-loader需要配合less软件包一起使用
步骤:
-
新建 less 代码(设置背景图)并引入到 src/login/index.js 中
-
下载 less 和 less-loader 两个npm安装包
jsnpm i less less-loader --save-dev -
配置webpack.config.js
jsmodule.exports = { // ...... module: rules: [ // css规则 //...... // less规则 { test: /\.less$/i, use: [ // compiles Less to CSS // 'style-loader', 不能和minicssextractplugin混用 MiniCssExtractPlugin.loader, 'css-loader', 'less-loader', ], }, ], }, }; -
打包并观察效果
小问题:这里在打包之后可能会失去原有的css样式。
原因:打包之后index.less的内容覆盖了index.css的内容(即打包后,index.css文件中的内容被替换成了index.less文件的内容)
一般情况下,只需要把css文件的原内容再次填进去并重新打包即可。
其他解决方法:
方法一:调整 import 顺序
把你想优先的 CSS 放后面:
jsimport 'bootstrap/dist/css/bootstrap.min.css' import './index.less' import './index.css' // 优先级最高,放最后方法二:把 index.css 内容写进 index.less 里
避免了很多麻烦
css/* index.less */ @color: red; body { background: @color; } /* 把 index.css 的内容复制到这里 */ ...
打包图片
资源模块:webpack5 内置资源模块(字体、图片等)打包,无需配置额外的loader
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
asset/resource发送一个单独的文件并导出 URL。之前通过使用file-loader实现。asset/inline导出一个资源的 data URI。之前通过使用url-loader实现。asset/source导出资源的源代码。之前通过使用raw-loader实现。asset在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用url-loader,并且配置资源体积限制实现。当在 webpack 5 中使用旧的 assets loader(如
file-loader/url-loader/raw-loader等)和 asset 模块时,你可能想停止当前 asset 模块的处理,并再次启动处理,这可能会导致 asset 重复,你可以通过将 asset 模块的类型设置为'javascript/auto'来解决。
步骤:
-
在 index.js中引入图片
在此实例中,我们引入同目录另一文件夹下的png文件,并将其利用js拼接到html页面。
js// 本地图片利用 import 引入 import imgObj from '../login/assets/logo.png' // 获取图片标签 const theImg = document.createElement('img') theImg.src = imgObj // 插入html中 document.querySelector('.login-wrap').appendChild(theImg) -
配置webpack.config.js让webpack拥有打包图片的功能
jsmodule.exports = { // ...... moudle: { rules: [ //...... { test:/\.(png|jpg|jpeg|gif)$/i, type:'asset', generator: { filename:'assets/[hash][ext][query]' } } ] } }注意:判断临界默认值:8KB
- 大于8KB的文件:发送一个单独的url文件并导出url地址
- 小于8KB的文件:导出一个data URL(base64字符串)
filename:'assets/[hash][ext][query]'中的三个占位符:这三个占位符是 Webpack 输出文件命名时常用的模板变量 ,在
generator.filename或output.filename里使用。
[hash]
- 含义:模块内容的哈希值(hash),Webpack 根据内容生成一串十六进制字符串。
- 作用:防止浏览器缓存旧文件。
- 示例:
jsfilename: 'assets/[hash][ext]'如果打包一张 logo.png,生成的文件可能是:
assets/3f5a2d1e8b.png小技巧:可以写
[hash:8],表示只取前 8 位,更短一些:
assets/3f5a2d1e.png
[ext]
含义 :原文件的扩展名(带
.)。作用:保持文件类型一致。
示例:
filename: 'assets/[hash][ext]'
原文件
logo.png→ 输出3f5a2d1e8b.png,扩展名仍然是.png。
[query]
- 含义:文件 URL 中的查询参数(query string)。
- 作用:如果你 import 的资源带了查询参数,会自动保留。
- 示例:
jsimport img from './logo.png?version=1'输出文件名会是:
assets/3f5a2d1e8b.png?version=1在实际项目中用得比较少,主要用于带版本号或 CDN 参数的资源。
占位符 作用 [hash]根据内容生成哈希,防缓存 [ext]保持原文件扩展名 [query]保留 import 时的查询参数
小案例:用户登录-完整功能
需求:完成核心的登录流程以及alert警告框的使用
步骤:
-
使用 npm 下载 axios
bashnpm i axio -
准备并修改utils工具包源代码导出实现函数
例如:我们需要封装两个js文件:
默认导出:
jsimport axios from 'axios' // ...... export default axios;命名导出:
jsexport function myAlert(...){...}在入口函数中引入并使用:
jsimport myAxios from '../utils/request.js' import { myAlert } from '../utils/alert.js' document.querySelector('.btn').addEventListener('click', () => { // get phone number and id-code const phone = document.querySelector('.login-form [name=mobile]').value const code = document.querySelector('.login-form [name=code]').value if (!checkPhone(phone)) { myAlert(false, '手机号码输入不合法') console.log('手机号码输入不合法!') return } if (!checkCode(code)) { myAlert(false, '验证码输入不合法') console.log('验证码输入不合法!') return } myAxios({ url: '/v1_0/authorizations', method: 'POST', data: { monile: phone, code: code } }).then(() => { myAlert(true, '已提交至服务器') }).catch(error => { myAlert(false, error.response.data.message) }) }) -
导入并编写逻辑代码,打包后运行观察效果。