vue3_vite_project
基于 Vue3
+ Vite
搭建的前端工程化项目演示模板
环境准备
- 开发环境:
Node.js v16.14.2
+npm v8.3.2
- 开发工具:
Visual Studio Code
orWebStorm
- 源代码管理:
Git
- npm镜像:
npm config set registry https://registry.npmmirror.com
技术栈
技术栈 | 描述 |
---|---|
Vue | 渐进式 JavaScript 框架 |
Vite | 新一代前端开发与构建工具 |
Element Plus | 基于 Vue 3,面向设计师和开发者的组件库 |
Pinia | 符合直觉的 Vue.js 状态管理库 |
vue-router | Vue.js 的官方路由管理库 |
Sass | CSS 预处理器 |
VueUse | 基于 Vue 组合式 API 的实用工具集 |
Axios | 用于浏览器和 Node.js 的基于 Promise 的 HTTP 请求库 |
Echarts | 一个基于 JavaScript 的开源可视化图表库 |
Eslint | 可配置的 JavaScript 检查器 |
Prettier | 代码格式化工具 |
项目构建
#创建项目 npm create vite #安装依赖 npm install #启动项目 npm run dev #构建项目 npm run build
到这一步,如果能成功运行项目,恭喜你!一个项目的基本框架已经搭建完成!
整理项目结构
主要是让项目工程更加感觉清晰
<!--src/App.vue--> <template> <div> <h1>App</h1> </div> </template>
删除 src/style.css
文件
删除 src/main.js
中引入的 style.css
文件
使用 Git 管理源代码
#Git仓库初始化 git init #添加所有文件到版本库 git add . #提交所有文件到版本库 git commit -m "feat: 项目初始化完成" #新建 dev 分支,并切换到 dev 分支 git checkout -b dev
本地代码仓库初始化完成,之后的开发工作都在当 dev 分支上进行
根据技术栈提供的文档,完成项目搭建
安装 Element Plus 组件库
#安装 Element Plus npm install element-plus
引入 Element Plus 组件库并使用测试安装结果
# src/main.js import { createApp } from 'vue' import ElementPlus from 'element-plus' # 新增 import 'element-plus/dist/index.css' # 新增 import App from './App.vue' const app = createApp(App) app.use(ElementPlus) # 新增:使用 Element Plus 组件库 app.mount('#app')
测试安装结果
<!--src/App.vue--> <template> <div> <h1>App</h1> <el-button type="primary">button</el-button> </div> </template>
当按钮能正常显示时,说明安装成功
安装 Vue Router 路由管理库
#安装 Vue Router npm install vue-router
在项目的 src 目录下新建一个 views
目录,然后在 views 目录下新建两个页面,用于路由跳转。
在项目的 src 目录下新建一个 router
目录,然后在 router 目录下新建一个 index.js 文件,该文件会作为 Vue Router 的入口文件,该文件内容如下
// src/router/index.js import {createRouter, createWebHistory} from "vue-router"; const router = new createRouter({ history: createWebHistory(), routes: [ { path: "/login", name: "Login", component: () => import("../views/login/index.vue"), }, { path: "/dashboard", name: "Dashboard", component: () => import("../views/dashboard/index.vue"), }, ] }) export default router
在 src/main.js 文件中引入 Vue Router,并使用 Vue Router
// src/main.js // ... import router from './router' // 新增 app.use(router) // 新增:使用 Vue Router // ...
修改 App.vue 文件,添加路由跳转
<template> <div class="app-container"> <ul> <li><router-link to="/dashboard">首页</router-link></li> <li><router-link to="/login">登录</router-link></li> </ul> <router-view /> </div> </template>
访问首页和登录页,查看路由是否正常跳转
router-link
和 router-view
是 Vue Router 的两个核心组件,router-link 是用来实现路由跳转,router-view 是用来显示路由对应的内容。
安装 Pinia 状态管理库
#安装 Pinia npm install pinia
在项目的 src 目录下新建一个 store
目录,然后在 store 目录下新建一个 index.js 文件,该文件会作为 Pinia 的入口文件
// src/store/index.js import {createPinia} from 'pinia' const pinia = createPinia() export default pinia
在 src/main.js 文件中引入 Pinia,并使用 Pinia
// src/main.js // ... import pinia from './store' // 新增 app.use(router) // 新增:使用 Pinia // ...
在 src/store 目录下创建一个 modules 目录,然后在 modules 目录下创建一个 user
状态管理对象,用于管理整个项目的用户登录状态
// src/store/modules/user.js import {defineStore} from 'pinia' import {ref} from 'vue' const useUserStore = defineStore('user', () => { const userInfo = ref({}) const loginStatus = ref(false) const token = ref('') /** * 登录 */ function handleLogin() { return new Promise((resolve, reject) => { if(Math.random() > 0.8){ loginStatus.value = true token.value = String(new Date().getTime()) userInfo.value = { name: 'admin', avatar: '/zb_users/upload/2024/csdn/f778738c-e4f8-4870-b634-56703b4acafe.gif?imageView2/1/w/80/h/80', } resolve('登录成功') }else { reject('登录失败') } }) } /** * 退出登录 */ function handleLogout() { return new Promise((resolve) => { loginStatus.value = false token.value = '' userInfo.value = {} resolve() }) } return { userInfo, loginStatus, token, handleLogin, handleLogout } }) export default useUserStore
在登录页面,使用 Pinia 获取用户状态管理对象,并调用登录方法
<!--src/views/login/index.vue--> <script setup> import useUserStore from '../../store/modules/user' const userStore = useUserStore() import {ElMessage } from 'element-plus' /** * 登录 */ function login() { userStore.handleLogin().then((res) => { ElMessage.success(res) }).catch(err => { ElMessage.error(err) }) } /** * 退出登录 */ function loginOut() { userStore.handleLogout().then(() => { ElMessage.success('退出登录成功') }).catch(err => { ElMessage.error(err) }) } </script> <template> <div class="login-container"> <el-button type="primary" @click="login">登 录</el-button> <el-button type="primary" @click="loginOut">退出登录</el-button> <hr> <h1>当前登录状态:{{ userStore.loginStatus ? '已登录' : '未登录' }}</h1> <ul> <li>用户名:{{ userStore.userInfo.name }}</li> <li>头 像:<img :src="userStore.userInfo.avatar" alt=""></li> </ul> </div> </template>
安装 Sass CSS 预处理器
#安装 Sass,安装时需要添加 -D 参数,表示将 Sass 添加到开发依赖中,在打包过程中,Sass 会自动编译为 CSS npm install sass -D
在项目的 src 目录下新建一个 styles
目录,然后在 styles 目录下新建一个 variables.scss
文件,该文件存放全局的 Sass 变量
//src/styles/variables.scss $success: #48C78E; $danger: #F28482;
在首页测试 Sass 变量,在 src/views/dashboard/index.vue 文件中修改如下
<template> <h1 class="success">这是一个成功样式</h1> <h2 class="danger">这是一个告警样式</h2> </template> <style scoped lang="scss"> .success{ color:$success; } .danger{ color: $danger; } </style>
此时浏览器会提示 Undefined variable.
,因为我们需要在 vite.config.js 文件中引入该文件,才能使用 Sass 变量
// vite.config.js import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], css: { // CSS 预处理器 preprocessorOptions: { // 定义全局 SCSS 变量 scss: { javascriptEnabled: true, additionalData: "@use '/src/styles/variables.scss' as *;", }, }, }, })
查看页面会显示成功和告警样式,表示 Sass 变量已经正常工作了
安装 VueUse 工具库
#安装 VueUse npm i @vueuse/core
在 src/views/dashboard/index.vue 文件中,使用 VueUse 的 useMouse
方法,获取当前鼠标实时位置
<script setup> import {useMouse} from '@vueuse/core' const {x,y} = useMouse() </script> <template> <h1 class="success">这是一个成功样式</h1> <h2 class="danger">这是一个告警样式</h2> <p>当前鼠标位置:X:{{ x }}、Y:{{ y }}</p> </template> <style scoped lang="scss"> .success{ color:$success; } .danger{ color: $danger; } </style>
页面上会实时显示鼠标的位置,表示 VueUse 工具库已经正常工作了,需要使用其它函数,可以参考 VueUse 文档
安装 Axios 网络请求库
#安装 Axios npm install axios
在 src 目录下新建一个 utils 目录,然后在 utils 目录下新建一个 request.js
文件,在该文件中,可以在发起请求前向请求头中添加一些请求头等信息
// src/utils/request.js import axios from 'axios' const request = axios.create({ baseURL: 'http://xxx.xxx.xxx.xxx // 请求的后端接口地址 }) /** * 请求拦截器 */ request.interceptors.request.use(config => { console.log('请求参数:',config) }) /** * 响应拦截器 */ request.interceptors.response.use(response => { console.log('响应参数:',response) }) export default request
在 src 目录下新建一个 api 目录,然后在 api 目录下新建一个 user.js
文件,在该文件中,封装一些用户相关的接口
import request from "../utils/request"; /** * 获取验证码 * @param checkKey */ export function getCodeInfo(checkKey) { return request({ method: "get", url: `/xxx/xxx/${checkKey}`, }); }
回到登录页面,测试获取验证码接口,修改如下:
<script setup> import {getCodeInfo} from '../../api/user' import {onMounted, ref} from "vue"; const captchaInfo = ref('') onMounted(() => { getCodeInfo(new Date().getTime()).then(({data}) => { captchaInfo.value = data.result }) }) </script> <template> <div class="login-container"> <ul> <li>验证码:<img :src="captchaInfo" alt=""></li> </ul> </div> </template>
页面上成功显示了验证码,表示 Axios 工具库已经正常工作了,之后其它 API 接口都统一放到 src/api 目录下统一管理
安装 Echarts 图表库
#安装 Echarts npm install echarts
在 src/views/dashboard/index.vue 文件中,使用 Echarts 的 init
方法,初始化一个图表
<script setup> import * as echarts from 'echarts'; import {onMounted, ref} from "vue"; const chartRef = ref(null) let echartClient = null onMounted(() => { initChart() }) function initChart() { echartClient = echarts.init(chartRef.value) echartClient.setOption({ tooltip: {}, xAxis: { data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'] }, yAxis: {}, series: [ { name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] } ] }) } </script> <template> <div class="chart-box" ref="chartRef" ></div> </template> <style scoped lang="scss"> .chart-box{ width: 600px; height: 400px; } </style>
页面上可以看到一个柱状图,表示 Echarts 工具库已经正常工作了
安装 Eslint 代码检查工具
#安装 Eslint 及相关插件 npm install eslint -D npm install eslint-config-airbnb-base -D npm install eslint-define-config -D npm install eslint-plugin-import -D npm install eslint-plugin-vue -D
在项目更目录下新建一个 .eslintrc.js
文件,配置如下:
// .eslintrc.js const { defineConfig } = require("eslint-define-config"); module.exports = defineConfig({ root: true, env: { browser: true, node: true, jest: true, es6: true, }, plugins: ["vue"], parser: "vue-eslint-parser", parserOptions: { ecmaVersion: "latest", sourceType: "module", allowImportExportEverywhere: true, ecmaFeatures: { jsx: true, }, }, extends: [ "eslint-config-airbnb-base", "eslint:recommended", "plugin:vue/vue3-essential", "plugin:vue/vue3-recommended", "plugin:vue/vue3-strongly-recommended", "plugin:import/recommended", "plugin:import/errors", "plugin:import/warnings", // ".eslintrc-auto-import.json", // 解决 Eslint 提示 no-undef 错误 "prettier", "plugin:prettier/recommended", ], /** * 规则说明:off 或 0 - 关闭规则;warn 或 1 - 打开规则作为警告(不影响退出代码);error 或 2 - 打开规则作为错误(退出代码将为 1) */ rules: { // 不使用制表符 "prettier/prettier": 2, // 强制使用分号 semi: [2, "always"], // 强制使用双引号 quotes: [2, "double"], // 解决最后一个逗号 // "comma-dangle": [2, "never"], // 关闭默认参数应为最后一个 "default-param-last": 0, // 禁止未使用的变量 "no-unused-vars": 1, // 关闭组件命名规则 "vue/multi-word-component-names": 0, // 禁止使用多余的包 "import/no-extraneous-dependencies": 0, // 确保在导入路径内一致使用文件扩展名 "import/extensions": 0, // 确保导入指向可以解析的文件/模块 "import/no-unresolved": 0, // 首选默认导出导入/首选默认导出 "import/prefer-default-export": 0, // 要求使用 let 或 const 而不是 var "no-var": 2, // 禁止使用 new 以避免产生副作用 "no-new": 1, // 禁止变量声明与外层作用域的变量同名 "no-shadow": 0, // 禁用 console "no-console": 0, // 禁止标识符中有悬空下划线 "no-underscore-dangle": 0, // 禁止在可能与比较操作符相混淆的地方使用箭头函数 "no-confusing-arrow": 0, // 禁用一元操作符 ++ 和 -- "no-plusplus": 0, // 禁止对 function 的参数进行重新赋值 "no-param-reassign": 0, // 禁用特定的语法 "no-restricted-syntax": 0, // 禁止在变量定义之前使用它们 "no-use-before-define": 0, // 禁止直接调用 Object.prototypes 的内置属性 "no-prototype-builtins": 0, // 禁止可以在有更简单的可替代的表达式时使用三元操作符 "no-unneeded-ternary": 2, // 禁止重复模块导入 "no-duplicate-imports": 2, // 禁止在对象中使用不必要的计算属性 "no-useless-computed-key": 2, // 禁止不必要的转义字符 "no-useless-escape": 0, // 禁用 continue 语句 "no-continue": 0, // 强制使用一致的缩进 indent: [2, 2, { SwitchCase: 1 }], // 强制使用骆驼拼写法命名约定 camelcase: 0, // 强制类方法使用 this "class-methods-use-this": 0, // 要求构造函数首字母大写 "new-cap": 2, // 强制一致地使用 function 声明或表达式 "func-style": 0, // 强制一行的最大长度 "max-len": 0, // 要求 return 语句要么总是指定返回的值,要么不指定 "consistent-return": 0, // 强制switch要有default分支 "default-case": 2, // 强制剩余和扩展运算符及其表达式之间有空格 "rest-spread-spacing": 2, // 要求使用 const 声明那些声明后不再被修改的变量 "prefer-const": 2, // 强制箭头函数的箭头前后使用一致的空格 "arrow-spacing": 2, // 只强制对象解构,不强制数组解构 "prefer-destructuring": [2, { object: true, array: false }], // 禁止在对象中使用不必要的计算属性 "no-unused-expressions": 0, }, });
修改 package.json
文件,在 scripts
中添加 "lint": "eslint --ext .js,.vue --fix src"
,运行 npm run lint
命令,会自动修复所有代码问题
安装 Prettier 代码格式化工具
#安装 Prettier 及相关插件 npm install -D prettier npm install -D eslint-plugin-prettier
在项目根目录下新建一个 .prettierrc.cjs
文件,配置如下:
module.exports = { // JSX 中的右尖括号是否换行,默认false jsxBracketSameLine: false, // 文件末尾是否换行,默认true endOfLine: "auto", // 换行符类型 (lf|crlf|cr;默认lf) rangeStart: 0, // 单个属性是否换行,默认false singleAttributePerLine: false, // 是否使用双引号,默认true doubleQuote: true, // 是否使用单行注释,默认false experimentalTernaries: false, // (x)=>{},单个参数箭头函数是否显示小括号。(always:始终显示;avoid:省略括号。默认:always) arrowParens: "always", // 开始标签的右尖括号是否跟随在最后一行属性末尾,默认false bracketSameLine: false, // 对象字面量的括号之间打印空格 (true - Example: { foo: bar } ; false - Example: {foo:bar}) bracketSpacing: true, // 是否格式化一些文件中被嵌入的代码片段的风格(auto|off;默认auto) embeddedLanguageFormatting: "auto", // 指定 HTML 文件的空格敏感度 (css|strict|ignore;默认css) htmlWhitespaceSensitivity: "css", // 当文件已经被 Prettier 格式化之后,是否会在文件顶部插入一个特殊的 @format 标记,默认false insertPragma: false, // 在 JSX 中使用单引号替代双引号,默认false jsxSingleQuote: false, // 每行最多字符数量,超出换行(默认80) printWidth: 120, // 超出打印宽度 (always | never | preserve ) proseWrap: "preserve", // 对象属性是否使用引号(as-needed | consistent | preserve;默认as-needed:对象的属性需要加引号才添加;) quoteProps: "as-needed", // 是否只格式化在文件顶部包含特定注释(@prettier| @format)的文件,默认false requirePragma: false, // 结尾添加分号 semi: true, // 使用单引号 (true:单引号;false:双引号) singleQuote: false, // 缩进空格数,默认2个空格 tabWidth: 2, // 元素末尾是否加逗号,默认es5: ES5中的 objects, arrays 等会添加逗号,TypeScript 中的 type 后不加逗号 trailingComma: "es5", // 指定缩进方式,空格或tab,默认false,即使用空格 useTabs: false, // vue 文件中是否缩进 <style> 和 <script> 标签,默认 false vueIndentScriptAndStyle: false, };
修改 package.json
文件,在 scripts
中添加 "prettier": "prettier --write src/**/*.{vue,js,jsx,ts,tsx,json,css,scss,md}"
,运行 npm run prettier
命令,会自动格式化所有代码
性能优化及打包策略
配置 Element Plus 按需导入
#安装插件 npm install -D unplugin-vue-components unplugin-auto-import
修改 vite.config.js
文件,添加了 vue
, vue-router
, @vueuse/core
相关函数自动导入配置
自动导入 src/**/components
目录下的组件,无需在页面中手动导入组件,添加了路径别名,@
默认指向 src
目录,导入模块的时候可以直接使用 import xxx from "@/xxx/xxx"
形式
// vite.config.js import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; import AutoImport from "unplugin-auto-import/vite"; import Components from "unplugin-vue-components/vite"; import { ElementPlusResolver } from "unplugin-vue-components/resolvers"; import { resolve } from "path"; const pathSrc = resolve(__dirname, "src"); export default defineConfig({ plugins: [ vue(), // 自动导入 AutoImport({ // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等 imports: ["vue", "vue-router", "@vueuse/core"], resolvers: [ // 自动导入 Element Plus 相关函数 ElementPlusResolver(), ], eslintrc: { enabled: true, // 解决 Eslint 提示 no-undef 错误 }, // 配置文件位置 (false:关闭自动生成) dts: resolve(__dirname, "src/types/auto-imports.d.ts"), }), Components({ resolvers: [ // 自动导入 Element Plus 组件 ElementPlusResolver(), ], // 指定自定义组件位置(默认:src/components) dirs: ["src/**/components"], // 配置文件位置 (false:关闭自动生成) dts: resolve(__dirname, "src/types/components.d.ts"), }), ], resolve: { // 导入文件时省略文件扩展名 extensions: [".js", ".ts", ".vue", ".json", "es"], // 配置路径别名 alias: { "@": pathSrc }, }, // ... });
删除 src/main.js
文件中之前引入的 Element Plus 的代码
// src/main.js import { createApp } from "vue"; // import ElementPlus from "element-plus"; // 删除 import router from "./router"; import pinia from "./store"; // import "element-plus/dist/index.css"; // 删除 import App from "./App.vue"; const app = createApp(App); app.use(router); app.use(pinia); // app.use(ElementPlus); // 删除 app.mount("#app");
删除 src/views/login/index.vue
中的 import { ElMessage } from "element-plus";
代码,现在所有与 Element Plus 相关的代码都被自动导入了,无需再手动引入。
修改 .eslintrc.cjs
文件中 extends
项,添加 ".eslintrc-auto-import.json"
配置,解决 Eslint 提示 no-undef 错误
# ... extends: [ # ... ".eslintrc-auto-import.json", # 解决 Eslint 提示 no-undef 错误 ] # ...
按需导入 Echarts 图表库
在 src/utils
文件夹下创建 echarts.js
文件,把需要用到的图表组件导入到该文件中,在需要使用 Echarts 的地方直接导入该文件,这样就可以按需导入 Echarts 图表库了
// src/utils/echarts.js // 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。 import * as echarts from "echarts/core"; // 引入柱状图图表,图表后缀都为 Chart import { BarChart } from "echarts/charts"; // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component import { TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, } from "echarts/components"; // 标签自动布局、全局过渡动画等特性 import { LabelLayout, UniversalTransition } from "echarts/features"; // 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步 import { CanvasRenderer } from "echarts/renderers"; // 注册必须的组件 echarts.use([ TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, BarChart, LabelLayout, UniversalTransition, CanvasRenderer, ]); export default echarts;
修改 src/views/dashboard/index.vue
文件,引入 src/utils/echarts.js
文件,这样就可以按需导入 Echarts 图表库了
// import * as echarts from "echarts"; // 删除 import echarts from "@/utils/echarts"; // 新增 // ...
打包静态资源优化
#安装插件 npm install terser -D
修改 vite.config.js
文件,添加了 terser
配置,打包时会自动压缩 js 文件,配置了 build.rollupOptions
将打包后的静态资源按文件类型进行分类
import { defineConfig } from "vite"; // ... export default defineConfig({ // ... // 预览模式配置 preview: { port: 8081, open: true, }, // 开发模式配置 server: { https: false, // 是否开启 https port: 8080, // 端口号 host: "0.0.0.0", // 监听所有地址 open: true, // 服务启动时是否自动打开浏览器 cors: true, // 允许跨域 proxy: {}, // 自定义代理规则 }, // 构建配置 build: { chunkSizeWarningLimit: 2000, // 消除打包大小超过500kb警告 minify: "terser", // Vite 2.6.x 以上需要配置 minify: "terser", terserOptions 才能生效 terserOptions: { compress: { keep_infinity: true, // 防止 Infinity 被压缩成 1/0,这可能会导致 Chrome 上的性能问题 drop_console: true, // 生产环境去除 console drop_debugger: true, // 生产环境去除 debugger }, format: { comments: false, // 删除注释 }, }, rollupOptions: { output: { // 用于从入口点创建的块的打包输出格式[name]表示文件名,[hash]表示该文件内容hash值 entryFileNames: "js/[name].[hash].js", // 用于命名代码拆分时创建的共享块的输出命名 chunkFileNames: "js/[name].[hash].js", // 用于输出静态资源的命名,[ext]表示文件扩展名 assetFileNames: (assetInfo) => { const info = assetInfo.name.split("."); let extType = info[info.length - 1]; // console.log('文件信息', assetInfo.name) if (/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/i.test(assetInfo.name)) { extType = "media"; } else if (/\.(png|jpe?g|gif|svg)(\?.*)?$/.test(assetInfo.name)) { extType = "img"; } else if (/\.(woff2?|eot|ttf|otf)(\?.*)?$/i.test(assetInfo.name)) { extType = "fonts"; } return `${extType}/[name].[hash].[ext]`; }, }, }, }, });
开启 Gzip 压缩
#安装插件 npm install vite-plugin-compression -D
修改 vite.config.js
文件,添加了 vite-plugin-compression
插件
import { defineConfig } from "vite"; // ... import viteCompression from "vite-plugin-compression"; export default defineConfig({ plugins: [ // ... viteCompression(), ], // ... });
在 Vite
构建项目时开启 Gzip
压缩后,为了确保 Nginx
能够正确处理并返回 Gzip
压缩后的文件,你需要在 Nginx
服务器上进行相应的配置
http { gzip on; gzip_static on; # 开启静态gzip功能,优先返回预压缩的.gz文件 server { listen 8080; server_name localhost; location / { root /usr/share/nginx/html/dist; # 替换为你的实际项目部署目录 index index.html index.htm; try_files $uri $uri/ /index.html; # 指定如果存在预压缩文件,则优先返回 .gz 文件 gzip_static always; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
在这个配置中,Nginx会在接收到请求时首先查找是否存在对应的.gz预压缩文件,如果存在则直接返回该文件,否则会返回原始未压缩的文件。
确保Vite构建时生成的预压缩文件与原始文件位于同一目录下,并且命名规范遵循Nginx的预期(即与原始文件同名,但扩展名为.gz)。同时,在重启Nginx服务后使新配置生效。