一篇教你学会如何用Webpack从零搭建一个Vue脚手架
前言
前面已经学习了一些webpack的基本配置,并从0搭建了一个React脚手架,接下来用学过的一些配置来搭建一个Vue脚手架!
开发模式下webpack配置
/*
* @Author: fdhou
* @Date: 2022-12-06 14:50:19
* @LastEditors: fdhou
* @LastEditTime: 2022-12-09 14:16:02
* @Description: 开发环境webpack配置
*/
const path = require('path')
const { DefinePlugin } = require('webpack')
const ESLintWebpackPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require('vue-loader')
// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
return [
"vue-style-loader", // 需要处理css功能和HMR功能
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor,
].filter(Boolean);
};
module.exports = {
entry: './src/main.js',
output: {
path: undefined, //开发环境不需要指定输出目录
filename: 'static/js/[name].js', // 输出的文件名
chunkFilename: 'static/js/[name].chunk.js', // 动态导入的文件打包输出的文件名
assetModuleFilename: 'static/media/[name][hash:10][ext][query]', // 图片等公共资源打包后的名字
},
module: {
rules: [
/**
* 样式资源处理
*/
{
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: /\.(png|jpe?g|gif|svg)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
},
/**
* 字体图标处理
*/
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource", // 原封不动输出
},
/**
* js资源处理
*/
{
test: /\.js$/,
include: path.resolve(__dirname, "../src"),
loader: 'babel-loader',
options: {
cacheDirectory: true, // 开启babel编译缓存
cacheCompression: false, // 缓存文件不要压缩
}
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new ESLintWebpackPlugin({
context: path.resolve(__dirname, "../src"),// 要处理的文件范围
exclude: "node_modules",
cache: true,
cacheLocation: path.resolve(__dirname, "../node_modules/.cache/.eslintcache"), // 缓存目录
}),
// 处理html资源
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
new VueLoaderPlugin(),
// cross-env定义的环境变量给打包工具webpack使用
// DefinePlugin定义的环境变量给代码内部使用!
new DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false
})
],
optimization: {
splitChunks: {
chunks: "all", // 代码分割
},
runtimeChunk: {
name: (entrypoint) => `runtime~${entrypoint.name}`,
},
},
mode: "development",
devtool: "cheap-module-source-map",
// webpack解析模块加载选项
resolve: {
// 自动补全扩展名
extensions: [".vue", ".js", ".json"]
},
// 自动化配置
devServer: {
open: true, // 是否自动打开浏览器
host: "localhost",
port: 4000,
hot: true, // 热模块替换
historyApiFallback: true, // 解决react-router刷新404问题
},
}
遇到的问题
环境变量
在完成基础的配置页面打开之后,控制台会报如下警告,说环境变量没有被定义,所以我们需要定义这两个环境变量!
解决
因为cross-env是给webpack使用的,但是这两个环境变量是在vue内部使用,所以我们需要用到webpack内置的一个插件DefinePlugin(专门用来定义环境变量给代码内部使用!),配置如下,配置完成之后就不会出现警告了!
webpack.dev.js
const { DefinePlugin } = require('webpack')
plugins:[
// cross-env定义的环境变量给打包工具webpack使用
// DefinePlugin定义的环境变量给代码内部使用!
new DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false
})
]
The template rootrequires exactly one element
在Vue3中<template>
支持多个根节点,但是发现代码依然在标红,虽然是能够正常运行的。找到原因是因为安装了插件vetur
,但是vetur
只能够去验证vue2的代码规范,就会导致标红报错!只需要将插件禁用即可,vue3 推荐使用Volar
来替换vetur
生产环境webpack配置
生产环境和开发环境配置基本是一样的,只需要做如下配置:
- 将css提取成单独文件用
MiniCssExtractPlugin.loader
- 对图片进行一下压缩用
image-minimizer-webpack-plugin
- 将public目录下的文件在打包时复制到dist目录下面用
copy-webpack-plugin
- 代码可以看github地址
生产模式和开发模式配置合并
github地址,Vue脚手架也有开发模式和生产模式合并的配置,主要就是通过下面这段代码去判断环境变量,判断当前运行的环境,去执行相对应的loader等,就不放代码了,可以在github看到。
// 获取cross-env定义的环境变量
const isProduction = process.env.NODE_ENV === 'production'
配置优化
element-plus按需引入
参考文档element-plus官方文档,
首先你需要安装unplugin-vue-components
和 unplugin-auto-import
这两款插件,然后进行如下配置即可完成按需引入!
npm install -D unplugin-vue-components unplugin-auto-import
// webpack.config.js
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = {
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
自定义主题颜色
参考element-plus官方文档,更改自定义主题是通过 SCSS 变量来进行改的,只需要进行如下配置,进行引入即可。
// styles/element/index.scss
/* 只需要重写你需要的即可 */
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': green,
),
),
);
// 如果只是按需导入,则可以忽略以下内容。
// 如果你想导入所有样式:
// @use "element-plus/theme-chalk/src/index.scss" as *;
手动引入
// main.js
......
import './styles/element/index.scss'
自动引入
使用 scss.additionalData
来编译所有应用 scss 变量的组件。
//webpack/config.js
// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
return [
isProduction ? MiniCssExtractPlugin.loader : 'vue-style-loader',
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor && {
loader: preProcessor,
options: preProcessor === 'sass-loader' ? {
additionalData: `@use "@/styles/element/index.scss" as *;`, // 自动引入
} : {}
}
].filter(Boolean);
};
......
plugins:[
Components({
resolvers: [
ElementPlusResolver({
// 自定义主题引入sass
importStyle: 'sass'
})
],
}),
]
tips
additionalData: `@use "~/styles/element/index.scss" as *;`,
在官网中是这样写,~
是路劲别名,通常我们使用@
,需要进行配置才可以生效:
// webpack.config.js
......
// webpack解析模块加载选项
resolve: {
// 自动补全扩展名
extensions: [".vue", ".js", ".json"],
alias: {
"@": path.resolve(__dirname, '../src')
}
}
......
这样配置就完成了,按钮就从原来的蓝色变成了绿色!
代码分割优化
因为node-moudel中的文件打包成单独一个文件的话太大,会影响加载速度也会影响按需引入的使用!所以我们可以将其进行分割进行单独打包,配置如下:
// webpack.config.js
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
.....
performance: false
其他配置
// package.json
{
"name": "Vue-scaffold",
"version": "1.0.0",
"description": "",
"main": ".eslintrc.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": "",
"license": "ISC",
"devDependencies": {
"@babel/eslint-parser": "^7.19.1",
"@vue/cli-plugin-babel": "^5.0.8",
"@vue/compiler-sfc": "^3.2.45",
"babel-loader": "^9.1.0",
"copy-webpack-plugin": "^11.0.0",
"cross-env": "^7.0.3",
"css-loader": "^6.7.2",
"css-minimizer-webpack-plugin": "^4.2.2",
"eslint": "^8.29.0",
"eslint-plugin-vue": "^9.8.0",
"eslint-webpack-plugin": "^3.2.0",
"html-webpack-plugin": "^5.5.0",
"image-minimizer-webpack-plugin": "^3.8.1",
"imagemin": "^8.0.1",
"less-loader": "^11.1.0",
"mini-css-extract-plugin": "^2.7.2",
"postcss-loader": "^7.0.2",
"postcss-preset-env": "^7.8.3",
"sass": "^1.56.2",
"sass-loader": "^13.2.0",
"stylus-loader": "^7.1.0",
"unplugin-auto-import": "^0.12.0",
"unplugin-vue-components": "^0.22.11",
"vue-loader": "^17.0.1",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.7.14",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1"
},
"dependencies": {
"element-plus": "^2.2.26",
"vue": "^3.2.36",
"vue-router": "^4.1.6"
}
}
// babel.config.js
module.exports = {
// 用来编译ES6的语法
presets: ["@vue/cli-plugin-babel/preset"],
}
// eslinttr.js
module.exports = {
root: true,
env: {
node: true,
},
extends: ["plugin:vue/vue3-essential", "eslint:recommended"],
parserOptions: {
parser: "@babel/eslint-parser",
},
};
小结
通过以上配置,就完成了使用webpack从0搭建一个vue脚手架,且进行了一些优化配置。今天是更文的第20天了,距离4级只需要280掘力值了,加油!
转载自:https://juejin.cn/post/7175386566993870903