一、vue-cli开发
1. 项目整体目录
2. package.json
{
"name": "vue-cli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "npm run dev",
"dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.config.js",
"build": "cross-env NODE_ENV=production webpack --config ./config/webpack.config.js"
},
"keywords": [],
"author": "cx",
"license": "ISC",
"browserslist": [
"last 2 version",
"> 1%",
"not dead"
],
"devDependencies": {
"@babel/core": "^7.17.10",
"@babel/eslint-parser": "^7.17.0",
"@vue/cli-plugin-babel": "^5.0.4",
"babel-loader": "^8.2.5",
"copy-webpack-plugin": "^10.2.4",
"cross-env": "^7.0.3",
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^3.4.1",
"eslint-plugin-vue": "^8.7.1",
"eslint-webpack-plugin": "^3.1.1",
"html-webpack-plugin": "^5.5.0",
"image-minimizer-webpack-plugin": "^3.2.3",
"imagemin": "^8.0.1",
"imagemin-gifsicle": "^7.0.0",
"imagemin-jpegtran": "^7.0.0",
"imagemin-optipng": "^8.0.0",
"imagemin-svgo": "^10.0.1",
"less-loader": "^10.2.0",
"mini-css-extract-plugin": "^2.6.0",
"postcss-loader": "^6.2.1",
"postcss-preset-env": "^7.5.0",
"sass": "^1.51.0",
"sass-loader": "^12.6.0",
"stylus-loader": "^6.2.0",
"unplugin-auto-import": "^0.7.1",
"unplugin-vue-components": "^0.19.3",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.6.14",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.9.0"
},
"dependencies": {
"element-plus": "^2.2.0",
"vue": "^3.2.33",
"vue-router": "^4.0.15"
}
}
3. eslintrc.js
这里需要继承vue3的eslint校验规则
module.exports = {
root: true,
env: {
node: true,
},
extends: ["plugin:vue/vue3-essential", "eslint:recommended"], // 继承
parserOptions: {
parser: "@babel/eslint-parser", // 解析器
},
};
4. babel.config.js
这里直接使用@vue/cli-plugin-babel/preset
预设,这里面已经为我们做好了各种兼容性处理和优化,不用我们在像以前一样还要自己配置core-js
,@babel/plugin-transform-runtime
等优化性的配置了。
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"], // 预设
};
5. webpack.config.js
const path = require("path");
const EslintWebpackPlugin = require("eslint-webpack-plugin"); // eslint检查代码
const HtmlWebpackPlugin = require("html-webpack-plugin"); // 生成html文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 提取css文件
const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin"); // 压缩css文件
const TerserWebpackPlugin = require("terser-webpack-plugin"); // 压缩js文件
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); // 压缩图片
const CopyPlugin = require("copy-webpack-plugin"); // 拷贝文件
const { VueLoaderPlugin } = require("vue-loader"); // vue-loader插件
const { DefinePlugin } = require("webpack"); // 定义环境变量
const AutoImport = require("unplugin-auto-import/webpack"); // 按需加载element-plus
const Components = require("unplugin-vue-components/webpack"); // 按需加载element-plus
const { ElementPlusResolver } = require("unplugin-vue-components/resolvers"); // 按需加载element-plus
const isProduction = process.env.NODE_ENV === "production"; // 判断是否是生产环境
// 返回处理样式loader函数
const getStyleLoaders = (pre) => {
return [
isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader",
"css-loader",
{
// 处理css兼容性问题
// 配合package.json中browserslist来指定兼容性
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: ["postcss-preset-env"],
},
},
},
pre && {
loader: pre,
options:
pre === "sass-loader"
? {
additionalData: `@use "@/styles/element/index.scss" as *;`, // 自定义element-plus主题
}
: {},
},
].filter(Boolean);
};
module.exports = {
entry: "./src/main.js", // 入口文件
output: { // 输出文件
path: isProduction ? path.resolve(__dirname, "../dist") : undefined, // 生产环境输出路径
filename: isProduction ? "static/js/[name].[contenthash:10].js" : "static/js/[name].js", // 生产环境文件名
chunkFilename: isProduction ? "static/js/[name].[contenthash:10].chunk.js" : "static/js/[name].chunk.js", // 生产环境代码分割文件名
assetModuleFilename: "static/media/[hash:10][ext][query]", // 生产环境资源文件名
clean: true, // 清除上一次打包文件
},
module: { // 处理模块规则
rules: [
// 处理css
{
test: /\.css$/,
use: getStyleLoaders(),
},
{
test: /\.less$/,
use: getStyleLoaders("less-loader"),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoaders("sass-loader"),
},
{
test: /\.styl$/,
use: getStyleLoaders("stylus-loader"),
},
// 处理图片
{
test: /\.(jpe?g|png|gif|webp|svg)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024,
},
},
},
// 处理其他资源
{
test: /\.(woff2?|ttf)$/,
type: "asset/resource",
},
// 处理js
{
test: /\.js$/,
include: path.resolve(__dirname, "../src"),
loader: "babel-loader",
options: {
cacheDirectory: true,
cacheCompression: false,
},
},
{
test: /\.vue$/, // 处理vue
loader: "vue-loader",
options: {
// 开启缓存
cacheDirectory: path.resolve(__dirname, "../node_modules/.cache/vue-loader"),
},
},
],
},
// 处理html
plugins: [
new EslintWebpackPlugin({ // eslint检查代码
context: path.resolve(__dirname, "../src"), // 指定eslint检查的目录
exclude: "node_modules", // 排除node_modules文件夹
cache: true, // 开启缓存
cacheLocation: path.resolve(__dirname, "../node_modules/.cache/.eslintcache"), // eslint缓存cache文件夹
}),
new HtmlWebpackPlugin({ // 生成html文件
template: path.resolve(__dirname, "../public/index.html"), // 指定html模板
}),
isProduction &&
new MiniCssExtractPlugin({ // 提取css文件
filename: "static/css/[name].[contenthash:10].css", // 生产环境文件名
chunkFilename: "static/css/[name].[contenthash:10].chunk.css", // 生产环境代码分割文件名
}),
isProduction &&
new CopyPlugin({ // 拷贝文件
patterns: [ // 拷贝文件列表
{
from: path.resolve(__dirname, "../public"), // 拷贝文件源
to: path.resolve(__dirname, "../dist"), // 拷贝文件目标
globOptions: {
// 忽略index.html文件
ignore: ["**/index.html"],
},
},
],
}),
new VueLoaderPlugin(), // vue-loader插件
// cross-env定义的环境变量给打包工具使用
// DefinePlugin定义环境变量给源代码使用,从而解决vue3页面警告的问题
new DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false,
}),
// 按需加载element-plus
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [
ElementPlusResolver({
// 自定义主题,引入sass
importStyle: "sass",
}),
],
}),
].filter(Boolean),
mode: isProduction ? "production" : "development",
devtool: isProduction ? "source-map" : "cheap-module-source-map", // 生产环境生成source-map
optimization: { // 优化
splitChunks: { // 代码分割
chunks: "all", // 分割所有代码
cacheGroups: { // 缓存组
vue: { // 分割vue
test: /[\\/]node_modules[\\/]vue(.*)?[\\/]/,
name: "vue-chunk",
priority: 40,
},
elementPlus: { // 分割element-plus
test: /[\\/]node_modules[\\/]element-plus[\\/]/,
name: "elementPlus-chunk",
priority: 30,
},
libs: { // 分割第三方库
test: /[\\/]node_modules[\\/]/,
name: "libs-chunk",
priority: 20,
},
},
},
runtimeChunk: {
name: (entrypoint) => `runtime~${entrypoint.name}.js`, // 生成runtime文件
},
minimize: isProduction, // 生产环境压缩代码
minimizer: [
new CssMinimizerWebpackPlugin(), // 压缩css文件
new TerserWebpackPlugin(), // 压缩js文件
new ImageMinimizerPlugin({ // 压缩图片
minimizer: { // 压缩器
implementation: ImageMinimizerPlugin.imageminGenerate, // 使用imagemin
options: {
plugins: [
["gifsicle", { interlaced: true }],
["jpegtran", { progressive: true }],
["optipng", { optimizationLevel: 5 }],
[
"svgo",
{
plugins: [
"preset-default",
"prefixIds",
{
name: "sortAttrs",
params: {
xmlnsOrder: "alphabetical",
},
},
],
},
],
],
},
},
}),
],
},
// webpack解析模块加载选项
resolve: {
// 自动补全文件扩展名
extensions: [".vue", ".js", ".json"],
// 路径别名
alias: {
"@": path.resolve(__dirname, "../src"),
},
},
devServer: {
host: "localhost",
port: 3000,
open: true,
hot: true, // 开启HMR
historyApiFallback: true, // 解决前端路由刷新404问题
},
performance: false, // 关闭性能提示
};
二、解读webpack.config.js关于vue的配置部分
1. module 部分:
- 处理 Vue 单文件组件的 loader:
{
test: /\.vue$/, // 处理vue
loader: "vue-loader",
options: {
// 开启缓存
cacheDirectory: path.resolve(__dirname, "../node_modules/.cache/vue-loader")
}
}
这里使用 vue-loader 处理 .vue 文件,开启缓存加快构建速度。
2. plugins 部分:
- VueLoaderPlugin:
new VueLoaderPlugin()
在 webpack.config.js 文件中使用了 VueLoaderPlugin,这是用于 Vue-loader 的插件,它会在开发环境下编译 Vue 单文件组件。
- DefinePlugin:
new DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false
})
Vue 3 项目会出现页面警告,可以使用 DefinePlugin 插件定义全局变量来解决,这里定义了 VUE_OPTIONS_API 和 VUE_PROD_DEVTOOLS。
- 按需加载element-plus
// 按需加载element-plus
AutoImport({
resolvers: [ElementPlusResolver()],
}),
3. optimization 部分:
这部分主要是配置优化选项,其中包括代码分割、压缩等配置。
- 代码分割:
splitChunks: {
chunks: "all",
cacheGroups: {
vue: {
test: /[\\/]node_modules[\\/]vue(.*)?[\\/]/,
name: "vue-chunk",
priority: 40
},
elementPlus: {
test: /[\\/]node_modules[\\/]element-plus[\\/]/,
name: "elementPlus-chunk",
priority: 30
},
libs: {
test: /[\\/]node_modules[\\/]/,
name: "libs-chunk",
priority: 20
}
}
}
在 webpack.config.js 文件中使用了 SplitChunksPlugin 插件对代码进行了分割,其中包括了对 Vue、Element-UI 等第三方库的分割,可以提高页面加载速度。
- 生产环境压缩:
minimize: isProduction,
minimizer: [
new CssMinimizerWebpackPlugin(),
new TerserWebpackPlugin(),
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: [
["gifsicle", { interlaced: true }],
["jpegtran", { progressive: true }],
["optipng", { optimizationLevel: 5 }],
[
"svgo",
{
plugins: [
"preset-default",
"prefixIds",
{
name: "sortAttrs",
params: {
xmlnsOrder: "alphabetical"
}
}
]
}
]
]
}
}
})
]
在生产环境中使用了优化插件,包括压缩 CSS、JS 和图片等资源文件。
4. resolve部分
// webpack解析模块加载选项
resolve: {
// 自动补全文件扩展名
extensions: [".vue", ".js", ".json"],
// 路径别名
alias: {
"@": path.resolve(__dirname, "../src"),
},
},