- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
webpack的核心概念,放到2022年相信很多的小伙伴都已经非常清楚了。但是,对于webpack配置中的output.path、output.filename以及output.publicPath,还有很多小伙伴还不理解。本文讲围绕output.filename、output.path与output.publicPath,讲解它们的功能,并分析这些配置与webpack中常使用到的MiniCssExtractPlugin、HtmlWebpackPlugin等插件的关系.
直接上总结图 。
我们现在基于webpack搭建了一个前端项目,完成项目初始化,并安装webpack三件套:
yarn init
yarn add -D webpack webpack-cli webpack-dev-server
安装完成以后,我们在项目根目录下创建一个webpack.config.js,一个极简的配置如下:
const {resolve} = require('path');
module.exports = {
mode: 'development',
entry: {
main: resolve(__dirname, 'src', 'index.js')
},
output: {
filename: 'main.js',
path: resolve(__dirname, 'dist')
}
}
然后,在package.json中添加脚本:
+ "scripts": {
+ "build": "webpack --config webpack.config.js"
+ },
"devDependencies": {
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1"
}
接着,我们在src目录下创建一个index.js文件,这个js文件的内容就是从dom上找到id为app的元素,并给其内部添加一个文本 "hello, world" :
document.getElementById('app').innerText = 'hello, world'
最后,我们运行webpack的构建过程:
yarn build
运行以后,就会在项目根目录下的dist目录下生成main.js.
注意:这里并没有配置关于js的解析,因为webpack默认就会处理js文件.
仅仅是生成目标js文件,可能还不是我们期望的效果。对于一个项目来说,我们通常还希望有一个html来展示UI,并运行js代码,但是手工创建可能不能是一个好的方案。这里,我们引入本项目的第一个插件: HtmlWebpackPlugin .
yarn add -D html-webpack-plugin
HtmlWebpackPlugin插件 基础 功能:
安装好该插件以后,在之前的webpack配置中,我们适当的修改:
const {resolve} = require('path');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
@@ -7,5 +8,10 @@ module.exports = {
output: {
filename: 'main.js',
path: resolve(__dirname, 'dist')
- }
+ },
+ plugins: [
+ new HtmlWebpackPlugin({
+
+ })
+ ]
}
让我们再次运行构建脚本后,我们会发现,dist目录中,不仅仅生成了main.js,还生成一个index.html:
通过检查这个index.html的内容可以看到,这个插件不仅仅帮我们生成了一个html,还在这个html中的head节点中创建了一个script节点,并且src属性填写的是main.js.
此时,我们使用浏览器直接打开这个index.html,尽管是在文件系统,但浏览器还是可以通过script节点中的属性`src="main.js",从index.html所在同级目录中加载main.js。然而,运行起来有报错:
PS:这里有同学可能会认为是script节点在body以前加载的,所以会报错。但是实际不是这样的,这里script节点中有一个 defer 属性,这个属性表明,文档加载完毕以后才会执行main.js( MDN - defer ),所以,我们不用担心由于DOM未加载完就执行js代码而造成报错.
这个地方的问题在于:我们的main.js中会执行查找id为app的元素,但是实际生成的html是没有这个元素的.
为了解决上述的问题,我们希望能够自定义生成index.html。通常的做法就是:
<div id="app"></div>
):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>这是一个模板HTML</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
</div>
</body>
</html>
template
参数,表明使用上述的创建的index.html:
plugins: [
new HtmlWebpackPlugin({
+ template: resolve(__dirname, 'public', 'index.html')
})
]
我们再次运行构建,可以看到在dist目录下的index.html是基于我们提供的模板生成:
此时,我们再次打开这个html,可以看到正确的处理后的结果:
让我们回到关于output.path与output.filename上来。回顾我们的webpack配置:
output.filename:确定js最终生成的文件名 。
output.path:确定js所在的根路径 。
js最终生成的路径是:
output.path(绝对路径) + output.filename(文件名,可以有相对路径前缀) 。
做一个简单的实验便可知,例如,我们修改配置如下,把output.filename改为 "js/main.js" ,output.path改为 'resolve(__diranme, "my-dist")' :
output: {
- filename: 'main.js',
- path: resolve(__dirname, 'dist')
+ filename: 'js/main.js',
+ path: resolve(__dirname, 'my-dist')
},
重新经过构建以后,我们会看到 my-dist 目录被创建,并且这个目录下面还会创建 js 目录, js 目录中会有main.js,正好匹配了 output.path(项目根目录/my-dist) + output.filename(js/main.js) .
但是,output.filename与output.path仅仅影响js的生成吗?不然,让我看看这两个参数对于HtmlWebpackPlugin的关联关系.
对于上述生成结果,我们会注意到,在webpack配置中的HtmlWebpackPlugin插件部分,我们没有编写过任何关于index.html的生成路径的配置,但这个index.html最终也生成到了 "my-dist" 目录下(与output.path一致);此外,我们还可以发现,生成的index.html里面的script节点的src属性,是 "js/mian.js" (与output.filename一致).
我们可以整理一个图,来描述相关配置与js构建、HtmlWebpackPlugin插件的关联关系:
总结来说,output.path与output.filename不能单纯只作为输出js的配置,HtmlWebpackPlugin也会使用它们:
读者可以根据上述的表格,自己进行实验验证.
对于output.filename,需要注意的是,不能是一个绝对路径,譬如: "/js/main.js" or "/main.js" ,一旦配置成了绝对路径,就会看到报错:
configuration.output.filename: A relative path is expected. However, the provided value "/js/main.js" is an absolute path!
Please use output.path to specify absolute path and output.filename for the file name.
你只能写成: "js/main.js" 或 "./js/main.js" 。然而,由于生成的html中script节点属性src的值,来源于这个output.filename值,如果我们有需求,希望生成的src等于一个绝对路径,譬如: src="/js/main.js" ,仅仅靠output.filename是不行的。于是乎,output.publicPath就登场了! 。
首先,在webpack中,这个参数不配置的话,默认是空字符串 "" 。然后,我们需要 纠正我们前面的一个结论 :
实际上,script节点的src属性的路径,并不只是output.filename来决定的,而是由output.publicPath与output.filename共同决定:
src = output.publicPath(还有斜杠的特殊处理,后面讲)+ output.filename 。
只是因为output.publicPath默认是空字符串,所以我们前面生成出来的只是 src="js/main.js" 。这里,我们可以做一个简单的实验,配置publicPath为 "/" ,则生成的节点就会成为: <script src="/js/main.js"> 。
output.publicPath: "abc"(尾部没有"/"),src="abc/js/main.js":
output.publicPath: "/abc"(尾部依然没有"/"),src="/abc/js/main.js":
仔细观察这几种场景,就可以知道HtmlWebpackPlugin插件,在生成html中的script标签时候,其中的src属性依赖output.filename以及output.publicPath,并且规则为:
需要注意的是,谨记js文件与html文件的生成不会受到output.publicPath的影响,只跟output.path和filename(js是output.filename,html是HtmlWebpackPlugin的filename)相关.
于是乎,我们重新整理前面的关系图,把output.publicPath配置引入:
细心的读者已经想到了,假如publicPath配置成了"/static/",影响了HtmlWebpackPlugin中的script节点的src属性路径;而js文件实际生成路径仅受到output.path+output.filename,势必造成js访问路径不匹配的问题:
所以,日常对于webpack的配置一定要注意这种路径问题,保持匹配,否则使用webpack-dev-server就会出现问题~ 。
相信看到这里,很多读者对output中的path、filename以及publicPath能够理解他们的效果了。接下来,我们举一反三,引入常用的CSS打包工具MiniCssExtractPlugin也来分析一下.
我们通常会有这样的需求,一个前端项目打包的时候,希望能够将项目依赖的css文件最终抽离为一个或N个css文件,并让我们的前端html直接以link节点的形式加载。这个时候,我们一般使用MiniCssExtractPlugin来完成这个需求。当然,除了这个插件以外,我们还需要一个最基础的loader: css-loader .
yarn add -D css-loader mini-css-extract-plugin
工程结构不会变化:
项目根目录/
├─ package.json
├─ public
│ └─ index.html
├─ src
│ └─ index.js
└─ webpack.config.js
内容主要是新增了css-loader与mini-css-extract-plugin.
接下来,我们编写一个简单的css样式文件存放于src目录下(src/my-style.css):
body {
background-color: aqua;
}
#app {
background-color: azure;
}
并修改index.js的代码,在index.js中引用它:
+import './my-style.css';
document.getElementById('app').innerText = 'hello, world'
此时,如果我们不进行任何的配置,运行webpack打包,会看到报错:
ERROR in ./src/my-style.css 1:5
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
核心问题在于,webpack无法处理index.js中关于 .css 的文件(webpack默认值处理js文件)。所以,需要我们配置专门处理css的规则:
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
... ...
plugins: [
new HtmlWebpackPlugin({
template: resolve(__dirname, 'public', 'index.html')
}),
+ new MiniCssExtractPlugin({
+ filename: 'css/main.css'
+ })
],
+ module: {
+ rules: [{
+ test: /\.css/,
+ use: [MiniCssExtractPlugin.loader, 'css-loader']
+ }]
+ }
}
首先引入MiniCssExtractPlugin插件;然后在plugins中,new出MiniCssExtractPlugin插件实例,并传入filename配置 css/main.css ;最后,配置module.rules中,添加对css的处理:
loader的执行顺序是按照数组从后向前的,所以use数组最后是css-loader,然后才是MiniCssExtractPlugin提供的loader。webpack在构建过程,遇到引用css的场景,则先调用css-loader,对css文件进行处理,然后调用MiniCssExtractPlugin提供的loader进行抽取 。
完成配置以后,我们再次启动webpack的构建,会看到dist目录下,又会产生一个css目录,里面存放的就是mian.js,并且,检查index.html会发现这一次除了script标签外,还插入了link标签:
有的读者可能已经能够推断出,这个link标签的href路径,也是根据output.publicPath+MiniCssExtractPlugin插件的filename组合而来。这里直接给出结论,就是这样的。我们再次更新图表,把导出css样式文件的MiniCssExtractPlugin插件与相关的配置关系也总结进去,得到如下最终版关系图:
通过关系图,我们很容易知道,webpack中关于文件生成最核心的配置就是output.path以及各种filename,js的生成、css的生成、html的生成都依赖了这套配置; 。
其次,与js相关的output.filename和与css相关的MiniCssExtractPlugin.filename配置都有两个作用:
最后,本文并没有讲到webpack-dev-server和上述配置的关系,这个会在本《掌握webpack》系列中单独出一期.
最后此篇关于掌握webpack(一)一张图让你明白webpack中output的filename、path、publicPath与主流插件的关系的文章就讲到这里了,如果你想了解更多关于掌握webpack(一)一张图让你明白webpack中output的filename、path、publicPath与主流插件的关系的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在用 C 语言实现一个带有输入和输出重定向的 shell。我可以成功进行输入重定向,但输出重定向不起作用。例如,如果我执行 ls > out.txt,则 out.txt 包含文本“out.txt”
我正在处理创建 AWS API 网关。我正在尝试创建 CloudWatch Log 组并将其命名 API-Gateway-Execution-Logs_${restApiId}/${stageName
我正在修改原作者使用数组构建网页的一些代码: $output[]=$stuff_from_database; $output[]='more stuff'; // etc echo join(
我只想知道它们之间的区别: sort < output 和 sort output 在 Linux 中。它是如何工作的? 最佳答案 这已经在 unix.stackexchange 上讨论过:Perfo
我正在生成外部控制台应用程序并使用异步输出重定向。 as shown in this SO post 我的问题是,在我收到 OutputDataReceived 事件通知之前,生成的进程似乎需要产生一
在 Udemy 上开设类(class)时,我们一直允许使用组件类中的 @Input() 装饰器向组件传递数据。 在阅读 ngBook-2 时,我发现还有另一种方法,即在 @Component 装饰器中
考虑一个 Linux 服务器,它在您的用户的 .bash_profile 中有以下行: echo "Hello world" 因此,每次您通过 ssh 进入它时,您都会看到 Hello world 现
public static void main(String[] args) { String input = new String(JOptionPane.showInputDialog("
我正在使用 MSVS 2008 中的 FFTW3 库对某些数据执行 r2c DFT (n=128)。我已经发现只使用了真实数据 DFT 输出的前半部分……如果我查看我的输出,这似乎是正确的: 0-64
我制作了一个 C 程序,可以从二进制文件中打印出很多值。我相信程序完成它的功能并在它实际显示它吐出的值之前结束。因此,结果我得到了一个可爱的 RUN SUCCESSFUL(总时间:198ms) 突然出
在 hadoop 作业计数器中,“映射输出具体化字节”与“映射输出字节”之间有什么区别?当我禁用映射输出压缩时我没有看到前者所以我猜它是真正的输出字节(压缩)而后者是未压缩的字节? 最佳答案 我认为你
有很多 Stack Overflow 文章与此相关,但没有直接的答案。 这条命令会输出一堆单词 OutputVariable.exe %FILEPATH% 输出: Mary had a little
互联网上的许多文章都使用“标准输入/输出/错误流”术语好像每个术语都与使用的“标准输入/输出/错误设备”术语具有相同的含义在其他文章上。例如,很多文章说标准输出流默认是监视器,但可以重定向到文件、打印
我在 Keras 中使用一些 tensorflow 函数(reduce_sum 和 l2_normalize)在最后一层构建模型时遇到了这个问题。我已经搜索了一个解决方案,但所有这些都与“Keras
我有来自 API 的自定义输出,我想将其格式化为带有一些颜色值的字符串。 最佳答案 输出 channel 可以用 TmLanguage grammar 着色. Output Colorizer扩展扩展
我正在寻找一种方法来查看虚拟机创建过程中发生的情况,因为我使用复杂的集群配置并测试其是否正常工作,我需要能够查看输出,在某些情况下我是不是因为敏感。这与运行remote-exec选项有关 module
当谷歌搜索此错误时没有看到任何相关结果,所以我想发布它。 stack build Building all executables for `gitchapter' once. After a suc
假设module_a里面有register_a,它需要链接到module_b。 register_a 是否应该单独声明并分配给 module_a 的输出: reg register_a; assign
我正在寻找一种方法来查看虚拟机创建过程中发生的情况,因为我使用复杂的集群配置并测试其是否正常工作,我需要能够查看输出,在某些情况下我是不是因为敏感。这与运行remote-exec选项有关 module
输入文件如下 eno::ename::dept::sal 101::emp1::comp1::2800000 201::emp2::comp2::2800000 301::emp3::comp3::3
我是一名优秀的程序员,十分优秀!