2022年了,再不会用webpack搭建项目多少说不过去了,基于最新的webpack5.65搭建,手摸手教你搭建vue项目,后续优化集成其他依赖会持续更新。
创建项目
- 指定目录打开命令行窗口,依次执行以下命令:
- mkdir webpack-vue
- cd webpack-vue
- npm init // 初始化 package.json
初始化webpack
- npm install webpack webpack-cli -D
- 修改package.json,添加启动命令
// package.json
{
...
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
}
复制代码
入口文件
-
根目录新建src文件夹(模仿vue)
-
src文件夹下新建main.js(入口文件)
-
根目录新建webpack.config.js (配置文件)
// 当前 webpack.config.js 配置
const path = require('path');
module.exports = {
entry: './src/main.js', // 入口
output: { // 输出
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
}
};
复制代码
-
npm run build (根目录dist文件下有main.js)
-
根目录新建index.html模板
-
npm install html-webpack-plugin -D (安装 html 插件,更改webpack.config.js配置)
// 当前 webpack.config.js 配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/main.js', // 入口
output: { // 输出
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
})
]
}
复制代码
- src目录下新建assets/css文件夹、css文件夹下新建index.css
html,body{
height: 100%;
width: 100%;
margin: 0;
padding: 0;
background: red;
}
复制代码
- npm install css-loader style-loader -D
- webpack.config.js新增loader配置
// ...
module: {
rules: [{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
}]
},
复制代码
- main.js 引入 index.css
import ('./assets/css/index.css')
- npm run build dist 目录下 index.html 用live server查看 背景图已经变成红色 说明loader生效
集成热更新
- npm install webpack-dev-server -D
- 修改webpack.config.js配置
// webpack.config.js 新增
devServer: {
static: path.join(__dirname, 'dist'), // 服务器资源的根目录
hot: true, //启用热加载
host: 'localhost',
port: 9000, //端口号
open: true, // 服务器启动后打开默认浏览器
},
复制代码
- 修改index.css文件 background:blue 看到页面背景变为蓝色 说明热更新生效
集成Vue3
- npm install vue@next // 安装最新版vue3
- npm i -D vue-loader@next @vue/compiler-sfc // 让webpack支持vue语法和单文件组件(sfc)
// 当前配置版本
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"dev": "webpack serve --mode development",
"build": "webpack --mode production"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@vue/compiler-sfc": "^3.2.26",
"css-loader": "^6.5.1",
"html-webpack-plugin": "^5.5.0",
"style-loader": "^3.3.1",
"vue-loader": "^17.0.0",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.3"
},
"dependencies": {
"vue": "^3.2.26"
}
复制代码
- src目录下新建App.vue
- 修改webpack.config.js配置
// 当前完整配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader'); // 引入VueLoaderPlugin
module.exports = {
// 入口
entry: './src/main.js',
// 出口
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},
// 配置vue-loader
{
test: /.vue$/,
use: ['vue-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html'
}),
new VueLoaderPlugin() // 新增 VueLoaderPlugin
],
devServer: {
static: path.join(__dirname, 'dist'), // 服务器资源的根目录,不写的话,默认为bundle.js
hot: true, //启用热加载
host: 'localhost',
port: 9000, //端口号
open: true, // 服务器启动后打开默认浏览器
},
}
复制代码
- 修改index.html文件
<body>
<div id="app"></div>
</body>
- 修改main.js配置
// 当前main.js配置
import ('./assets/css/index.css');
import {createApp} from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
复制代码
- npm run dev 可以看到vue文件已经正常编译
集成scss
- 以sass为例,安装sass
npm install node-sass sass-loader -D
容易失败,可以多尝试俩次
- 修改 webpack.config.js loader配置
// ...
{
test: /.(s[ac]ss|css)$/i, // 匹配sass 和 css
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
复制代码
- App.vue 文件修改style样式
<style lang="scss">
#app{
color: green;
}
</style>
复制代码
- npm run dev 样式生效表示sass集成成功
集成vue-router
- npm install vue-router@4 // 注意后面的@4很重要 这是在声明安装的版本
- src 目录下新建views文件夹,文件夹下新建A B C三个vue文件,内容随意
// A.vue
<template>
<div>
<h1> this is page A </h1>
<a @click="$router.push('B')">跳转页面B</a>
<br/>
<a @click="$router.push('C')">跳转页面C</a>
<!-- 子路由 -->
<router-view></router-view>
</div>
</template>
// ...
// B.vue / C.vue
<template>
<div>
this is page B / C
</div>
</template>
复制代码
- src 目录下新建route/index.js 文件
import { createRouter,createWebHistory } from "vue-router";
const router = createRouter ({
history:createWebHistory(), // history 模式
routes: [
{
path: '/',
redirect: { name: 'A' },
},
{
name: 'A',
path: '/A',
component: () => import('../views/A.vue'),
children: [
{
name: 'C',
path: '/C',
component: () => import('../views/C.vue')
}
]
},
{
name: 'B',
path: '/B',
component: () => import('../views/B.vue')
}
]
})
export default router;
复制代码
- main.js 引入路由
import ('./assets/css/index.css');
import {createApp} from 'vue'
import App from './App.vue'
import router from './route'
createApp(App).use(router).mount('#app')
复制代码
- App.vue 添加 组件
- npm run dev 启动项目可以看到路由可以正常使用、A页面嵌套路由也正常使用
- 刷新路由404的问题,修改webpack配置
// webpack.config.js
// ...
devServer: {
static: path.join(__dirname, 'dist'), // 服务器资源的根目录,不写的话,默认为bundle.js
hot: true, //启用热加载
host: 'localhost',
port: 9000, //端口号
open: true, // 服务器启动后打开默认浏览器
historyApiFallback: true, // 解决history模式刷新404
},
复制代码
集成vuex
- npm install -save vuex@4.*
- src 目录下新建store/index.js
- main.js 引入 store
// 当前配置
import ('./assets/css/index.css');
import {createApp} from 'vue'
import App from './App.vue'
import router from './route'
import store from './store'
createApp(App)
.use(router)
.use(store)
.mount('#app')
复制代码
- 编辑 store/index.js
// 搞一个官网示例
import { createStore } from 'vuex'
export default createStore({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
},
modules: {
}
})
复制代码
- 编辑 A.vue
<template>
<div>
<h1>this is page A {{count}}</h1>
<a @click="$router.push('B')">跳转页面B</a>
<br />
<a @click="$router.push('C')">跳转页面C</a>
<br />
<button @click="$store.commit('increment')">增加</button>
<!-- 子路由 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count
}
},
}
</script>
// 验证vuex数据相同
// C.vue
<template>
<div>
this is page C {{count}}
</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count
}
},
}
</script>
复制代码
- run dev 看到store数据共享生效
集成babel
- npm i -D babel-loader @babel/core @babel/cli @babel/preset-env // 插件预设
- npm install --save core-js@3
core-js是什么?
core-js 它是JavaScript标准库的 polyfill(垫片/补丁), 新功能的es'api'转换为大部分现代浏览器都可以支持 运行的一个'api' 补丁包集合
相比之下
polyfill 污染全局环境、支持实例方法
runtime 不污染全局环境、不支持实例方法
- 根目录新建 .babelrc
{
"presets": [
["@babel/preset-env", {
"useBuiltIns": "usage",
"corejs": 3
}]
]
}
复制代码
- webpack.config.js 修改
module: {
rules: [
// ...
{
test: /.js$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
},
复制代码
- main.js 新增一些es6+语法
// ...
console.log(
[1, 2, 3].map(n => n ** 2)
);
()=>{console.log(123)}
复制代码
- npm run dev 可以看到es6+代码被编译
// 经编译后
console.log([1, 2, 3].map(function (n) {
return Math.pow(n, 2);
}));
(function () {
console.log(123);
});
复制代码
- 到此package.json版本信息如下
{
"name": "webpack-vue",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"dev": "webpack serve --mode development",
"build": "webpack --mode production"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.16.8",
"@babel/core": "^7.16.7",
"@babel/preset-env": "^7.16.8",
"@vue/compiler-sfc": "^3.2.26",
"babel-loader": "^8.2.3",
"css-loader": "^6.5.1",
"html-webpack-plugin": "^5.5.0",
"node-sass": "^7.0.1",
"sass-loader": "^12.4.0",
"style-loader": "^3.3.1",
"vue-loader": "^17.0.0",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.3"
},
"dependencies": {
"core-js": "^3.20.2",
"vue": "^3.2.26",
"vue-router": "^4.0.12",
"vuex": "^4.0.2"
}
}
复制代码
分离css
此时执行npm run build 命令我们会发现css都被打包到一个个chunk包里面去了,在生产环境下我们需要将css分离出来。
- npm install -D mini-css-extract-plugin
webpack4以上版本不在使用“extract-text-webpack-plugin”,而改为“mini-css-extract-plugin”
- 编辑 webpack.config.js
// ...
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// loader
// ...
{
test: /.(s[ac]ss|css)$/i,
use: [
// 'style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
]
},
// plugins
// ...
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "css/[name].css"
})
复制代码
- npm run dev 可以看到页面css的引用已经从style标签变成css文件
至此为止 process.env.NODE_ENV 这个变量是undefined 我们需要修改package.json的指令,在执行环境中加入 NODE_ENV 变量 , 安装 cross-env 这是一个跨平台设置和使用环境变量的脚本,用来区分node环境变量(开发或者生产环境)
- npm install cross-env -D
- 修改package.json scripts 命令
// ...
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"dev": "cross-env NODE_ENV=development webpack serve",
"build": "cross-env NODE_ENV=production webpack "
},
复制代码
- npm run build 看到 css文件已经抽离出来 表示成功
开发环境和生产环境的区别
生产环境可能需要分离 CSS 成单独的文件,以便多个页面共享同一个 CSS 文件;
生产环境需要压缩 HTML/CSS/JS 代码;
生产环境需要压缩图片;
开发环境需要生成 SourceMap 文件;
开发环境需要打印 debug 信息;
开发环境需要 HMR、devServer 等功能…
按环境划分 Webpack 配置文件
webpack.config.js :所有环境的默认入口配置文件;
webpack.base.js :基础配置;
webpack.development.js :开发环境使用的配置;
webpack.production.js :生产环境使用的配置。
webpack配置拆分
根据上述环境区别的描述,我们来拆分一下现有 webpack.config.js 文件
- 根目录新建build文件夹
- build文件夹下新建webpack.base.js、webpack.dev.js、webpack.prod.js
- 根据上述环境区别的描述来拆分文件
- npm i webpack-merge -D // 用来合并配置文件 感觉和object.assign 功能差不多
// webpack.base.js
const { VueLoaderPlugin } = require('vue-loader');
const devConfig = require('./webpack.dev');
const prodConfig = require('./webpack.prod');
const {merge} = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const isProduct = process.env.NODE_ENV === 'production';
const baseConfig = {
// 入口
entry: '/src/main.js',
module: {
rules: [
{
test: /.(s[ac]ss|css)$/i,
use: [
isProduct ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /.vue$/,
use: ['vue-loader']
},
{
test: /.js$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: 'index.html'
}),
],
}
module.exports = isProduct ? merge(baseConfig, prodConfig) : merge(baseConfig, devConfig);
复制代码
// webpack.dev.js
const path = require('path');
module.exports = {
devServer: {
static: path.join(__dirname, 'dist'), // 服务器资源的根目录,不写的话,默认为bundle.js
hot: true, //启用热加载
host: 'localhost',
port: 9000, //端口号
open: true, // 服务器启动后打开默认浏览器
historyApiFallback: true, // 解决history模式刷新404
},
}
复制代码
// webpack.prod.js
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// 出口
output: {
filename: 'js/[name]-[chunkhash].js',
path: path.resolve(__dirname, '../dist')
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "css/[name].css"
})
]
}
复制代码
- 修改package.json命令
"dev": "cross-env NODE_ENV=development webpack serve --config build/webpack.base.js",
"build": "cross-env NODE_ENV=production webpack --config build/webpack.base.js"
复制代码
- 执行 npm run dev / npm run build 成功 拆分成功
清理打包文件
每次build 默认不会清除之前build的文件 每次都要手动清理
- npm install --save-dev clean-webpack-plugin
- webpack.prod.js 编辑
// ...
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// plugins
plugins: [
// ...
new CleanWebpackPlugin()
]
复制代码
处理图片
注意!!!:啊啊啊啊啊啊啊啊,抓狂呀,webpack5 已经废弃 url-loader / file-loader ,通过内置的 asset 模块的处理资源文件 ,webpack5 已经支持资源模块,通过 type 参数进行配置,可选的参数有:1、asset/resource2、asset/inline 3、asset/source 4、asset 。
- assets目录下新建image/cat.jpg文件
- A.vue文件下
// ...
<img src="../assets/image/cat.jpg" alt="">
<style lang="scss" scoped>
.pageA{
background: url("../assets/image/cat.jpg") no-repeat;
h1{
background: url('~@/assets/image/cat.jpg') no-repeat;
}
img{
width: 200px;
}
}
</style>
复制代码
- webpack.base.js
// loader
[
// ...
{
test:/.(jpg|png|gif)$/,
type:"asset",
//解析
parser: {
//转base64的条件
dataUrlCondition: {
maxSize: 10 * 1024, // 小于 10kb 文件转为base64地址 减少请求
}
},
generator:{
//与output.assetModuleFilename是相同的,这个写法引入的时候也会添加好这个路径
filename:'img/[name]-[hash:6].[ext]',
//打包后对资源的引入,文件命名已经有/img了
// publicPath:'./'
},
}
]
复制代码
- 图片加载成功
浏览器兼容css
- npm i postcss-loader postcss-preset-env -D
postcss是一个平台 我们可以使用一些基于这个平台的插件 例如 autofix
- webpack.base.js 编辑
// ...
{
test: /.(s[ac]ss|css)$/i,
use: [
isProduct ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
'postcss-loader',
'sass-loader',
]
},
复制代码
- 根目录新建 postcss.config.js
module.exports = {
plugins: [
[
// postcss-preset-env插件读取package.json文件中的browserslist配置
// 或者根目录新建一个 .browserslistrc 文件
require('postcss-preset-env')(),
],
],
};
复制代码
- package.json 编辑
"browserslist": [
"> 0.05%",
"last 2 versions",
"not ie <= 8",
"Android > 4.0"
]
复制代码
- A.vue 编辑
<style lang="scss" scoped>
.pageA{
background: url("../assets/image/cat.jpg") no-repeat;
h1{
// background: url('~@/assets/image/cat.jpg') no-repeat;
background-color: red;
display: flex;
color: rgba(255, 165, 0, 0.5);
justify-content: space-between;
box-sizing : border-box;
box-shadow: none;
}
img{
width: 200px;
}
}
</style>
复制代码
- npm run dev 运行元素样式有浏览器前缀 表示成功
// 浏览器中有删除线
background-color: red;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
color: rgba(255, 165, 0, 0.5);
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-box-shadow: none;
box-shadow: none;
复制代码
配置sourceMap
sourceMap是源代码和编译后的代码之间映射关系的一个对象文件,我们开发环境和生产环境运行的代码其实都是编译后的代码,编译后的代码信息和源码是不一样的,在开发环境中我们需要定位到错误的源代码位置,而在生产环境中我们需要隐藏这个映射文件。
- 编辑 webpack.base.js
// ...
const baseConfig = {
// 入口
entry: '/src/main.js',
// 生产环境下隐藏映射关系或false 开发环境下开启
devtool: isProduct ? false : 'source-map',
// ......
}
复制代码
- 编辑 A.vue 打印一个未定义变量
- npm run dev 看到报错映射到源文件
- sourceMap 有多个可配置项 根据自己的情况去设定
false | eval | [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
日志美化
当前配置下我们在run的时候会有很多输出内容,非常不美观
- npm i friendly-errors-webpack-plugin -D // 更多配置
- 编辑webpack.base.js配置 配合stats 实现输出日志优化
const baseConfig = {
// 入口
entry: '/src/main.js',
devtool: isProduct ? 'hidden-source-map' : 'source-map',
stats: "errors-only", // 配合stats 只在错误的时候输出
// ...
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: 'index.html'
}),
new FriendlyErrorsWebpackPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://localhost:9000`]
}
}),
],
}
复制代码
- npm run dev 控制台输出Your application is running here: http://localhost:9000 且向上滚动控制台看到输出日志很简洁 表示成功
打包进度条
基于当前配置,我们在打包的时候没有进度显示,不知道打包进行到哪个阶段多着急
- npm i -D progress-bar-webpack-plugin
- 编辑webpack.base.js
// ...
const chalk = require("chalk");
const ProgressBarPlugin = require("progress-bar-webpack-plugin");
// ...
plugins: {
// 进度条
new ProgressBarPlugin({
format: ` :msg [:bar] ${chalk.green.bold(":percent")} (:elapsed s)`,
}),
}
复制代码
别名配置
配置别名可以加快 webpack 查找模块的速度
// webpack.base.js
// ...
resolve: {
alias: {
'@': path.resolve(__dirname,'../src') // 因为此时我们在build目录下 所以src相对于当前文件的外层
}
},
复制代码
文件查找范围
指定 extensions 之后可以不用再 require 或是 import 的时候加文件拓展名
查找的时候会依次尝试添加拓展名进行匹配
// webpack.base.js
// ...
resolve: {
extensions: ['.js', '.jsx','.json'], // 引入文件时,默认js,json不用写扩展名,但是当引入例如jsx文件时默认是不可以不写后缀名的,如果不想写后缀名在这里进行配置
alias: {
'@': path.resolve(__dirname,'../src') // 因为此时我们在build目录下 所以src相对于当前文件的外层
}
},
复制代码
babel-loader缓存
在webpack中使用babel-loader是去为了兼容我们的js代码,将更高级的语法转译成浏览器所能识别语法。loader需要经过编译、转换、生成这三个步骤,所以这一过程很慢,当我们设置cacheDirectory选项后,之后的 webpack 构建,将会尝试读取缓存(node_modules/.cache/babel-loader),来避免在每次执行时,可能产生的、高性能消耗的 Babel 重新编译过程(recompilation process),从而提高构建速度。
- 编辑 webpack.base.js
// ...
{
test: /.js$/,
use :['babel-loader?cacheDirectory=true'], // 开启babel缓存,第二次构建时,会读取之前的缓存
exclude: /node_modules/
},
复制代码
- npm run build 打包成功后查看node_modules 可以看到生成了.cache文件夹
- 此后每次构建的时间相对第一个构建时间会少一点
文件缓存(持久缓存)
通过 cache: filesystem 可以将构建过程的 webpack 模板进行缓存,大幅提升二次构建速度、打包速度,当构建突然中断,二次进行构建时,可以直接从缓存中拉取,可提速 90% 左右。
// webpack.base.js
// ...
cache: {
type: "filesystem", // 使用文件缓存
},
复制代码
多线程
把这个 loader 放置在其他 loader 之前, 放置在这个 loader 之后的 loader 就会在一个单独的 worker 池(worker pool)中运行
- npm install --save-dev thread-loader
- 编辑 webpack.base.js
{
test: /.js$/,
use: [
{
loader: "thread-loader",
// 有同样配置的 loader 会共享一个 worker 池(worker pool)
options: {
// 产生的 worker 的数量,默认是 cpu 的核心数
workers: 2,
// 一个 worker 进程中并行执行工作的数量
// 默认为 20
workerParallelJobs: 50,
// 额外的 node.js 参数
workerNodeArgs: ['--max-old-space-size', '1024'],
// 闲置时定时删除 worker 进程
// 默认为 500ms
// 可以设置为无穷大, 这样在监视模式(--watch)下可以保持 worker 持续存在
poolTimeout: 2000,
// 池(pool)分配给 worker 的工作数量
// 默认为 200
// 降低这个数值会降低总体的效率,但是会提升工作分布更均一
poolParallelJobs: 50,
// 池(pool)的名称
// 可以修改名称来创建其余选项都一样的池(pool)
name: "my-pool"
}
},
'babel-loader',
],
exclude: /node_modules/
},
复制代码
- 每个 worker 都是一个单独的有 600ms 限制的 node.js 进程。同时跨进程的数据交换也会被限制。
- 请仅在耗时的 loader 上使用
happypack 同样是用来设置多线程,但是在 webpack5 就不要再使用 happypack了,官方也已经不再维护了,推荐使用 thread-loader。
结语
本文是自己将最近搭建的项目一步一步记录下来的,因为是空的项目,所以优化上做的不多,对webpack有兴趣,但没搭建过webpack项目的盆友可以尝试从零搭建一个webpack项目,相信这个过程会让你有不错的收获。
// 当前依赖信息 package.json
{
"name": "webpack-vue",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "cross-env NODE_ENV=development webpack serve",
"build": "cross-env NODE_ENV=production webpack ",
"start": "cross-env NODE_ENV=development webpack serve --config build/webpack.base.js",
"done": "cross-env NODE_ENV=production webpack --config build/webpack.base.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.16.8",
"@babel/core": "^7.16.7",
"@babel/preset-env": "^7.16.8",
"@vue/compiler-sfc": "^3.2.26",
"babel-loader": "^8.2.3",
"clean-webpack-plugin": "^4.0.0",
"cross-env": "^7.0.3",
"css-loader": "^6.5.1",
"friendly-errors-webpack-plugin": "^1.7.0",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.4.6",
"node-sass": "^7.0.1",
"postcss-loader": "^6.2.1",
"postcss-preset-env": "^7.2.3",
"progress-bar-webpack-plugin": "^2.1.0",
"sass-loader": "^12.4.0",
"style-loader": "^3.3.1",
"thread-loader": "^3.0.4",
"vue-loader": "^17.0.0",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.3",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"core-js": "^3.20.2",
"vue": "^3.2.26",
"vue-router": "^4.0.12",
"vuex": "^4.0.2"
},
"browserslist": [
"> 0.05%",
"last 2 versions",
"not ie <= 8",
"Android > 4.0"
]
}
复制代码