1.什么是webpack?
1.是现代 javascript 应用程序的 静态模块打包器
静态: 文件资源
模块: node环境, 引入文件, 遵守模块化语法
2.除了合并代码, 还可以翻译和压缩代码
less/sass -> css
ES6/7/8 -> ES5
html/css/js -> 压缩合并
3.减小代码包体积, 让浏览器更快速打开网页
1.使用webpack前, 准备什么?
1. 初始化包环境,得到webpack.json文件
yarn init
2.安装依赖包(webpack和webpack-cli)
yarn add webpack webpack-cli -D
3.配置自定义命令,为打包做准备
在package.json中, 配置scripts(自定义命令)
scripts: { "build": "webpack" }
1.webpack如何使用?
1.先下载安装webpack, 配置打包命令
2.默认入口src/index.js要被打包的文件, 要引入到这里使用(所有代码都引入这个入口文件)
3.输入yarn build打包命令(实际是项目环境webpack命令)
注意:要在src的父级终端运行
4.输出代码到dist/main.js中,查看main.js文件, 是打包压缩后的代码
2.问题:如何将2个js文件整和并压缩在一起?
1.新建src/add/add.js - 定义求和函数导出
export const addFn = (a, b) => a + b
2.新建src/index.js导入使用
// webpack打包的入口 import { addFn } from './add/add' console.log(addFn(5, 2));
3.运行打包命令
yarn build
效果
src并列处, 生成dist目录和main.js文件
查看main.js文件, 是打包压缩后的代码
(()=>{"use strict";console.log(7)})();
1.代码增加后如何打包?
1.要和src/index.js有直接或间接的引入关系
2.重新执行yarn build
问题:如果代码增加(代码变化),如何打包?
步骤
1.新建src/tool/tool.js - 导出数组求和方法
export const getArraySum = arr => arr.reduce((sum, val) => { return sum = sum + val; }, 0)
2.src/index.js - 导入使用
import { addFn } from './add/add' import { getArraySum } from './tool/tool' console.log(addFn(5, 2)); console.log(getArraySum([5, 6, 9, 10]));
3.重新打包
yarn build
效果
自动覆盖原dist, 结果压缩极致
(()=>{"use strict";console.log(7),console.log([5,6,9,10].reduce(((o,e)=>o+e),0))})();
总结:
1.webpack默认入口和出口是什么?
默认入口 src/index.js
默认出口 dist/main.js
2.webpack默认配置文件名?
webpack.config.js
注意:webpack基于node,所以导出,遵守CommonJS规范
问题:如何修改webpack,默认入口和出口?
1.项目根目录 - 新建webpack.config.js文件 (默认配置文件名)
2.填入配置项-入口(entry)和输出(output)
入口(entry):口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的
输出(output):output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为
./dist
。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。你可以通过在配置中指定一个output
字段,来配置这些处理过程const path = require("path") module.exports = { // webpack入口 entry: './src/main.js', output: { // path必须用绝对地址: path.resolve()拼接2个路径 // __dirname: node内置全局变量(值: 当前文件所在文件夹的绝对路径) path: path.resolve(__dirname, 'dist'), // webpack出口文件 filename: 'bundle.js' }
3.修改代码里src/index.js 为 src/main.js
4.重新打包观察输出文件名字
注意:所有要被打包的资源都要跟入口产生直接/间接的引用关系
总结:
1.简述总结下打包流程?
1.执行局部webpack命令(前提项目中下载了webpack包)
2.有webpack.config.js用, 否则用内置默认
3.根据入口建立引入关系
4.编译翻译整合打包输出到指定位置
2.模块想要被webpack识别打包, 要注意什么?
模块文件要和webpack入口产生直接或间接引入关系
1.下载jquery
yarn add jquery
2.新建public/index.html - 前端首页,准备一些li
Document
- 我是第1个li
- 我是第2个li
- 我是第3个li
- 我是第4个li
- 我是第5个li
- 我是第6个li
- 我是第7个li
- 我是第8个li
- 我是第9个li
3.在src/main.js引入jquery,在main.js中编写, 隔行变色代码
// 目标2: yarn下的包, 在js引入, 不能直接用到前端 import $ from 'jquery' $("#myUL>li:nth-child(2n+1)").css('color', 'yellow') $("#myUL>li:nth-child(2n)").css('color', 'green')
4.执行打包命令
yarn build
5.把public/index.html手动复制到dist下
6.再public/index.html中手动引入打包后bundle.js
关键
1.yarn下的包, 在main.js文件里, 用import语法导入
浏览器不支持import语法
2.webpack翻译打包后输出到dist中的bundle.js文件
3.html页面引入翻译打包后的bundle.js即可正常使用
用yarn下的包,如何使用在前端项目?
- 借助webpack, 把模块和代码打包
- 把打包后js文件, 引入到html执行查看效果
案例:自动生成html和引入打包后文件, 如何做?
1.下载插件
yarn add html-webpack-plugin -D
2.webpack.config.js配置
// 引入自动生成 html 的插件 const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { // ...省略其他代码 plugins: [ new HtmlWebpackPlugin({ // webpack生成dist/html网页, 要以template指定的文件作为模板 template: './public/index.html' }) ] }
3.重新打包后观察dist下
自动生成html文件
自动引入打包后js文件
总结: webpack就像一个人, webpack.config.js是人物属性, 给它穿什么装备它就干什么活
问题:webpack如何打包css文件
1.新建 - src/css/index.css,编写去除li圆点样式代码
li{ list-style: none; }
2.在main.js引入index.css
一定要引入到入口才会被webpack打包
import "./css/index.css"
3.安装依赖
yarn add css-loader style-loader -D
4.webpack.config.js 配置
module.exports = { // ...其他代码 module: { // 如何处理项目中不同模块文件 rules: [ // 规则 { test: /\.css$/, // 匹配所有的css文件 use: [ "style-loader", "css-loader"] } ] } }
5.执行打包命令, 观察打包后dist下
注意:
test 表示匹配的文件类型,use 表示对应要调用的 loader
css-loader -> 识别.css文件, 代码打包进main.js中
style-loder -> 把js里样式代码, 插入到DOM中
use数组里从右向左运行
总结:
1.webpack如何支持css打包?
使用style-loader和css-loader
2.style-loader和css-loader作用?
css-loader让webpack识别.css文件, 打包代码到js中
style-loader把js中的css代码, 插入到style标签里显示
3.打包后样式在哪里?如何生效?
打包后样式在.js文件中
运行后, 被插入到style标签里
1.新建src/less/index.less - 设置li字体大小24px
@size:24px; ul, li{ font-size: @size }
2.引入到main.js中
import "./less/index.less"
3.下载依赖包
yarn add less less-loader -D
4.webpack.config.js 配置
module: { rules: [ // 规则数组 { //处理css的规则 test: /\.css$/i, use: ["style-loader", "css-loader"], }, {//处理less的规则 test: /\.less$/i, use: ['style-loader', 'css-loader', 'less-loader'], // less-loader 识别.less文件 -> less文件和less语法 -> css // css-loader 识别css -> 打包进js中 }, ] }
注意:
less-loader -> 识别.css文件
less -> 把less语法转翻译成css
style-loader, css-loader缺一不可
小结:
1.webpack如何支持less打包?
1.下载less和less-loader2个包
2.less-loader识别less文件
3.less是翻译less代码到css代码
2.less翻译后, 还要注意什么?
1. 还要用css-loader把css代码进js中
2.style-loader, 把css代码插入到DOM上
案例:webpack如何打包图片文件?
1.素材文件夹/2个图文件,
2.在css/less/index.less - 把小图片用做背景图
body{ background: url(../assets/logo_small.png) no-repeat center; }
3.在src/main.js - 把大图插入到创建的img标签上, 添加body上显示
// 引入图片-使用 import imgUrl from './assets/1.gif' const theImg = document.createElement("img") theImg.src = imgUrl document.body.appendChild(theImg)
4.webpack.config.js 配置
module: { rules: [ // ...省略其他 { test: /\.(png|jpg|gif|jpeg)$/i, // 匹配图片文件 type: 'asset' // 在导出一个 data URI 和一个单独的文件之间自动选择 // 小于8kb的, 转成data URI(图片转成base64字符串打包进js中) // 大于8kb的, 直接复制文件到dist目录下(因为转base64会体积增30%) } ] }
注意:asset模式, 会在复制文件到dist下 和 图片文件转base64之间根据图片大小自动选择
5.打包后运行dist/index.html观察区别
小结:
1.webpack如何支持图片打包?
webpack5内置了, 只需要配置type:'asset'
2对图片有哪两种处理方案?
默认8kb以下图片, 转成base64字符串打包进js中, 减少网络请求次数
超过8kb的图片, 直接复制到dist下, 转base64会增加30%体积
案例:webpack如何处理字体文件
1.素材文件夹/字体库fonts文件夹
2.在main.js引入iconfont.css
// 目标6: 字体图标 import "./assets/fonts/iconfont.css" let theI = document.createElement('i') theI.className = "iconfont icon-qq" document.body.appendChild(theI)
3.配置webpack.config.js
{ test: /\.(eot|svg|ttf|woff|woff2)$/, type: 'asset/resource', // 当做静态资源直接复制文件 generator: { filename: 'font/[name].[hash:6][ext]' // 放到dist/font文件夹, 文件名格式如左 } }
小结:
webpack如何处理字体文件?
在webpack.config.js的rules里针对字体图标文件类型设置asset/resource,直接输出到dist下
案例:测试让webpack, 对高版本js语法降级
1.src/main.js - 编写箭头函数
const fn = () => { // 高级语法 console.log("你好babel"); } console.log(fn) // 一定打印函数, 才会被webpack把"函数体"打包起来
2.安装包
yarn add -D babel-loader @babel/core @babel/preset-env
3.webpack.config.js 配置规则
module: { rules: [ // 设置babel降级js语法 { test: /\.m?js$/, // 匹配.mjs或.js结尾文件 exclude: /(node_modules|bower_components)/, // 排除node_modules第三方包里面js文件 -> //因为别人写的(如果你下载jq3.x版本, 你就已经决定不兼容ie6, 也没有jq降级) use: { loader: 'babel-loader', // 允许webpack使用babel降级编译js代码 options: { presets: ['@babel/preset-env'] // 使用这个包里记录的规则 } } } ] }
4.打包后观察dist/的js文件, 自动变成普通函数
小结:
webpack如何帮助我们降低js版本语法?
借助babel-loader和babel编译器,给webpack配置上, 翻译再打包使用
1. 为什么学开发服务器?
每次修改代码, 重新打包, 才能看到最新的效果,实际工作中, 打包非常费时 (10-20s) 之间, 影响开发效率。
2.开发服务器的使用
下载包
yarn add webpack-dev-server -D
package.json配置自定义命令serve
scripts: { "build": "webpack", "serve": "webpack serve" }
运行命令-启动webpack开发服务器
yarn serve #或者 npm run serve
启动一个web服务器和端口, 在浏览器访问查看
效果: 以后改src下的代码, 自动打包更新到浏览器上
小结:
1.如何用webpack开发服务器, 实时打包我们的代码?
下载webpack-dev-server包
在package.json配置serve命令, 启动
webpack-dev-server给我们一个地址+端口, 供浏览器访问查看index.html页面和打包后的js和css等
2.webpack开发服务器好处是?
打包进内存里, 使用更快
代码变化, 只会重新打包和更新, 变化的文件和代码
3.开发服务器-配置
1.webpack.config.js中添加服务器配置
module.exports = { // ...其他配置 devServer: { port: 3000, // 端口号 open: true // 启动后自动打开浏览器 } }
2.重启开发服务器观察效果即可
小结:
如何修改webpack开发服务器的配置呢?
去文档查找配置项的名字
在webpack.config.js的devServer选项里添加
问题:项目做完了, 要上线怎么办?
1.webpack.config.js修改mode选项(==任选一个==)
module.exports = { // ...其他配置 mode: 'development' // 开发环境-> 不会极致压缩, 一般开发服务器默认使用这个属性 }
module.exports = { // ...其他配置 mode: 'production' // 生产环境-> 会极致压缩, 一般上线npm run build会自动采用这个模式 }
2.执行之前的yarn build产生dist目录,所有代码, 被整合打包
3.把dist目录交给后台/运维, 部署给客户使用即可,开发环境的代码不用发
小结:
1.项目分哪2个环境?
线上和线下2个环境
线上也叫"生产环境"/"部署", 英文"production"
线下也叫"开发环境"/写代码, 英文"development"
2.项目做完了, 要上线需要做什么?
1.webpack.config.js修改mode选项,设置为production(默认)
2.运行打包命令,再把地dist文件发送给后台
1、什么是webpack(必会)
webpack是一个javascript的静态模块打包工具
webpack里一切文件皆模块,通过loader加载器转换文件,通过plugin插件注入钩子
最后输出由多个模块组合成的文件,webpack专注构建模块化项目
2、webpack的优点是什么?(必会)
专注于处理模块化的项目,能做到开箱即用,一步到位
通过plugin插件扩展,完整好用又不失灵活
通过loaders加载器扩展, 可以让webpack把所有类型的文件都解析打包
区庞大活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展
3、webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全(必会)
webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:
初始化参数:从配置文件读取与合并参数,得出最终的参数
开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,开始执行编译
确定入口:根据配置中的 entry 找出所有的入口文件
编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
在以上过程中,webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 webpack 提供的 API 改变 webpack 的运行结果
4、说一下 webpack 的热更新原理(必会)
webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
HMR的核心就是客户端从服务端拉去更新后的文件,准确的说是 chunk diff (chunk 需要更新的部分),实际上 WDS(webpack-dev-server) 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。
后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)由 HotModulePlugin 来完成,提供了相关 API 以供开发者针对自身场景进行处理,像react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR。
5、webpack与grunt、gulp的不同?(必会)
1) 三者之间的区别
三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。
grunt和gulp是基于任务和流(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。
webpack是基于入口的。webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。
2) 从构建思路来说
gulp和grunt需要开发者将整个前端构建过程拆分成多个
Task
,并合理控制所有Task
的调用关系 webpack需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader做何种解析和加工3) 对于知识背景来说
gulp更像后端开发者的思路,需要对于整个流程了如指掌 webpack更倾向于前端开发者的思路
6、有哪些常见的Loader?他们是解决什么问题的?(必会)
1、 file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
2、 url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
3、 source-map-loader:加载额外的 Source Map 文件,以方便断点调试
4、 image-loader:加载并且压缩图片文件
5、 babel-loader:把 ES6 转换成 ES5
6、 css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
7、 style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
8、 eslint-loader:通过 ESLint 检查 JavaScript 代码
7、Loader和Plugin的不同?(必会)
1) 不同的作用
loader直译为"加载器"。webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。
Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 API 改变输出结果。
2) 不同的用法
Loader在module.rules中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options)
Plugin在plugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。