彻底解决新手对webpack的恐惧!,三级缓存框架问题你都了解了吗

import mk85 from ‘./assets/images/mk85.jpeg’

console.log(mk85) // mk85.jpeg

const img = document.createElement(‘img’)

img.src = mk85

const BoxDiv = document.getElementsByClassName(‘box’)

BoxDiv[0].appendChild(img)

运行webpack命令看一下结果0bef75b0ce85a0a63e1ff92ab1efc82f.png

实现图片在css文件中引入


在css中引入图片我们依旧使用url-loader,但需要对配置稍微进行修改css代码

.box {

width: 100px;

height: 100px;

/* background-color: yellowgreen; */

background-image: url(‘./assets/images/mk85.jpeg’);

display: flex;

}

直接引用并打包,打包成功!打开html页面,发现看不到图片,因为地址不对。打包后mk85图片在dist文件夹下,而index.css的引用路径依旧是mk85.jpeg,可index.css是在css文件夹下的,所以自然是无法引用到。那如何才能引用到呢?最简单的方法就是加上/但这里有坑(其实也不是坑,这是一个关于/images./imagesimage三者有什么不同的知识点)。补充:create-react-app也是通过/ 实现引用统一的d79d1c21b8acd9afba27e3dae93c2e8a.png修改url-loader配置

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

MiniCssExtractPlugin.loader,

‘css-loader’,

‘postcss-loader’

]

},

{

test: /.(png|jpe?g|gif)$/,

use: {

loader: ‘url-loader’,

options: {

name: ‘[name].[ext]’,

limit: 1024 * 3,

outputPath: “images/”,

publicPath: “/images”,

}

}

}

]

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”,

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’

}),

new CleanWebpackPlugin()

]

}

  • outputPath表示输出的到哪里(file-loader提供的)

  • name: images/[name].[ext]这样写和用outputPath设置效果一样吗?在配合publicPath字段时不一样。所以当你不需要配置publicPath字段时,可以通过name设置输出路径(file-loader提供的)

options: {

name: ‘[name].[ext]’,

limit: 1024 * 3,

outputPath: “images/”,

publicPath: “/images”,

}

// 等价于

options: {

name: ‘images/[name].[ext]’,

limit: 1024 * 3,

publicPath: “/”,

}

  • publicPath表示资源引用的路径

运行webpack命令看一下结果001b5fd873caab0428bcf930ec3d07c2.png成功了!是我们想要的结果,不过问题又来了,当你打开html页面时发现并不能看到图片正常显示,这里就牵扯到关于/images./imagesimage三者有什么不同的知识点简单来说,如果我起了服务,我的实际路径就是“localhost:8080/images/mk85.jpeg”,如果没有起服务那就是“/images/mk85.jpeg”所以让我们开启一个服务吧!

实现webpack本地服务


安装webpack-dev-server

yarn add webpack-dev-server -D

配置url-loader

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

MiniCssExtractPlugin.loader,

‘css-loader’,

‘postcss-loader’

]

},

{

test: /.(png|jpe?g|gif)$/,

use: {

loader: ‘url-loader’,

options: {

name: ‘[name].[ext]’,

limit: 1024 * 3,

outputPath: “images/”,

publicPath: “/images”,

}

}

}

]

},

devServer: {

open: true,

port: 8080,

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”,

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’

}),

new CleanWebpackPlugin()

]

}

  • 只需要加上devServer配置即可

  • open表示打开浏览器

  • port表示服务的端口号

注意:这时就不是使用webpack命令来启动项目了,需使用webpack-dev-server来启动

实现多页面打包


顾名思义,多页面自然是有多个html页面,每个html页面都有自己的js文件,那么,有多少个入口就要有多少个出口我们首先要设置一下目录形式,以适应多页面打包的形式(以下形式不是唯一的,但有助于大家的理解)23664c4e1929d111ff46972ac8e88ae2.png

  • 这里不需要src/index.js

  • 新建一个webpack.multiple.config.js

  • 新建src/pages/login/js/index.js

  • 新建src/pages/main/js/index.js

安装glob,用于处理文件

yarn add glob -D

