webpack開(kāi)發(fā)vue-cli的項(xiàng)目實(shí)踐
一、vue-cli開(kāi)發(fā)
1. 項(xiàng)目整體目錄

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校驗(yàn)規(guī)則
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預(yù)設(shè),這里面已經(jīng)為我們做好了各種兼容性處理和優(yōu)化,不用我們?cè)谙褚郧耙粯舆€要自己配置core-js,@babel/plugin-transform-runtime等優(yōu)化性的配置了。
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"], // 預(yù)設(shè)
};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"); // 定義環(huán)境變量
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"; // 判斷是否是生產(chǎn)環(huán)境
// 返回處理樣式loader函數(shù)
const getStyleLoaders = (pre) => {
return [
isProduction ? MiniCssExtractPlugin.loader : "vue-style-loader",
"css-loader",
{
// 處理css兼容性問(wèn)題
// 配合package.json中browserslist來(lái)指定兼容性
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, // 生產(chǎn)環(huán)境輸出路徑
filename: isProduction ? "static/js/[name].[contenthash:10].js" : "static/js/[name].js", // 生產(chǎn)環(huán)境文件名
chunkFilename: isProduction ? "static/js/[name].[contenthash:10].chunk.js" : "static/js/[name].chunk.js", // 生產(chǎn)環(huán)境代碼分割文件名
assetModuleFilename: "static/media/[hash:10][ext][query]", // 生產(chǎn)環(huán)境資源文件名
clean: true, // 清除上一次打包文件
},
module: { // 處理模塊規(guī)則
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: {
// 開(kāi)啟緩存
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, // 開(kāi)啟緩存
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", // 生產(chǎn)環(huán)境文件名
chunkFilename: "static/css/[name].[contenthash:10].chunk.css", // 生產(chǎn)環(huán)境代碼分割文件名
}),
isProduction &&
new CopyPlugin({ // 拷貝文件
patterns: [ // 拷貝文件列表
{
from: path.resolve(__dirname, "../public"), // 拷貝文件源
to: path.resolve(__dirname, "../dist"), // 拷貝文件目標(biāo)
globOptions: {
// 忽略index.html文件
ignore: ["**/index.html"],
},
},
],
}),
new VueLoaderPlugin(), // vue-loader插件
// cross-env定義的環(huán)境變量給打包工具使用
// DefinePlugin定義環(huán)境變量給源代碼使用,從而解決vue3頁(yè)面警告的問(wèn)題
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", // 生產(chǎn)環(huán)境生成source-map
optimization: { // 優(yōu)化
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: { // 分割第三方庫(kù)
test: /[\\/]node_modules[\\/]/,
name: "libs-chunk",
priority: 20,
},
},
},
runtimeChunk: {
name: (entrypoint) => `runtime~${entrypoint.name}.js`, // 生成runtime文件
},
minimize: isProduction, // 生產(chǎn)環(huán)境壓縮代碼
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解析模塊加載選項(xiàng)
resolve: {
// 自動(dòng)補(bǔ)全文件擴(kuò)展名
extensions: [".vue", ".js", ".json"],
// 路徑別名
alias: {
"@": path.resolve(__dirname, "../src"),
},
},
devServer: {
host: "localhost",
port: 3000,
open: true,
hot: true, // 開(kāi)啟HMR
historyApiFallback: true, // 解決前端路由刷新404問(wèn)題
},
performance: false, // 關(guān)閉性能提示
};二、解讀webpack.config.js關(guān)于vue的配置部分
1. module 部分
處理 Vue 單文件組件的 loader:
{
test: /\.vue$/, // 處理vue
loader: "vue-loader",
options: {
// 開(kāi)啟緩存
cacheDirectory: path.resolve(__dirname, "../node_modules/.cache/vue-loader")
}
}這里使用 vue-loader 處理 .vue 文件,開(kāi)啟緩存加快構(gòu)建速度。
2. plugins 部分
VueLoaderPlugin:
new VueLoaderPlugin()
在 webpack.config.js 文件中使用了 VueLoaderPlugin,這是用于 Vue-loader 的插件,它會(huì)在開(kāi)發(fā)環(huán)境下編譯 Vue 單文件組件。
DefinePlugin:
new DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false
})Vue 3 項(xiàng)目會(huì)出現(xiàn)頁(yè)面警告,可以使用 DefinePlugin 插件定義全局變量來(lái)解決,這里定義了 VUE_OPTIONS_API 和 VUE_PROD_DEVTOOLS。
按需加載element-plus
// 按需加載element-plus
AutoImport({
resolvers: [ElementPlusResolver()],
}),3. optimization 部分
這部分主要是配置優(yōu)化選項(xiàng),其中包括代碼分割、壓縮等配置。
代碼分割:
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 插件對(duì)代碼進(jìn)行了分割,其中包括了對(duì) Vue、Element-UI 等第三方庫(kù)的分割,可以提高頁(yè)面加載速度。
生產(chǎn)環(huán)境壓縮:
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"
}
}
]
}
]
]
}
}
})
]在生產(chǎn)環(huán)境中使用了優(yōu)化插件,包括壓縮 CSS、JS 和圖片等資源文件。
4. resolve部分
// webpack解析模塊加載選項(xiàng)
resolve: {
// 自動(dòng)補(bǔ)全文件擴(kuò)展名
extensions: [".vue", ".js", ".json"],
// 路徑別名
alias: {
"@": path.resolve(__dirname, "../src"),
},
},到此這篇關(guān)于webpack開(kāi)發(fā)vue-cli的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)webpack開(kāi)發(fā)vue-cli內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- windows下vue-cli及webpack搭建安裝環(huán)境
- vue-cli的webpack模板項(xiàng)目配置文件分析
- 解決vue-cli + webpack 新建項(xiàng)目出錯(cuò)的問(wèn)題
- vue-cli webpack模板項(xiàng)目搭建及打包時(shí)路徑問(wèn)題的解決方法
- webpack+vue-cli項(xiàng)目中引入外部非模塊格式j(luò)s的方法
- webpack4+Vue搭建自己的Vue-cli項(xiàng)目過(guò)程分享
- vue-cli5.0?webpack?采用?copy-webpack-plugin?打包復(fù)制文件的方法
- vue-cli與webpack處理靜態(tài)資源的方法及webpack打包的坑
相關(guān)文章
vue項(xiàng)目實(shí)現(xiàn)設(shè)置根據(jù)路由高亮對(duì)應(yīng)的菜單項(xiàng)操作
這篇文章主要介紹了vue項(xiàng)目實(shí)現(xiàn)設(shè)置根據(jù)路由高亮對(duì)應(yīng)的菜單項(xiàng)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Elementui?el-input輸入框校驗(yàn)及表單校驗(yàn)實(shí)例代碼
輸入框是使用非常多的元素,用來(lái)輸入用戶名、密碼等等信息,Element提供了功能和樣式豐富的輸入框,下面這篇文章主要給大家介紹了關(guān)于Elementui?el-input輸入框校驗(yàn)及表單校驗(yàn)的相關(guān)資料,需要的朋友可以參考下2023-06-06
Vue3 響應(yīng)式數(shù)據(jù) reactive使用方法
這篇文章主要介紹了Vue3 響應(yīng)式數(shù)據(jù) reactive使用方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-11-11
vue2中組件互相調(diào)用實(shí)例methods中的方法實(shí)現(xiàn)詳解
vue在同一個(gè)組件內(nèi),方法之間經(jīng)常需要互相調(diào)用,下面這篇文章主要給大家介紹了關(guān)于vue2中組件互相調(diào)用實(shí)例methods中的方法實(shí)現(xiàn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08
Vue.js中輕松解決v-for執(zhí)行出錯(cuò)的三個(gè)方案
v-for標(biāo)簽可以用來(lái)遍歷數(shù)組,將數(shù)組的每一個(gè)值綁定到相應(yīng)的視圖元素中去,下面這篇文章主要給大家介紹了關(guān)于在Vue.js中輕松解決v-for執(zhí)行出錯(cuò)的三個(gè)方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-06-06
Vue export import 導(dǎo)入導(dǎo)出的多種方式與區(qū)別介紹
這篇文章主要介紹了Vue export import 導(dǎo)入導(dǎo)出的多種方式與區(qū)別介紹,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
Vue組件傳值過(guò)程接收不成功的問(wèn)題及解決
這篇文章主要介紹了Vue組件傳值過(guò)程接收不成功的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06

