前言
作为后端开发者,相信大家或多或少都接触过webpack。 如今,webpack已经渗透到后端的各个方面,所以我们有必要了解和学习webpack。 Webpack 是一个用于构建 JavaScript 应用程序的工具。 静态模块打包器,它还可以以相对一致且开放的处理方式加载应用程序中的所有资源文件(图像、CSS、视频、字体文件等),并将其合并打包成浏览器兼容的网页资源。 文档。 与其他重构工具相比,webpack 功能更强大,扩展性更强。 它还可以集成多种工程工具,将开发阶段的应用代码编译打包成适合网络分发和客户端运行的应用产品。 。
核心概念输入输出入口
Webpack 的创建入口“入口点”指示 webpack 应该使用哪个模块作为构建其内部依赖关系图的开始。 进入入口点后,webpack 会找出入口点所依赖的模块和库(直接和间接)。
// 单入口
module.exports = {
entry: './src/main.js'
}
// 多入口
module.exports = {
entry: {
a: './src/a.js',
b: './src/b.js'
}
}
输出
“output”属性告诉 webpack 在哪里输出它创建的包,以及如何命名该文件。 主输出文件默认为 ./dist/main.js,其他生成的文件默认放置在 ./dist 文件夹中。
// 单入口
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
}
}
// 多入口
module.exports = {
entry: {
a: './src/a.js',
b: './src/b.js'
},
output: {
filename: '[name].[hash:6].js', // 通过占位符确保文件名唯一,考虑缓存问题,还可以为文件名加上hash
path: __dirname + '/dist',
publicPath: '/', // 生产环境一般是CDN地址,开发环境配置为/或不配置
}
}
模块处理加载器
webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱即用的内置功能。 “Loaders”允许 webpack 处理其他类型的文件并将其转换为可供应用程序使用并添加到依赖关系图中的有效模块。
例如:配置 webpack 将 css-loader 应用于 css 文件
module.exports = {
module: {
rules: [
{test: /.css$/, use: 'css-loader'}
]
}
}
module.rules 允许您在 webpack 配置中指定多个加载器。 这种方法是显示加载程序的简洁方法,有助于使代码显得紧凑且易于维护。
插入
“插件”是 webpack 的支柱。 Webpack 本身构建在您在 webpack 配置中使用的相同插件系统上!
插件的目的是解决加载器无法实现的“其他事情”。 Webpack 提供了许多开箱即用的插件。
例如:为编译过程添加进度报告插件
const Webpack = require('webpack')
module.exports = {
plugins: [new Webpack.ProgressPlugin()]
}
解决
用于配置模块路径解析规则,可用于帮助Webpack更准确、高效地找到指定模块
例如配置别名:
创建导入别名或 require 以使模块导入显得更简单。 例如,位于 src/ 文件夹中的一些常用模块:
module.exports = {
resolve: {
alias: {
node_modules: path.resolve(__dirname, './node_modules'),
'@': path.resolve(__dirname, './src'),
api: path.resolve(__dirname, './src/api'),
components: path.join(__dirname, './src/components'),
}
}
}
模块
这些选项决定如何处理项目中不同类型的模块。
比如我们常见的loader是在module.rules中配置的。
module.exports = {
module: {
rules: [
{test: /.css$/, use: 'css-loader'}
]
}
}
外部因素
用于声明外部资源,Webpack会直接忽略这部分资源,跳过此类资源的解析和打包操作
例如,要“防止”单个导入的包被“打包”到捆绑包中,请在运行时从外部获取此类“外部依赖项”。
例如:从CDN引入Vue
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.3/vue.min.js"></script>
// webpack.config.js
module.exports = {
externals: {
vue: 'vue'
}
}
后处理优化
用于控制如何优化产品包的体积,内置了Dead Code Elimination、Scope Hoisting、代码混淆、代码压缩等功能
从 webpack 4 开始,会根据你选择的模式进行不同的优化,但所有优化仍然可以自动配置和重绘。
module.exports = {
//...
optimization: {
chunkIds: 'named',
},
};
目标
用于配置编译产品的目标运行环境。 支持Web、Node、Electron等值。 不同的值最终的产品也会有所不同。
例如:如果target设置为node,webpack就会在node环境下编译
module.exports = {
target: 'node'
}
模式
提供模式配置选项,告诉webpack使用相应模式的外部优化。
string = 'production': 'none' | 'development' | 'production'
module.exports = {
mode: 'development',
};
或者从 cli --mode 参数传递
webpack --mode development
开发效率观察
启用观看模式。 这意味着在初始构建之后,webpack 将继续侦听对任何已解析文件的修改。
module.exports = {
watch: true
}
“注意:webpack-dev-server 和 webpack-dev-middleware 默认启用监视模式。”
开发工具
此选项控制是否以及如何生成源映射。
string = 'eval' | false
选择源映射样式以改进调试过程。 不同的值将显着影响构建和重建率。
开发服务器
用于配置与HMR强相关的开发服务器功能
通过 webpack-dev-server 的此配置webpack定义模块,可以通过多种方式更改其行为。 这里比较常见的配置有:端口、主机、代理等。
module.exports = {
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 9000,
}
}
缓存
Webpack 5之后webpack定义模块,此项用于控制如何缓存编译过程信息和编译结果。
缓存生成的 webpack 模块和块以提高构建速度。 缓存将在开发模式下设置为 type: 'memory' 并在生产模式下禁用。 cache: true 与cache: { type: 'memory' } 配置相同。 传递 false 将禁用缓存:
module.exports = {
cache: false
}
入门配置
了解了webpack的核心概念后,我们可以尝试自动配置一个Vue开发环境
初始化项目
首先 npm init -y 初始化 package.json 文件
然后安装我们的webpack,webpack-cli
npm i webpack webpack-cli -D
“注意:我的 webpack 是版本 5”
"webpack": "^5.85.1",
"webpack-cli": "^4.7.2",
使用 Vue 代码
Native Webpack无法处理这些内容格式的文件,因此我们需要引入一个专用于Vue SFC的加载器:vue-loader
npm i vue-loader
// webpack.config.js
const Webpack = require('webpack')
const {VueLoaderPlugin} = require('vue-loader')
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.[hash:6].js',
path: __dirname + '/dist',
},
module: {
rules:[
{test: /.vue$/, use: 'vue-loader'},
]
},
plugins:[
new Webpack.ProgressPlugin(),
new VueLoaderPlugin(),
],
}
“提示:vue-loader 库同时提供了用于处理 SFC 代码翻译的 Loader 组件和用于处理上下文兼容性的 Plugin 组件。两者需要同时配置才能正常运行。”
此时我们的文件结构是这样的,与Vue项目结构大致一致
尝试启动它并查看:
// package.json
"dev": "webpack --mode development",
npm run dev
由于我们的vue文件中有css内容,而webpack默认不理解css内容,所以报错
处理 CSS 内容
这里需要安装style-loader和css-loader进行处理。
修改webpack配置
// webpack.config.js
const Webpack = require('webpack')
const {VueLoaderPlugin} = require('vue-loader')
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.[hash:6].js',
path: __dirname + '/dist',
},
module: {
rules:[
{test: /.vue$/, use: 'vue-loader'},
{
test: /.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins:[
new Webpack.ProgressPlugin(),
new VueLoaderPlugin(),
],
}
这时候再运行,发现没有报错。
处理JS内容
我们日常开发中肯定会用到ES6句型。 这里我们还需要配置相应的loader来进行处理。
“安装 babel-loader”
npm i babel-loader @babel/preset-env @babel/core
“配置”
module.exports = {
module: {
rules: [
{
test: /.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
},
exclude: /node_modules/
}
]
}
}
当然,你也可以在.babelrc或者babel.config.js中单独配置这里的options配置。
处理图像资源
和 CSS 一样,webpack 默认不理解图像,所以这里需要配置 loader 来处理。
「webpack4」
在webpack4中,我们常用的处理图片的loader有:file-loader、url-loader
// webpack.config.js
module.exports = {
// ...
module: {
rules: [{
test: /.(png|jpg|gif|jpeg)$/,
use: ['file-loader']
}],
},
};
经过file-loader处理后,原始图片将被重命名并复制到产品文件夹中,图片URL地址将被插入到代码中。
module.exports = {
// ...
module: {
rules: [{
test: /.(png|jpg|gif|jpeg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1024
}
}]
}],
},
};
经过 url-loader 处理后,小于 limit 参数(1024B)的图片将被转换为 Base64 编码。 对于超过限制值的图片,会直接调用file-loader完成加载。
「webpack5」
file-loader 和 url-loader 不仅限于处理图像。 它们还可以用于加载任何类型的多媒体或文本文件。 它们使用如此频繁,几乎已经成为标准组件! 因此,Webpack5直接外部化了这个能力,可以开箱即用。
使用上来说,原本需要安装并导入Loader。 Webpack5之后,只需要通过 module.rules.type 属性指定资源类型即可。
例如:
module.exports = {
// ...
module: {
rules: [{
test: /.(png|jpg|gif|jpeg)$/,
type: 'asset/resource'
}],
},
};
运行页面
配置了这么多内容,我们还看不到页面的内容,我们也肯定不想看到。 虽然上面的步骤相当于翻译了Vue SFC文件的内容,但是我们仍然需要让页面真正运行起来。
粗略计划
有一个快速的方法可以验证我们的打包配置是否正确:我们只需要新建一个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">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="../dist/bundle.42603d.js"></script>
</body>
</html>
如果我们在浏览器中打开这个html文件,可以看到我们的vue项目可以正常打开。
“这种方案的一个缺点是,我们打包的文件通常带有哈希值,这需要我们每次打包后都去HTML文件中更改导入的文件。这样是不是有点太费力了?您能忍受吗? ?”
优雅的解决方案
上述方案在日常开发中实际上是无法接受的。 作为一个程序员,能偷懒就一定偷懒!
我们可以使用以下两个工具来使这个过程更加智能和自动化。
“html-webpack-plugin:自动生成HTML页面”
HtmlWebpackPlugin 简化了 HTML 文件的创建来为您的 webpack 包提供服务。 这对于文件名中包含哈希值且哈希值随每次编译而变化的 webpack 包很有用。
“webpack-dev-server:让页面真正运行起来,并且具备热更新能力。”
webpack-dev-server 主要提供两个功能:
“安装”
npm i html-webpack-plugin webpack-dev-server
“修改设置”
const Webpack = require('webpack')
const {VueLoaderPlugin} = require('vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.[hash:6].js',
path: __dirname + '/dist',
},
module: {
rules:[
{test: /.vue$/, use: 'vue-loader'},
{
test: /.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
},
exclude: /node_modules/
},
{
test: /.(png|jpg|gif|jpeg)$/,
type: 'asset/resource',
}
]
},
plugins:[
new Webpack.ProgressPlugin(),
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html',
filename: 'index.html'
})
],
devServer: {
hot: true,
open: true
}
}
“修改启动脚本”
"dev": "webpack serve --mode development"
“跑步”
npm run dev
这时候webpack就可以手动帮我们打开浏览器运行页面
vue文件内容如下:
webpack + vue -- {{ name }}
import { ref } from 'vue'
const name = ref('前端南玖')
.title {
font-size: 16px;
font-weight: bold;
color: salmon;
}
.top_bg {
width: 100%;
height: auto;
}
“如果本文对您有帮助,请关注+点赞鼓励作者,文章将发布在公众号上,关注前端南九第一时间获取最新文章~”
发表评论