Webpack 项目中 html-webpack-plugin 和 public 目录的关系

本文探讨了在 Webpack 项目中,html-webpack-plugin 的作用及其与 public 目录的关系。public 目录作为静态资源目录,用于存放项目中的静态文件,可以通过 webpack-dev-server 访问。html-webpack-plugin 则负责在打包时生成 HTML 文件并自动引入打包后的文件,解决了动态文件名在 HTML 中写死的问题。文章通过分析配置和流程,解释了脚手架项目如何实现这一功能。
摘要由CSDN通过智能技术生成

这几天一直在研究 Webpack 这些打包工具链,在研究项目启动的过程中,初步认识到平时开发时是通过 Webpack-dev-server 调用 Webpack 的打包能力结合静态资源服务器能力开发的

大概是下面这个图片

但是由于 webpack-dev-server 为了更快,它的打包文件都是放在缓存里的,对于我来说其实可以说是黑盒操作

首先来到我的第一个疑问

public 目录是什么?

通常基于 Webpack 的项目都会有一个 public 文件夹

比如 Vue CLI@4.5.15 创建的项目

├── node_modules
├── public
|├── favicon.ico
|└── index.html
├── src
├── babel.config.js
├── package.json
├── package-lock.json
└── README.md 

比如 creat react app@5.0.1

├── node_modules
├── public
|├── favicon.ico
|├── index.html
|├── logo192.png
|├── logo512.png
|├── manifest.json
|└── robots.txt
├── src
├── .gitignore
├── babel.config.js
├── package.json
├── package-lock.json
└── README.md 

共同点是都有 public/index.htmlpublic/favicon.ico,如果你尝试修改 index.html 还可以在浏览器中看到相应的修改

首先解密 public 目录是干什么的?

静态资源目录

public 其实是作为 Webpack 的静态资源目录,通过 http 请求的方式访问 public 目录下的文件内容,默认 http://localhost:port/ 会返回 publicindex.html

那么可不可以返回其它的文件呢?

当然可以,但是需要改动的地方会比较长,webpack-dev-server 提供的静态资源是依靠一下库的赋能

webpack-dev-server <- express <- serve-static

回到正题Webpack 作为前端工具链重要的一环,有一个很重要的作用就是热更新,并将热更新修改内容反映在我们的浏览器中,这也就是我们需要 public/index.html,为什么需要静态资源服务器

那么来到我的第二个疑问

既然 public/index.html 是热更新的入口,那么为什么没有看到脚手架创建的 publc/index.html 中存在和打包文件相关的部分呢?

里面纯手工运行了一个 Vue 项目(以单文件组件(SFC/.vue)的方式)

但里面的 index.html 需要依赖打包文件

<!-- index.html -->
<body><div id="app"></div>
</body>
<script type="text/javascript" src="bundle.js" charset="utf-8"></script> 
// webpack.config.js
// ...
module.exports = {mode: "development",devServer: {static: {directory: path.join(__dirname, "public"),},port: 8080,},// ...entry: path.join(__dirname, "./main.js"),output: {publicPath: "",filename: "bundle.js",},// ...
}; 

但脚手架的默认 index.html 是没有任何的 js 引入的,以 Vue CLI 为例

<!-- index.html -->
<!DOCTYPE html>
<html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1.0"><link rel="icon" href="<%= BASE_URL %>favicon.ico"><title><%= htmlWebpackPlugin.options.title %></title></head><body><noscript><strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><!-- built files will be auto injected --></body>
</html> 

但你先别急,脚手架项目运行之后的 index.html 可不是上面这样的,实际如下

<!DOCTYPE html>
<html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1.0"><link rel="icon" href="/favicon.ico"><title>vue-cli-create-demo</title><link href="/js/app.js" rel="preload" as="script"><link href="/js/chunk-vendors.js" rel="preload" as="script"></head><body><noscript><strong>We're sorry but vue-cli-create-demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><!-- built files will be auto injected --><script type="text/javascript" src="/js/chunk-vendors.js"></script><script type="text/javascript" src="/js/app.js"></script></body>
</html> 

对比上下两个 index.html 的内容,多出了 .js 的引入以及 <%= htmlWebpackPlugin.options.title %> 被覆盖

所以脚手架它们到底是怎么做到呢?

html-webpack-plugin

回到上面的两个 index.html 里面有个 htmlWebpackPlugin 很关键,其实答案就在它身上,文档上关于 html-webpack-plugin 的介绍是这样的

HtmlWebpackPlugin 简化了 HTML 文件的创建,以便为你的 webpack 包提供服务。这对于那些文件名中包含哈希值,并且哈希值会随着每次编译而改变的 webpack 包特别有用。你可以让该插件为你生成一个 HTML 文件,使用 lodash 模板提供模板,或者使用你自己的 loader

那么它和 public/index.html 有什么联系呢?我从它的配置上得到了答案

其实这个 html-webpack-plugin 干的活就是会在 webpack 打包时生成 index.html 并且放置在 webpack-dev-server 设置的静态资源服务文件夹,因此会替换掉默认的 index.html通常用户设置的 index.html 会作为 webpack-dev-server 调用 Webpack 打包能力时通过 html-webpack-plugin 的模版,基于此生成一个 index.html,因此像 Vue CLI 此类脚手架会在配置中设置插入打包文件的脚本引入,因此无需用户手动配置

大致流程如下图

要实现基本脚手架的这个能力可以参照下面的实现

// webpack.config.js
// ...
module.exports = {// ...plugins: [// ...
    new HtmlWebpackPlugin({
      // 设置模板
      template: "public/index.html",
      // 设置 html-webpack-plugin 以 defer 模式自动引入打包文件
      scriptLoading: "defer",
    }),
  ],
}; 

总结

为什么需要 html-webpack-plugin?比如生产环境的打包 js 文件其实是动态文件名,像这种情况不能够写死,因此就需要 html-webpack-plugin 去帮忙配置

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值