通过loader加载任何类型的资源
大文件(大于10kb)单独提取存放,提高加载速度
npm i file-loader
yarn add file-loader
{
text:/.png$/
use:‘file-loader’
}
需要用的话,首先需要先安装file-loader
可以将文件转换成base64 ,小文件(小于10kb)使用,减少请求次数
{
text:/.png$/
use:‘url-loader’
}
{
text:/\.png$/
use:{
loader:'url-loader'
options:{
limit:10*1024 //10KB
}
}
}
常用加载器分类:
编译转换类(css-loader)
文件操作类(file-loader)
代码检查类(eslint-loader)
转换es6语法—babel-loader
取代默认的加载器,处理代码中的新特性
yarn babel-loader @babel/core @babel/preset-env --dev
{
test:/.js$/
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env']
}
}
}
webpack 只是打包工具
加载器可以用来编译转换代码(用于处理新特性)
遵循Es module的import声明
遵循Common Js 标准的require函数
遵循AMD 标准的define函数和require函数
*样式代码中的@import指令和url函数
*html-loader 加载html代码中图片标签的src属性
找到打包的入口文件(一般是js文件)
根据import 生成依赖树
找到每个节点对应的资源文件
生成bundle.js文件
loader机制是webpack的核心
webpack开发一个Loader
开发一个markdown文件加载器
markdown-loader.js文件
const marked= require('marked')
module.exports = source=>{
const html = marked(source)
// return `export default ${JSON.strigify(html)}` //返回的必须是js代码 也可以是
return `module.exports = ${JSON.strigify(html)}` //返回的必须是js代码
}
{
test :/.md$/,
use:'./markdown-loader'
}
总结 :
loader负责资源文件从输入到输出的转换,对于同一个资源可以依次使用多个;如:Loader css-loader->style-loader
Loader专注实现资源模块加载
plugin解决其他自动化工作(如:清除打包目录、拷贝静态文件至输出目录、压缩输出代码)
clean-webpack-plugin 自动清除输出目录插件
yarn add clean-webpack-plugin
const {CleanWebpackPlugin} = require('clean-webpack-plugin ')
pulgin:[
new CleanWebpackPlugin()
]
html-webpack-plugin
yarn add html-webpack-plugin
const HtmlWebpackPlugin = require(html-webpack-plugin)
plugin:[
//用于生成index.html
new HtmlWebpackPlugin({
title:'webpack pulgin sample',
meta:{
viewport:'width=device-width'
},
template:'./src/index.html' //指定模板 用于输出html文件
})
//用于生成about.html
new HtmlWebpackPlugin({
filename:'about.html',
}
//开发阶段最好不使用这个插件
new CopyWebpackPlugin([
'public' //指定目录 同时拷贝到输出目录
])
]
webpack插件总结
copy-webpack-plugin
webpack插件机制的工作原理
相比于Loader,plugin拥有更宽的能力范围
plugin通过钩子机制实现
plugin必须是一个函数或者是一个包含apply方法的对象
通过在生命周期的钩子中挂载函数实现扩展
删除bundle.js中的注释
class MyPlugin{
apply(compiler){
compiler.hooks.emit.tap('MyPlugin',compilation=>{
//compilation 可以理解为此次打包的上下文
for(const name in compilation.assets){
console.log(compilation.assets[name].source())
if(name.endsWith('.js')){
const contents = compilation.assets[name].source()
const withoutComments = contents.replace(/\/*\*+\*//g,'')
compilation.assets[name]={
source:()=>withoutComments,
size:()=>withoutComments.length
}
}
}
})
}
}
plugins:[
new MyPlugin()
]
watch 工作模式
监听文件变化 ,自动重新打包
yarn webpack --watch 以监视模式运行
browserSync
操作上麻烦,需要同时使用两个工具
效率上降低,会出现两次读写磁盘的操作
集成【自动编译】和【自动刷新浏览器】等功能
会有一个http server
yarn add webpack-dev-server
直接使用yarn webpack-dev-server
将打包结果存放到内存中,再发给浏览器
module.exports = {
devServer:{
contentBase:'./public' //路径 额外为开发服务器指定查找资源目录
}
}
webpack dev server 支持配置代理
module.exports = {
devServer:{
contentBase:'./public' //路径 额外为开发服务器指定查找资源目录
proxy:{
'/api':{
//http://local:8080/api/users-> https://api.gitbug.com/api/users
target:'https://api.gitbug.com'
pathRewrite:{
'^/api':''
}
//不使用localhost:8080 作为请求gitHub的主机名
changeOrigin:true
}
}
}
}
source map 解决了源代码与运行代码不一致所产生的问题
devtool:‘source-map’
devtool有12种模式
每种方式的效率和效果各不相同(效率好的、生产代码时最慢;生产代码时最快的、效率最差)
devtool
const webpack = require('webpack')
devServer:{
hot:true
}
plugins:[
new webpack.HotModuleReplacementPlugin()
]
HMR需要手动处理模块热替换逻辑
js、图片并不是开箱即用
样式文件可以直接热更新
通过脚手架创建的项目内部都集成了HMR方案
在入口文件中增加如下代码(module.hot是由HMR开启的)
module.hot.accept(‘./editor’,()=>{
})
三个配置文件
webpack.common.js、webpack.dev.js、webpack.prod.js
合并配置文件
yarn add webpack-merge --dev
在webpack.prod.js 中
const common = require('./webpack.common')
const merge = require('webpack-merge')
module.exports = merge(common,{
mode:'production'
})
适应于多页应用程序
一个页面对应对应一个打包入口,公共部分单独提取
module.exports = {
mode:'none',
entry:{
index:'./src/index.js',
album:'./src/album.js'
}
output:{
filename:'[name].bundle.js'
},
optimization:{
splitChunks:{
chunks:'all' //提取公共模块
}
}
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
}
]
},
plugins:[
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title:'Multi Entry',
template:'./src/index.html',
filename:'index.html',
chunks:['index'] //多入口时需要配置
})
new HtmlWebpackPlugin({
title:'Multi Entry',
template:'./src/album.html',
filename:'album.html',
chunks:['album']
})
]
}
需要用到某个模块时去加载
动态导入的模块会被自动分包
提高响应速度
magic comment
import(/* webpackChunkName:‘album’ */‘./album.album’).then()
提取css到单个文件(超过150KB才建议提取)
module:{
rules:[
{
test:/\.css$/,
use:[
//'style-loader', //将样式通过style标签注入
MiniCssExtractPlugin.loader, //提取css到单个文件
'css-loader'
]
}
]
}
压缩输出的css文件
npm i optimize-css-assets-webpack-plugin --dev
const OptimizeCssAssetsWebpackPlugin = require(‘optimize-css-assets-webpack-plugin’)
可配置到pulgins数组中,但通常是配置到minimizer数组中,只有配置了optimization时才会去压缩,同时也要单独为js去配置压缩,可通过terser-webpack-plugin来处理js压缩
const TerserWebpakcPlugin = require('terser-webpack-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimizer-css-assets-webpack-plugin')
optimization:{
minimizer:[
new TerserWebpakcPlugin()
new OptimizeCssAssetsWebpackPlugin()
]
}
生产模式下,文件名使用hash值
filename:‘[name]-[hash].bundle.css’
filename:‘[name]-[chunkhash:8].bundle.css’ 一般用这个
filename:‘[name]-[contenthash].bundle.css’
hash、chunkhash(更精确定位到文件级别的hash)、contenthash(不同的文件就有不同的变化)
chunkhash