您好,如果喜欢我的文章,可以关注我的公众号「量子前端」,将不定期关注推送前端好文~
前言
Vue是当下非常火热的前端框架,选择Vue-Cli是大部分人主流的选择,因为其快捷、便利可以让我们一键生成整个项目模板,如果需要自定义配置下从0开始搭建一个Vue项目,其实也不难,接下来就来记录一下。
项目初始化
通过命令:
npm init -y
生成一个初始的带包管理器的项目模板,参考Vue3脚手架生成的目录,我们也同样同步目录文件:
文件内容笔者直接参照vue-cli生成的文件内容复制粘贴~~就不贴代码了。
构建打包
这里我们选择Webpack进行打包,首先下载依赖包。
npm i --save-dev webpack webpack-cli webpack-dev-server webpack-merge html-webpack-plugin
这里首先下载这几个最基本的依赖包,简单说明下:
- webpack 我们需要打包的包
- webpack-cli 打包依赖包+1
- webpack-dev-server 开发环境建立本地网络服务器所需的包
- webpack-merge 开发环境、生产环境分离打包
- html-wepback-plugin 打包html文件的依赖包
OK,下载完成,接下来我们新建3个文件
webpack.config.js、webpack.config.dev.js、webpack.config.pro.js
这里简单说明下,如果不理解可以看笔者最近的一篇文章Webpack分环境打包(生产/开发两套打包)
- webpack.config.js 公共配置项
- webpack.config.dev.js 开发环境的配置项
- webpack.config.pro.js 生产环境的配置项
配置npm命令
这里配置一下生产环境和开发环境的打包命令。
scripts: {
"dev": "webpack-dev-server --mode=development --config webpack.config.dev.js",
"build": "npx webpack --mode=production --config webpack.config.pro.js"
}
配置webpack.config.js
配置项:
const path = require('path')
const {
VueLoaderPlugin } = require('vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {
CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
resolve: {
extensions: ['.js', '.vue'],
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
},
{
test: /\.(png|jpe?g|gif|svg|webp|ico)$/,
type: 'asset/resource'
},
{
test: /\/js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
cacheDirectory: true
}
}
}
],
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html', // 这是html模板存放的地址
filename: 'index.html',
}),
new CleanWebpackPlugin()
],
}
简单说明下,首先安装公共配置的依赖包:
npm i --save-dev vue-loader clean-webpack-plugin babel-loader @babel/preset-env
- entry、output分别配置了项目的打包入口和打包出口,这个是公共配置项,毋庸置疑;
- resolve配置了项目中的便捷路径转义写法,这里就先写一个常用的@;
- loader中配置了vue-loader、静态资源、babel三个预处理器进行文件处理;
- plugins中配置了vue的插件、html模板编译、打包清空目录三个插件;
这些都是生产、开发环境不会改变的固定配置。
配置webpack.config.dev.js
接下来进行开发环境的打包配置:
const path = require('path');
const {
merge } = require('webpack-merge');
const baseConfig = require('./webpack.config.js');
module.exports = merge(baseConfig, {
module: {
rules: [
{
test: /\.css|scss|sass$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
]
},
devServer: {
open: true,
host: '127.0.0.1',
port: 8080,
client: {
logging: 'none',
},
hot: true,
historyApiFallback: true
},
mode: 'development',
devtool: 'inline-source-map'
})
这里开发环境比较简单,主要就是devServer本地服务器的配置,可以让我们方便的开发,以及样式的预处理器,由于开发中不需要进行压缩,因此选择style-loader即可。
最后通过webpack-merge插件将当前配置和webpack.config.js配置合并。
开发配置中所需的依赖包:
npm i --save-dev style-loader css-loader sass-loader sass
配置webpack.config.pro.js
接下来进行生产环境的配置:
const path = require('path');
const {
merge } = require('webpack-merge');
const baseConfig = require('./webpack.config.js');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = merge(baseConfig, {
module: {
rules: [
{
test: /\.css|scss|sass$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
},
]
},
plugins: [
new CopyPlugin({
patterns: [
{
from: path.resolve(__dirname, 'public', 'favicon.ico'),
to: path.resolve(__dirname, 'dist/image/')
}
]
})
],
optimization: {
usedExports: true,
minimize: true,
minimizer: [
new TerserPlugin(),
new MiniCssExtractPlugin({
filename: 'index-[contenthash:8].css',
chunkFilename: '[id].css'
})
]
},
cache: {
type: 'filesystem',
},
mode: 'production',
devtool: 'cheap-module-source-map'
})
生产环境的打包因注重优化,如打包文件体积、打包速度,因此都是一些优化配置项。
先说一下生产环境的依赖包把。
npm i --save-dev mini-css-extract-plugin copy-webpack-plugin
配置项介绍:
- 样式预处理器采用 mini-css-extract-plugin 将所有样式抽离成一行;
- copy-webpack-plugin 将一些静态资源直接转移至dist目录,这里用Vue ico举例;
- optimization 进行了代码压缩,包括tree-shaking、js压缩、css压缩;
- cache 开启文件缓存,可以让我们的打包速度飞跃性的提升;
产物
至此,我们的所有webpack配置就结束了,展示一下产物吧。
生产环境打包:
开发环境页面:
Vue全家桶加入
Vue Router
首先下载依赖包:
npm i vue-router --save-dev
接下来在src目录下新建router文件夹,并创建index.js、routes.js。
index.js:
import {
createRouter, createWebHistory } from 'vue-router'
import routes from './routes' //导入router目录下的router.js
const router = createRouter({
history: createWebHistory(), //路由模式
routes
})
export default router; //导出
routes.js:
const routes = [
{
name: 'a',
path: '/a',
component: () => import('@/view/A')
},
{
name: 'b',
path: '/b',
component: () => import('@/view/B')
},
];
export default routes
在src目录下创建view目录,并创建A.vue、B.vue用于测试路由跳转。
A.vue:
<template>
<div>
A
</div>
</template>
<script setup>
import {
onMounted } from "vue"
onMounted(() => {
console.log("A页面渲染了")
})
</script>
<style lang="scss" scoped></style>
测试:
Vuex
下载依赖包:
npm i --save-dev vuex
在src目录下创建store.js并写入:
// VueX 创建了一个全局唯一的仓库,用来存放全局的数据
import {
createStore } from 'vuex';
export default createStore({
state: {
name: "John",
},
getters: {
},
mutations: {
changeName(state, value) {
state.name = value
},
},
actions: {
},
modules: {
}
})
接下来还是使用A.vue进行测试,A.vue文件修改为如下:
<template>
<div>
A
<span @click="changeName">{
{
store.state.name }}</span>
</div>
</template>
<script setup>
import {
onMounted } from "vue"
import {
useStore } from "vuex"
let store = useStore()
onMounted(() => {
console.log("A页面渲染了")
})
const changeName = () => {
store.commit("changeName", "Mike")
}
</script>
<style lang="scss" scoped></style>
测试:
Axios
下载依赖包:
npm i axios --save-dev
src目录下新建_utils/request.js:
import axios from 'axios'
// 创建一个 axios 实例
const service = axios.create({
baseURL: '/api', // 所有的请求地址前缀部分
timeout: 60000, // 请求超时时间毫秒
withCredentials: true, // 异步请求携带cookie
headers: {
// 设置后端需要的传参类型
'Content-Type': 'application/json',
'token': 'your token',
'X-Requested-With': 'XMLHttpRequest',
},
})
// 添加请求拦截器
service.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config
},
function (error) {
// 对请求错误做些什么
console.log(error)
return Promise.reject(error)
}
)
// 添加响应拦截器
service.interceptors.response.use(
function (response) {
console.log(response)
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
// dataAxios 是 axios 返回数据中的 data
const dataAxios = response.data
// 这个状态码是和后端约定的
const code = dataAxios.reset
return dataAxios
},
function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
console.log(error)
return Promise.reject(error)
}
)
export default service
至此,一个基础的Vue项目搭建完毕了,项目结构如图:
总结
使用Vue-Cli搭建项目很方便,但是自己从0搭建一个完整的Vue项目运行环境也是巩固Webpack学习的一个很好的过程,项目已经上传github给大家学习参考。