webpack 介绍
webpack 本身就是一个模块打包工具 将零散的模块代码打包到同一个js文件当中 对于打包中有环境兼容的代码 就可以在打包的过程中通过模块加载器 (loader) 对其进行编译装换 同时webpack还具备代码拆分的能力 在应用当中将我们的代码按照我们的需要去打包 解决了 在应用当中将所有的模块代码打包在一起 产生的文件比较大的问题 应用加载过程当中 初次运行的时候将所必须的模块 打包到一起 对于其他的模块单独存放 当我们需要时 再异步加载这些模块 解决文件太碎 或太大 支持以模块化的方式 载入任意类型的文件
安装
yarn add webpack webpack-cli --dev
配置文件
- 创建 webpack.config.js
- 它是一个在 node 环境下运行的文件
- 控制打包输入输出目录
const path = require('path')
module.exports ={
entry:'./src/index.js', // 打包入口
output:{ // 打包后输出目录
filename:'bundle.js',
path:path.join(__dirname,'output') // 必须是绝对路径 否则报错
}
}
webpack 打包结果运行原理
bundle.js
- 一个函数的自调用 参数是一个数组 每个元素都是一个函数 对应源代码当中的模块 也就是说每个模块都会包裹在每个函数当中 从而实现私有作用域
工作入口函数
- 定义一个对象 缓存加载过的模块
- 定义了一个加载模块的函数 webpack_require_
- 在 webpack_require 挂载了一些工具函数
- return webpack_require 开始加载模块
webpack_require 执行过程
- 在缓存 判断是否已经加载过
- 没有缓存 定义对象 属性有 moduleId L export
- 用 call 方法调用 moduleId 的函数并执行函数中的内容 最后把 module.export 导出的内容 赋值到对象的 export 中 最终返回
webpack4 新增了工作模式的用法
production 模式
- 默认使用
- 帮我们的代码进行压缩
yarn wepack --mode production
development 模式
- 优化我们的打包速度和方便调试
yarn webpack --mode development
none 模式
- 运行最原始状态的打包 不会对其进行任何的处理
- 除此之外 可以在配置文件中设置 mode 的属性来配置打包模式
yarn webpack --mode none
除了命令行的方式 还可以直接在配置文件中使用
const path = require('path')
module.exports ={
mode:'production',
entry:'./src/index.js',
output:{
filename:'bundle.js',
path:path.join(__dirname,'output') // 必须是绝对路径 否则报错
}
}
Loader
介绍
- 专注实现资源模块加载
- webpack的核心特性
- 借助loader就可以加载任何类型的资源
- 将资源模块作为 js 代码去工作
- webpack默认打包 js 代码 其他文件需要使用loader加载器
Css loader
- 打包css文件
安装
yarn add css-loader --dev
yarn add style-loader --dev
配置
const path = require('path')
module.exports ={
mode:'none',
entry:'./src/main.css',
output:{
filename:'bundle.js',
path:path.join(__dirname,'dist')
},
//对其他资源模块加载资源规则的配置
//每个规则对象都需要两个属性
//text 正则表达式 用来匹配打包过程中的文件路径
//use 匹配到的文件需要使用的loader 先执行最后一个loader
module:{
rules:[
{
test:/.css$/,
use:[
'style-loader',
'css-loader'
]
}
]
}
}
工作原理
• css-loader 将 css 文件转换成打包后的模块 将 css 代码 push 到 bundle.js 模块数组当中 这个数组是由 css-lodash 内部的模块提供的 整个过程没有使用到这个数组 需要使用 style-lodash 将 css-lodash 转化过后的结果通过 style 标签的形式追加到页面上
filer-loader
- 图片 字体....通过js 的方式表示
- 安装
- yarn add file-loader --dev
- 案例
- 导入图片 并添加到页面中
module.export = {
entry:'main.js',
output:{
filename:'bundle.js',
path:path.join(__dirname,'dist'),
publicPath:'dist/', //文件路径默认是在项目路径下 而打包后实在 dist 目录 导致浏览器看不到效果 使用
},
module:{
rules:[
{
test:'/.png/',
use:['file-loader'] // here
},
{
test:'/.css/',
use:[
'style-loader',
'css-loader'
]
}
]
}
}
URL资源加载器
介绍
- 除了用 file-loader 处理 图片 文字 还可以用 url 资源加载器
- Data url 是一种特殊的 url 协议 传统 url 就必须服务器必须要有一个文件 然后请求对应的地址得到服务器上的 文件 而 Data url 直接用 url 直接表示一个文件内容 使用这种 url 的时候 就不会再去发送任何的 http 请求 也就是文本就包含文件的内容
格式
比如下面这段代码
浏览器会解析出来这是一个 html 文件 编码是utf-8 内容是h1标签
如果是图片 或者是字体 无法通过文本去表示的二进制类型文件 可以通过图片进行base 64编码 将 base64 编码过后的结果作为图片内容
安装
yarn add url-loader --dev
使用建议
适合体积比较小的资源 如果体积比较大会影响打包结果非常大 从而影响运行速度
- 最佳实践
- 小文件使用 data url 减少请求数
- 大文件用 file-loader 单独存放,提高加载速度
- 限制范围 超过范围大小 则使用 file-loader
{
test:/.png$/,
use:{
loader:'url-loader',
options:{
limit :10*1024 // 将 10kb 以下的文件存入到 url
}
}
}
- 超出10kb文件单独存放
- 小于10kb转换为 data url嵌入代码
注意:
必须要安装file-loader
babel-loader
- webpack 只是打包工具 只处理 import 和 export 做相应的转换 不能处理es6中其他的特性
安装:
yarn add babel-loader @babel/core @babel/preset-env --dev
配置
{
test: /.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
webpack 导入资源的方式
- 支持的三种导入方式
- ESmodule 标准的 import 声明
commonjs 标准的 require
AMD标准的 define函数 和 require 函数
- 注意
- 除非必要否则不要混合使用这些标准 将大大降低项目的可维护性
- 导入 HTML 模块是一个字符串 需要接受一下
- 另外 以下几种方式也可以加载模块
- 样式代码中的 @import 指令和url 函数
- html 代码中的图片标签 src 属性
- 引入html模块到入口文件js时 需要安装html-loader
- html默认处理img src属性 触发其他标签属性打包 需配置
html-lodaer
module:{
rules:[
{
test:'/.html/'
use:[
loader:'html-loader',
options:{
attr:['img:src','a:href']
}
]
}
]
}
webpack特点
- 在代码当中所有需要引用到的资源 都会被 webpack 找出来 然后根据引用配置和不同的 loader 去处理 将处理的结果整体打包的输出目录 webpack 就是用这个特点 实现项目的模块化
- webpack 打包的核心工作原理与过程
- 项目当中一般都会有散落的各种各样代码和资源文件 webpack会根据我们的配置找到 js 文件作为打包的入口 然后顺着我们入口文件的代码 根据出现的 import 和 export 这样的语句 解析代码所需要的模块 分别去解析每个资源模块对应的依赖 最后形成整个项目中的所有用到文件的依赖数 然后 webpack 去递归这个依赖数 找到每个节点所配置的文件 然后根据配置文件中 rules 属性 找到模块所对应的加载器 交给加载器去加载这个模块 最后将加载到的结果 放入到 bunner.js 从而实现整个项目的打包
开发自己的loader
- 每个 loader 都需要导出一个函数 这个函数对所加载到的资源的一个处理过程 输入就是要加载到的文件内容 输出就是加工过后的结果 函数的参数接受输入 返回值输出
- 概念
- loader 负责资源文件从输入到输出的转换
- 可以把 loader 交给下一个 loader 处理
- 标准
- loader最后的返回值必须是一段 js 代码
- 原因 打包后会将结果 push 打包后的 js 模块中 如果不是 js 代码 就会报错
- 允许像管道一样凭借多个 loader 最终转换为 js 代码
例: 创建 markdom-loader
• //导出函数 该函数的参数是输入内容 对内容进行处理 并把结果作为返回值输出出去
//下载并导入marked 第三方模块 将内容转换为html标签
const marked = require('marked')
module.exports= source=>{
const html = marked(source)
//将html 转换字符串
return `export defalut ${JSON.stringify(html)}`
//将返回的结果交给下一个loader
// return html
}
loader:[
'./markdowm-loader',
'html-loader'
]
webpack 插件机制 plugin
- 插件机制是 webpack 另外一个核心机制
- 作用
- 增强 webpack 自动化能力
- 解决除了 loader 资源加载以外其他自动化工作
- 例如
- 打包之前清除dist目录
- 拷贝静态文件到输出目录
- 压缩打包后输出代码
- 常用插件
- 绝大多数插件模块导出的是一个类 使用它就是为这个类型创建实例 然后放到 plugins 数组当中
clean-webpack-plugin
- 解构导入的插件 并创建实例对象
- 每次打包前清除 dist 目录
- 安装
- yarn add clear-webpack-plugin --dev
- 导入
- import { ClearWebapckPlugin } from 'clear-webpack-plugin'
//plugin是一个数组 添加一个插件就是在数组添加元素
plugins:[
new CleanWebpackPlugin()
]
html-webpack-plugin
- 硬编码的方式写 html 会导致 上线后无法确保路径引用是否正确 而且当配置文件的入口文件发生变化之后 需要手动修改 html 的引用路径
- 自动生成使用打包结果 bundle.js 的 html 文件并生成到同一个目录 上线后只要发布 dist 目录就可以了 并且html 对于 bundle 的引用是动态注入进来的 不需要手动的去硬编码 确保路径引用正常
- 默认导出文件的类型 不需要解构
- 安装
- yarn add html-webpack-plugin --dev
- html 标题 通过修改 htmlwebpackPublic 的属性实现
- 如果需要自定义 HTML 文件的话
- 通过模板文件 直接拷贝模板文件
- 当需要多个页面文件时创建多个 htmlwebpackplugin 实例到 plugins 的属性当中
- 问题 : 启动项目找不到该 html 文件
- 修改 publicPat 属性 将 html 目录修改为当前目录
plugins:[
new htmlWebpackPlugin({
title:'' // html 的标题
meta:{
viewPort:'width=device-width'
},
//自定义模板内容
template:'./src/index.html'
})
// 生成多个 html 文件
new htmlWebpackPlugin({
filename:'about.html'
})
]
copy-webpack-plugin
- 使用背景
- 将静态文件 plugin 文件夹 输入 到 dist
- 开发阶段不要使用这个插件
new CopyWebpackPlugin({
//从那个路径到那个路径
patterns: [
{ from: "public", to: "public" },
],
})
开发自己的插件
- 插件机制的实现
-
就是在软件开发中经常看到的钩子机制 钩子机制就是 web 当中的事件机制 在webPack工作中会有很多个环节 为了便于插件的扩展 webpack 给给个环节都埋下了钩子 开发插件的时候 就可以往每个节点挂载不同的任务 轻松扩展 webpack 的能力
-
要求插件必须是一个函数 或者是包含 apply 方法的对象 通常是创建一个类型 在类型中添加一个 apply 方法 然后通过创建实例来使用这个方法
-
就是往 webpack 打包的声明周期 挂载函数实现扩展
-
class myPlugin{
// compiler 注册的信息
apply(compiler){
//compilation 本次打包的所有信息
compiler.emit.tap('myplugin',(compilation)=>{
//遍历模块
for(let name for compition){
if(name.endWidth('.js')){
// 获取文本内容
const content = compilation.assets[name].source()
//把文本中的注释替换掉
const widthoutComents = content.replace(/\/\*\*+*\/g,'')
//把处理结果重新输出到该文件中
compilation.assets[name] ={
source: () => widthoutComents,
size:() => widthoutComents.length
}
}
}
})
}
}
webpack 思想
- webpack 建议在 js 当中引入任何你当前代码需要的资源 是因为真正需要资源的不是的应用 而是此时正在编写的代码 是你当前编写代码需要这些资源
- 由 JavaScript 驱动整个前端应用
- 逻辑合理,js需要多种文件配合才能实现对应的功能
- 确保上线时资源不缺失,并且每一个文件都是必要的
预告 下一篇 webpack 打包结果的优化和提高打包体验
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!