配置webpack.multiple.config.js

module.exports = {

entry: {

login: ‘./src/pages/login/js/index.js’,

main: ‘./src/pages/main/js/index.js’

},

output: {

filename: ‘[name].js’,

path: path.resolve(__dirname, ‘./dist’)

},

plugins: [

new HtmlWebpackPlugin({

template: ‘./src/index.html’,

filename: ‘login.html’,

chunks: [‘login’] // chunks的名字对应entry中的名字

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’,

filename: ‘main.html’,

chunks: [‘main’]

})

]

}

这样就完成了!你可以使用webpack --config ./`webpack.multiple.config.js 命令运行一下。结果会如你所愿的但是,这时你肯定会想难道我每写一个页面就重新配置一次吗?这也太麻烦了,也不优雅!那我们现在解决一下这个问题吧,直接上代码

// 我们写一个方法自动做我们上面配置的事情

const glob = require(“glob”)

const setMpa = () => {

const entry = {}

const htmlwebpackplugins = []

// 通过glob库拿到我们的入口文件数组

const entryFiles = glob.sync(path.resolve(__dirname, “./src/pages///index.js”))

// console.log(entryFiles)

// 打印结果

// [

//  ‘/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/login/js/index.js’,

//  ‘/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/main/js/index.js’

// ]

entryFiles.forEach((item) => {

const entryFile = item

const match = entryFile.match(/src/pages/(.*)/js/index.js$/)

// console.log(match)

// 打印结果

// [

//   ‘src/pages/login/js/index.js’,

//   ‘login’,

//   index: 43,

//   input: ‘/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/login/js/index.js’,

//   groups: undefined

// ]

const pageName = match[1]

entry[pageName] = entryFile

htmlwebpackplugins.push(

new HtmlWebpackPlugin({

template: ./src/index.html,

filename: ${pageName}.html,

chunks: [pageName]

})

)

})

return {

entry,

htmlwebpackplugins,

}

}

有了这个方法以后,我们把它加到配置文件里

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)

const glob = require(“glob”)

const setMpa = () => {

const entry = {}

const htmlwebpackplugins = []

const entryFiles = glob.sync(path.resolve(__dirname, “./src/pages///index.js”))

entryFiles.forEach((item) => {

const entryFile = item

const match = entryFile.match(/src/pages/(.*)/js/index.js$/)

const pageName = match[1]

entry[pageName] = entryFile

htmlwebpackplugins.push(

new HtmlWebpackPlugin({

template: ./src/index.html,

filename: ${pageName}.html,

chunks: [pageName]

})

)

})

return {

entry,

htmlwebpackplugins,

}

}

const { entry, htmlwebpackplugins } = setMpa()

module.exports = {

entry,

output: {

filename: ‘[name].js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

‘style-loader’,

‘css-loader’,

‘postcss-loader’

]

},

{

test: /.(png|jpe?g|gif)$/,

use: {

loader: ‘url-loader’,

options: {

name: ‘[name].[ext]’,

limit: 1024 * 3,

outputPath: “images/”,

publicPath: “/images”,

}

}

}

]

},

devServer: {

open: true,

port: 8080,

hot: true

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”,

}),

new CleanWebpackPlugin(),

…htmlwebpackplugins

]

}

我们再使用webpack --config ./`webpack.multiple.config.js 命令运行一下,成功!

关注下方「前端开发博客」,回复 “加群”

加入我们一起学习,天天进步

62efe80dcc534dccf76c763e0975d6ca.png

小结

到这里就算是完成了一个简单的webpack项目配置,看到这里先不要着急往下看,思考一下是否真的了解了loader和plugin,如果让你写一个loader和plugin,你有思路吗我想不出意外的话,你应该是已经有了思路。如果没有也不用担心,看看下面的内容

实现一个loader

==========

先上链接,官网编写loader文档[11]首先loader是一个函数,注意这里不能是箭头函数编写一个替换字符串的loader

// replaceLoader.js

