目录
- 图片文件
- 资源模块类型
- JS文件
- babel
- 命令行使用
- babel-loader
- babel-preset
- Vue文件
- vue-loader
- @vue/compiler-sfc
- plugin
- CleanWebpackPlugin
- HtmlWebpackPlugin
- DefinePlugin
图片文件
需要先在项目中使用图片,比较常见的使用图片的方式是两种:
img
元素,设置src
属性- 其他元素(比如
div
),设置background-image
的css
属性
在webpack5
之前,加载这些资源需要使用一些loader
,比如raw-loader
、url-loader
、file-loader
在webpack5
开始,我们可以直接使用资源模块类型(asset module type
),来替代上面的这些loader
资源模块类型
资源模块类型是指用于处理非 JavaScript
文件(例如 CSS
、图像、字体等)的一种机制
常见的资源模块类型包括以下几种:
-
asset/resource
:
-
用途:用于将文件(如图像、字体等)导出为单独的文件,并返回该文件的 URL(即路径)
-
作用:类似于
file-loader
,会在构建时将文件移到输出目录,最终导出的JavaScript
会引用文件的URL
-
适用文件类型:图像(如
.png
,.jpg
),字体文件(如.woff
,.ttf
),音视频文件等
-
-
asset/inline
:
-
用途:用于将文件(如小图像)以
Base64
字符串的形式嵌入到最终的JavaScript
中,而不生成单独的文件 -
作用:类似于
url-loader
,用于将文件转为Data URL
(Base64
编码),适合小文件,以减少HTTP
请求 -
适用文件类型:小图像、字体等文件,尤其是文件较小的情况
-
-
asset/source
:
-
用途:用于导出文件的源代码内容,而不是将它们打包成单独的文件或
Base64
字符串 -
作用:类似于
raw-loader
,返回文件的源代码内容作为JavaScript
模块导出的字符串。适用于直接想以字符串形式引入文件内容的情况 -
适用文件类型:文本文件(如
.txt
,.svg
,.md
),CSS
或其他代码文件
-
-
asset
:
-
用途:一种通用的资源模块类型,它可以在
asset/resource
和asset/inline
之间动态切换 -
作用:类似于
url-loader
,Webpack
会根据文件大小自动选择是将文件作为资源输出还是内联到代码中。如果文件大小超过指定限制(默认是8KB
),它会导出为资源文件;否则会作为内联文件处理 -
适用文件类型:图片、字体、音频、视频文件等
-
-
javascript/auto
:-
用途:这是
Webpack5
默认的JavaScript
模块类型,用于处理CommonJS、ES Modules
和其他类型的JavaScript
文件 -
作用:可以处理所有的
JavaScript
文件,并支持混合的模块类型(例如,既有import
也有require
的文件) -
适用文件类型:
.js
,.cjs
,.mjs
文件
-
-
javascript/esm
:-
用途:明确指定该模块只能使用
ECMAScript
模块(ESM
)的模块类型 -
作用:主要用于现代
JavaScript
的ES
模块化,import
和export
语法 -
适用文件类型:通常是
.mjs
文件,也可以是.js
文件,但明确支持ESM
-
上面主要介绍了四种处理图片的类型,打包图片时也可以加自定义设置:
- 自定义文件的输出路径和文件名:
-
常用的占位符:
[ext]
: 处理文件的扩展名[name]
:处理文件的名称[hash]
:文件的内容,使用MD4
的散列函数处理,生成的一个128位的hash
值(32个十六进制) -
方式一: 修改
output
,添加assetModuleFilename
属性const path = require("path"); module.exports = { entry: "./src/index.js", output: { filename: "index.js", path: path.resolve(__dirname, "build"), assetModuleFilename: "img/[name].[hash:6][ext]", // 放img目录下 图片名字.hash的前六位 扩展名 }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"], }, { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader", "postcss-loader"], }, { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: "asset", }, ], }, };
-
方式二: 在
Rule
中,添加一个generator
属性,并且设置filename
const path = require("path"); module.exports = { entry: "./src/index.js", output: { filename: "index.js", path: path.resolve(__dirname, "build"), // assetModuleFilename: "img/[name].[hash:6][ext]", // 放img目录下 图片名字.hash的前六位 扩展名 }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"], }, { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader", "postcss-loader"], }, { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: "asset", generator: { filename: "image/[name].[hash:8][ext]", }, }, ], }, };
-
- 图片大小设置
-
开发中往往是小的图片需要转换,但是大的图片直接使用图片即可
-
是因为小的图片转换
base64
之后可以和页面一起被请求,减少不必要的请求过程 -
而大的图片也进行转换,反而会影响页面的请求速度
-
将
type
修改为asset
,添加一个parser
属性,并且制定dataUrlCondition
,添加maxSize
属性const path = require("path"); module.exports = { entry: "./src/index.js", output: { filename: "index.js", path: path.resolve(__dirname, "build"), }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"], }, { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader", "postcss-loader"], }, { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: "asset", generator: { filename: "image/[name].[hash:8][ext]", }, parser: { dataUrlCondition: { maxSize: 100 * 1024, // 这时使用的图片没有超过这个值他就不会被打包成文件,而是转base64使用 }, }, }, ], }, };
-
JS文件
开发中,想要使用ES6+
的语法,想要使用TypeScript
,开发React
项目,这些文件的处理它们都是离不开Babel
的
babel
事实上,在开发中我们很少直接去接触babel
,但是babel
对于前端开发来说,目前是不可缺少的一部分,学习Babel
对于我们理解代码从编写到线上的转变过程至关重要
Babel
是一个工具链,主要用于旧浏览器或者环境中将ES6+``代码转换为向后兼容版本的JavaScript
,包括语法转换、源代码转换等
命令行使用
babel
本身可以作为一个独立的工具(和postcss
一样),不和webpack
等构建工具配置来单独使用
如果希望在命令行尝试使用babel
,需要完成如下操作:
-
npm install @babel/cli @babel/core -D
-
@babel/core
:babel
的核心代码,必须安装 -
@babel/cli
:可以让我们在命令行使用babel
-
-
npx babel src --out-dir dist
:使用babel
来处理源代码-
src
:是源文件的目录 -
--out-dir
:指定要输出的文件夹dist
-
-
拓展功能需要用到插件:
-
比如需要转换箭头函数,那么就可以使用箭头函数转换相关的插件
npm install @babel/plugin-transform-arrow-functions -D
npx babel src --out-dir dist --plugins=@babel/plugin-transform-arrow-functions
-
查看转换后的结果:会发现
const
并没有转成var
npm install @babel/plugin-transform-block-scoping -D
npx babel src --out-dir dist --plugins=@babel/plugin-transform-block-scoping,@babel/plugin-transform-arrow-functions
-
如果要转换的内容过多,一个个设置是比较麻烦的,可以使用预设(
preset
):npm install @babel/preset-env -D
npx babel src --out-dir dist --presets=@babel/preset-env
-
babel-loader
在实际开发中,通常会在构建工具中配置babel
来对其进行使用的,比如在webpack
中
-
之前已经安装了
@babel/core
,不需要再次安装 -
npm install babel-loader -D
-
可以设置一个规则,在加载
js
文件时,使用babel
babel-preset
如果一个个去安装使用插件,需要手动来管理大量的babel
插件,可以直接给webpack
提供一个preset
,webpack
会根据预设来加载对应的插件列表,并且将其传递给babel
-
常见的预设有三个:
env,react,TypeScript
-
安装
preset-env
:npm install @babel/preset-env
-
添加
wk.config.js
配置const path = require("path"); module.exports = { entry: "./src/index.js", output: { filename: "index.js", path: path.resolve(__dirname, "build"), }, module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"], }, { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader", "postcss-loader"], }, { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: "asset", generator: { filename: "image/[name].[hash:8][ext]", }, parser: { dataUrlCondition: { maxSize: 100 * 1024, // 这时使用的图片没有超过这个值他就不会被打包成文件,而是转base64使用 }, }, }, { test: /\.m?js$/, use: [ { loader: "babel-loader", options: { // presets: [ // [ // "@babel/preset-env", // { // targets: "> 0.25%, not dead", // useBuiltIns: "usage", // corejs: 3, // }, // ], // ], presets: ["@babel/preset-env"], }, }, ], }, ], }, };
Vue文件
- 编写
vue
代码// app.vue <template> <div class="box-vue"> <h2>hello vue</h2> <p>哈哈哈哈哈</p> </div> </template> <script setup></script> <style> .box-vue { width: 100px; height: 100px; background: cyan; } </style> // index.js import "./style.css"; import "./style.less"; import "./bgImg.css"; import App from "./app.vue"; import { createApp } from "vue/dist/vue.esm-bundler.js"; const img = require("./images/2.jpg"); const divEl = document.createElement("div"); divEl.innerHTML = `<div class='box-css'>hello css</div><div class='box-less'>hello less</div><div class='bgImg'></div><image class='img' src='${img}' />`; divEl.className = "box"; document.body.appendChild(divEl); createApp(App).mount("#app");
- 打包会报错,我们需要安装
vue-loader
vue-loader
-
npm install vue-loader -D
:安装vue-loader
-
添加配置
wk.config.js
:{ test: /\.vue$/, loader: "vue-loader" }
-
这时在打包依然会报错,因为需要添加
@vue/compiler-sfc
来对template
进行解析
@vue/compiler-sfc
-
npm install @vue/compiler-sfc -D
:安装@vue/compiler-sfc
,如果安装vue
时自动安装了就不需要安装了 -
需要配置对应的
Vue
插件:const path = require("path"); const { VueLoaderPlugin } = require("vue-loader/dist/index"); module.exports = { entry: "./src/index.js", output: { filename: "index.js", path: path.resolve(__dirname, "build"), }, plugins: [new VueLoaderPlugin()], module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"], }, { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader", "postcss-loader"], }, { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: "asset", generator: { filename: "image/[name].[hash:8][ext]", }, parser: { dataUrlCondition: { maxSize: 100 * 1024, // 这时使用的图片没有超过这个值他就不会被打包成文件,而是转base64使用 }, }, }, { test: /\.m?js$/, use: [ { loader: "babel-loader", options: { presets: ["@babel/preset-env"], }, }, ], }, { test: /\.vue$/, loader: "vue-loader", }, ], }, };
plugin
上面打包vue
我们引入了个新的知识插件,接下来学习plugin
相关内容
Webpack的另一个核心是Plugin
,官方有这样一段对Plugin
的描述:
-
Loader
是用于特定的模块类型进行转换 -
Plugin
除了loader功能其他都可以做,可以用于执行更加广泛的任务,比如打包优化、资源管理、环境变量注入等
CleanWebpackPlugin
前面练习的过程中,每次修改了一些配置,重新打包时都需要手动删除dist
文件夹,可以借助于一个插件来帮助完成就是 CleanWebpackPlugin
npm install clean-webpack-plugin -D
:安装- 在wk.config.js中配置
- 也可以使用
Webpack5
内置的clean
功能https://webpack.docschina.org/configuration/output/#outputclean
- 我们可以先在你打包后的文件夹创建个
abc.js
,然后配置完执行打包命令就可以看到它会把你打包文件夹下的abc.js
删除
HtmlWebpackPlugin
我们的HTML
文件是编写在根目录下的,最终打包的build
文件夹中是没有index.html
文件,但在进行项目部署的时,必然是需要有对应的入口文件index.html
,所以也需要对index.html
进行打包处理
-
npm install html-webpack-plugin -D
:对HTML
进行打包处理使用另外一个插件:HtmlWebpackPlugin
-
配置
wk.config.js
-
执行打包命令后,发现自动在
build
文件夹中,生成了一个index.html
的文件,该文件中也自动添加了我们打包的index.js
文件 -
html
默认情况下是根据ejs
的一个模板来生成的,在html-webpack-plugin
的源码中,有一个default_index.ejs
模块
-
也可以修改打包
index.html
的内容-
自定义
HTML
模板比如添加一个
noscript
标签,在用户的JavaScript
被关闭时,给予相应的提示比如在开发
vue
或者react
项目时,我们需要一个可以挂载后续组件的根标<div id="app">
-
自定义模板数据填充
上面的
html
中,会有一些类似这样的语法<% 变量 %>
,这个是EJS
模块填充数据的方式title
:可以在进行htmlWebpackPlugin.options.title
读取时,就会读到该信息template
:指定我们要使用的模块所在的路径filename
:生成的HTML
文件名inject
:插入打包的资源文件,默认值为true
。可以设置为'head'
或'body'
来指定资源注入的位置。minify
:对生成的HTML
进行压缩(常用于生产环境)collapseWhitespace
: 去除空白,removeComments
: 移除注释,removeAttributeQuotes
: 移除属性的引号
-
-
配置
wk.config.js
并打包// ./public/index.html <!DOCTYPE html> <html lang="en"> <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,user-scalable=no" /> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <noscript> <strong> We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue. </strong> </noscript> <div id="app"></div> </body> </html> // wk.config.js const path = require("path"); const { VueLoaderPlugin } = require("vue-loader/dist/index"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { entry: "./src/index.js", output: { filename: "index.js", path: path.resolve(__dirname, "build"), }, plugins: [ new VueLoaderPlugin(), new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: "haahha", template: "./public/index.html", filename: "main.html", minify: { collapseWhitespace: true, // 移除空白 removeComments: true, // 移除注释 removeAttributeQuotes: true, // 移除属性的引号 }, }), ], module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"], }, { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader", "postcss-loader"], }, { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: "asset", generator: { filename: "image/[name].[hash:8][ext]", }, parser: { dataUrlCondition: { maxSize: 100 * 1024, // 这时使用的图片没有超过这个值他就不会被打包成文件,而是转base64使用 }, }, }, { test: /\.m?js$/, use: [ { loader: "babel-loader", options: { presets: ["@babel/preset-env"], }, }, ], }, { test: /\.vue$/, loader: "vue-loader", }, ], }, };
我们配置完打包发现还是报错,因为在模块中还使用到一个BASE_URL
的常量,要用到下面的插件
DefinePlugin
在模块中还使用到一个BASE_URL
的常量,但是我们并没有设置过这个常量值,所以会出现没有定义的错误,这个时候可以使用DefinePlugin
插件
-
DefinePlugin
允许在编译时创建配置的全局常量,是一个webpack
内置的插件(不需要单独安装) -
在
wk.config.js
配置再打包就可以取到BASE_URL
不会报错了