前言
作为前端,在日常开发项目中,我们常使用vue
、react
来开发项目。webpack
在其中起到了很重要的作用,下面我们就去认识一下。
本文开发版本
webpack 5.73.0
vue 3.2.37
npm 7.21.0
1. 搭建一个本地服务
在平常开发项目时,我们会先搭建一个开发环境,用于本地调试。本文先使用webpack
的webpack-dev-server
简单搭建一个vue
本地服务,然后再一一学习相应的内容。
1.1 初始化
新建一个目录,初始化一个package.json文件
npm init -y
安装几个需要用到的包
npm install webpack webpack-cli webpack-dev-server --save-dev
npm install vue vue-loader --save-dev
npm install html-webpack-plugin --save-dev
1.2 新建文件
在根目录新建以下几个文件:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello webpack</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
src\main.js
import { createApp } from "vue"
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
src\App.vue
<template>
<div>hello webpack</div>
</template>
build\dev.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
mode: 'development', // 开发模式
entry: {
app: path.resolve(__dirname, '../src/main.js')
},
devServer: {
hot: true,
host: 'localhost',
open: false,
port: 8866
},
module: {
rules: [
{
test: /\.vue$/,
use: [
{ loader: 'vue-loader' }
]
}
]
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
})
]
}
最后在package.json
文件scripts
中新增dev
属性:
"scripts": {
"dev": "webpack-dev-server --config build/dev.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
完成以上操作后,运行npm run dev
命令,然后在浏览器中输入地址http://localhost:8866/
,浏览器会显示hello webpack
,能成功显示说明配置成功了。
2. 对项目进行打包
通过上面的配置搭建好了一个开发服务,但开发完以后需要打包上线。下面来看下打包需要配置那些。
2.1 配置output
在build\prod.js 添加输出配置output: 表示打包后文件存放位置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
mode: 'production', // 生产模式
entry: {
app: path.resolve(__dirname, '../src/main.js')
},
module: {
rules: [
{
test: /\.vue$/,
use: [
{ loader: 'vue-loader' }
]
}
]
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'static/js/[name].[chunkhash:8].js',
publicPath: '/'
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
})
]
}
2.2 使用babel转义
其中需要注意它们的版本,我这里使用了固定版本。安装
babel-loader@8.1.0
@babel/core@7.1.6
@babel/preset-env@7.1.6
npm install babel-loader@8.1.0 @babel/core@7.1.6 @babel/preset-env@7.1.6 --save-dev
使用
build\prod.js
module.exports = {
...,
module: {
rules: [
...,
{
test: /\.js$/,
use: ['babel-loader'],
exclude: /(node_modules)/,
include: [resolve('src'), resolve('test')]
}
]
},
}
然后在package.json
文件scripts
中新增build
属性:
"scripts": {
"dev": "webpack-dev-server --config build/dev.js",
"build": "webpack --config build/prod.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
构建配置时,完成上面两个的修改,运行npm run build
命令,会生成一个dist目录,打包后的文件都保存在这个目录。
3 配置分析
完成上面两个步骤后,我们可以正常运行和打包项目。接下来就来分析一下每个属性的配置。
入口(entry): entry可有多种配置方式
entry: path.resolve(__dirname, '../src/main.js'),
entry: ['./app/entry1', './app/entry2'],
entry: {a: "./app/entry-a", b: ["./app/entry-b1", "./app/entry-b2"]}
输出(output)
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js',
publicPath: '/'
}
模式(mode)
mode: 'production', // 生成
mode: 'development', // 开发
mode: 'none',
模块配置(module.rules): 可有多种配置方式
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.vue$/,
use: [
{ loader: 'vue-loader' }
]
}
]
}
插件(plugin):html-webpack-plugin、vue-loader
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
})
]
4. 插件(plugins)配置
4.1 清理构建文件夹:clean-webpack-plugin
每次打包构建之前先清理文件夹内容的文件(文本构建后的文件保留在dist
文件夹),保留最新构建的文件。
安装
npm install clean-webpack-plugin --save-dev
使用
build\prod.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
...,
plugins: [
new CleanWebpackPlugin()
]
}
配置完成后,运行npm run build
命令,会发现dist
中上一次打包的文件会被清理掉。
4.2 提取css:mini-css-extract-plugin
1. 首先我们要保证样式能在开发模式下能正常运行,我们需要先安装vue-style-loader
、css-loader
,如果配置成功,当我们在.vue
的style
标签中添加样式是会生效的。2. 完成这一步后,当打包的时候,就需要配置
mini-css-extract-plugin
.
安装
npm install css-loader --save-dev
npm install vue-style-loader --save-dev
npm install clean-webpack-plugin --save-dev
使用
build\dev.js
module.exports = {
...,
module: {
rules: [
...,
{
test: /\.css$/,
use: [
{ loader: 'vue-style-loader' },
{ loader: 'css-loader' }
]
}
]
},
}
build\prod.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
...,
module: {
rules: [
...,
{
test: /\.css$/,
use: [
'vue-style-loader',
MiniCssExtractPlugin.loader,
{ loader: 'css-loader' }
]
}
]
},
plugins: [
...,
new MiniCssExtractPlugin({
filename: 'static/css/[name]_[chunkhash:8].css',
chunkFilename: 'static/css/[id]_[chunkhash:8].css'
})
]
}
打包构建好以后,我们打开dist
目录,查看是否生成.css
后缀的文件,有说明已经成功了。
4.3 清理构建文件夹:copy-webpack-plugin
复制单个文件或者目录到构建目录。
安装
npm install copy-webpack-plugin --save-dev
使用
build\prod.js
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
...,
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, '../static'), // 需要拷贝的目录
to: 'static2', // 拷贝到那个目录下
globOptions: {
ignore: ['.*'] // 拷贝的文件类型
}
}
]
})
]
}
5. 优化(optimization)配置
5.1 splitChunks
这里会创建一个使用vendor
chunk文件,它包含整个node_modules
文件的代码。
build\prod.js
module.exports = {
...,
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
minSize: 0,
minChunks: 1,
chunks: 'all'
}
}
}
}
}
6. 其它
6.1 处理图片、媒体、字体等文件
通常是使用file-loader
来实现,一般会和url-loader
搭配使用。
安装
npm install file-loader url-loader --save-dev
使用
build\prod.js
、build\dev.js
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
...,
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,
resourceQuery: /\?.*/,
type: 'asset/inline',
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
type: 'asset/resource',
type: 'asset',
generator: {
filename: 'static/img/[name][ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
type: 'asset/resource',
type: 'asset',
generator: {
filename: 'static/fonts/[name][ext]'
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'static/media/[name].[ext]'
}
}
]
}
}
结语
我们在学习webpack
的时候一定要边看边跟着敲(时间够的话敲个三四遍),这样才能知道每个属性、属性值的意义,影响也会更深。虽然这样花费的时间比较多,但是效果还是很显著的。
前端的内容更新迭代太快,我们只有不断学习才能跟上节奏。
共勉~~~
本文的代码地址:gitee.com/xia_ming/st…