module.exports = function (soure) {

console.log(soure, this) // 这里可以自己打印看一下信息,内容太长我就不放进来了

return source.replace(‘hello webpack’, “你好呀,webpack!”)

}

  • loader是一个函数

  • 不能使用箭头函数,因为要用到上下文的this

  • soure接收到的是待处理的文件源码

  • return处理后的文件源码,也是下一个loader接收到的文件源码

使用loader

{

test: /.js$/,

use: path.resolve(__dirname, ‘./loader/replaceLoader.js’)

}

运行webpack命令看一下结果a0fb1dcf223c4a6fff72a80c8e72a23a.png成功!是不是发现原来自定义loader这么简单,感兴趣可以自己尝试写一下css、png等其他文件的loader

实现一个plugin

==========

线上链接,官网编写plugin文档[12]同样简单,我们已经用了很多次plugin了,发现是不是都需要new一下。很显然,自定义loader是一个构造函数。我们看一下格式:

class PluginName {

constructor (options) {

}

apply(compiler) {

}

}

  • 这里一定要写apply方法,webpack会通过apply方法启动插件

  • PluginName可以写成普通function,apply必须挂载到原型对象上(PluginName.prototype

  • class类中的apply不能写成箭头函数

  • webpack的compiler钩子[13],查看钩子决定你的插件要在哪一步做什么

编写一个假的html-webpack-plugin,输出一个fake.html文件

class HtmlPlugin {

constructor (options) {

}

apply(compiler) {

compiler.hooks.emit.tap(‘HtmlPlugin’, (compolation) => {

const content = ‘fake html’

compolation.assets[‘fake.html’] = {

source: function () {

return content

},

size: function () {

return content.length

}

}

})

}

}

module.exports = HtmlPlugin

使用这个plugin

plugins: [

new HtmlPlugin()

]

运行webpack命令看一下结果e8c76c02baad6fbcbd4be800af237555.png成功!你也可以试着完善一下这个插件,加上配置,加上引入资源文件等

指纹策略

====

关于浏览器缓存


  • 现代浏览器都会有缓存机制

  • 当我们第一次访问A网站时,这时加载了y.js的文件进行了缓存

  • 当我们第二次访问A网站时,浏览器发现缓存中已经有y.js了

  • 缓存中有y.js那就用缓存的文件

  • 优点:减少了资源的请求

  • 缺点:当y.js的内容更新了,若不通过强制刷新浏览器的话则无法获取最新的y.js内容

  • 我们加上标识符就可以解决这个问题了

  • 第一次访问时加载了y.123.js

  • 第二次访问发现有缓存就用缓存中的y.123.js

  • 这时服务器中的y文件内容改变了,同时也修改了名字为y.111.js

  • 第三次访问发现没有y.111.js文件,正确加载最新y.111.js

上诉都是比较简单解释,具体细节你可以不用知道,明白这个缓存机制的缓存方式即可

webpack中使用指纹策略


使用:

filename: ‘[name].[hash].[ext]’,

  • hash:以项目为单位,项目内容改变了,则会生成新的hash,内容不变则hash不变

  • 整个工程任何一个需要被打包的文件发生了改变,打包结果中的所有文件的hash值都会改变

  • chunkhash:以chunk为单位,当一个文件内容改变,则整个chunk组的模块hash都会改变

  • 假设打包出口有a.123.js和c.123.js

  • a文件中引入了b文件

  • 修改了b文件的内容

  • 重新的打包结果为a.111.js和c.123.js

  • a的hash值会被影响,但是c的hash值不受影响

  • contenthash:以自身内容为单位,依赖不算

  • 假设打包出口有a.123js和b.123.css

  • a文件引入了b文件

  • 修改了b文件的内容

  • 重新打包结果为a.123.js和b.111.css

  • a的hash值不受影响

热模块替换

=====

你一定使用过这个功能,只是你不知道罢了!场景:

  • 启动项目本地服务

  • 修改了一个.css文件的内容

  • 浏览器没有刷新,但是修改的内容还是生效了

这就是热模块替换,提示:无论是css还是js都可以做热模块替换,但是个人建议只做css的热模块替换即可。因为js的热模块替换需要写代码进行替换,除非特定情况下,否则js的热模块替换用处不大。我们来做一个css的热模块替换吧注:热模块替换不支持抽取出的css文件,只能放在style中,所以需要style-loader配置webpack.config.js

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)

const HtmlPlugin = require(‘./plugin/htmlPlugin’)

const Webpack = require(‘webpack’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.js$/,

use: path.resolve(__dirname, ‘./loader/replaceLoader.js’)

},

{

test: /.css$/,

use: [

// MiniCssExtractPlugin.loader,

‘style-loader’,

‘css-loader’,

‘postcss-loader’

]

},

{

test: /.(png|jpe?g|gif)$/,

use: {

loader: ‘url-loader’,

options: {

name: ‘[name].[ext]’,

limit: 1024 * 3,

outputPath: “images/”,

publicPath: “/images”,

}

}

}

]

},

devServer: {

open: true,

port: 8080,

hot: true

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”,

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’

}),

new CleanWebpackPlugin(),

new HtmlPlugin(),

new Webpack.HotModuleReplacementPlugin()

]

}

思考了一下,还是附了一份完整的配置文件(有点担心这样太占页面位置了)

  • 首先,将之前的MiniCssExtractPlugin.loader替换回style-loader

  • 给devServer中加上hot: true

  • 引入webpack: const Webpack = require('webpack')

  • 在plugin中添加:new Webpack.HotModuleReplacementPlugin()

运行webpack-dev-server命令看看效果吧!

webpack5都更新了什么

==============

话不多说,直接上链接,webpack5更新的内容[14]提示:当你使用webpack4的时候,无论是装plugin(插件)还是loader都尽量看看该插件现在都有什么版本,如果发现版本从4.x一下子跳到了5.x,那么一定要去安装4.x的版本,否则在打包的时候会发生未知的错误

结尾

==

这篇文章最初只写到【搭建webpak项目】部分就发布并标记了未完待续,本想着后面的内容写的简洁一点(写详细了其实还是挺累的),但是看到有留言催更、表示很赞时,我决定一定要把这篇文章写好送给大家。截止此刻通过这篇文章我的粉丝从0变成了18,非常感谢大家的认同,这对我也是很大的鼓励。之后会努力写出好的文章分享给大家。最后,希望大家都不忘初心,共同进步成长!像我掘金的ID一样,祝大家KDDA(keep da dream alive)

关于本文

作者:KDDA_

https://juejin.cn/post/6953042611963691021

参考资料

[1]

https://github.com/postcss/autoprefixer

[2]

https://github.com/postcss/postcss

[3]

https://github.com/postcss/postcss#plugins

[4]

https://www.babeljs.cn/docs/plugins

[5]

https://www.babeljs.cn/docs/presets

[6]

https://webpack.js.org/configuration/mode/

[7]

https://webpack.docschina.org/plugins/mini-css-extract-plugin/

[8]

https://webpack.docschina.org/plugins/html-webpack-plugin/

[9]

https://github.com/jantimon/html-webpack-plugin#options

[10]

https://www.npmjs.com/package/clean-webpack-plugin

[11]

https://webpack.docschina.org/contribute/writing-a-loader/

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

_

https://juejin.cn/post/6953042611963691021

参考资料

[1]

https://github.com/postcss/autoprefixer

[2]

https://github.com/postcss/postcss

[3]

https://github.com/postcss/postcss#plugins

[4]

https://www.babeljs.cn/docs/plugins

[5]

https://www.babeljs.cn/docs/presets

[6]

https://webpack.js.org/configuration/mode/

[7]

https://webpack.docschina.org/plugins/mini-css-extract-plugin/

[8]

https://webpack.docschina.org/plugins/html-webpack-plugin/

[9]

https://github.com/jantimon/html-webpack-plugin#options

[10]

https://www.npmjs.com/package/clean-webpack-plugin

[11]

https://webpack.docschina.org/contribute/writing-a-loader/

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-itdihmWT-1710927728168)]
[外链图片转存中…(img-F62BZobw-1710927728168)]
[外链图片转存中…(img-XochqXhp-1710927728169)]
[外链图片转存中…(img-axVJq2zc-1710927728169)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
[外链图片转存中…(img-uF3dZR4Z-1710927728169)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值