作者:codexu
链接:www.zhihu.com/question/46…
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1.搭建脚手架
使用 vue-cli 或 vite ,通过一系列的配置,初始化一个开发模板,无需从零开始搭建开发环境,可以有效的提升开发效率,相信也是大多数开发者接手一个新项目所使用的一种方式。尽管官方提供的脚手架已经足够优秀,但未必是真正符合我们自己团队的使用习惯,所以从官方的基础上,开发一款属于我们自己的脚手架,能更多的提升开发效率。
1.1 前端脚手架应具备哪些功能?
- 减少重复的初始化工作,不需要再复制其他类似的项目删除无关代码,或从零搭建一个项目。
- 可以根据团队需求,使用简单的交互操作生成相应的目录结构和文件。
- 统一团队的开发习惯、代码风格,保证构建结果的一致性。
- 完整的使用文档,降低新人上手、开发和后期维护成本。
1.2 如何开发一款自己的脚手架?
提到构建前端工程化中脚手架,相信大家已经看过不少文章,几年前我也曾经写过一篇关于脚手架构建的文章,随便搜一下关键词可以看到很多相关的文章,在这里不做太多的介绍,主要讲一些这些文章中很少提到的如何根据选项生成文件。
1.3 如何根据选项生成文件?
说实话我也不知道大佬们是怎么根据各种配置编译成相应的文件,这块希望大家踊跃发言,寻求一种更佳高效简洁的方式。在这里跟大家分享一下我的方案:
交互方面,搭建过脚手架的同学一定知道 inquirer,这个库可以很方便的通过交互式操作获取到我们选择的一些自定义配置参数。那么问题来了,如何通过这些配置相应的创建对应的文件呢?
这里我推荐使用 EJS + Prettier 生成代码,通过 fs-extra 写入最终的文件。
- EJS
EJS 是一款 JavaScript 模板引擎,我们可以通过传入参数,生成对应的代码串,例如创建一个 package.ejs 用来生成 package.json 中,如果我们选择使用了 scss 作为 CSS 预处理器,然后将 sass 和 stylelint-scss 作为项目的安装依赖:
<% if (precss === 'scss') { -%>
"sass": "1.26.5",
"stylelint-scss": "^3.20.1",
<% } -%>
模板引擎可以帮你通过参数生成代码,它并不会限制你生成任何类型的代码文件,因为我们生成的是纯代码,最后通过读取 .ejs 文件对应生成相应的类型文件即可。
- Prettier
Prettier 是一款代码格式化工具,相信大家对它并不陌生。使用 EJS 生成的目的还是给开发人员阅读和编辑,所以生成的代码应该符合最终的格式要求,因为后续我们会为脚手架添加 ESLint 和 StyleLint 等工具,刚刚创建的项目里面一堆红线报错可是十分不友好的。
import prettier = require("prettier");
prettier.format(code, { parser: 'json' }))
parser 是 prettier 的解析器,常见的 typescript、css、less、json 等文件都可以进行格式化。
2.基于 vite 的搭建基础模板
最早搭建 vue3 脚手架的时候,我选择的用 vue/cli 搭建,因为生态不健全,有些基于 webpack 的功能无法使用,但现在 vite 生态已经比较完善了,所以重构脚手架,由 webpack 转向 vite,这一步极大的提升了开发体验。
2.1 创建基本模板项目
npm init vite@latest
yarn create vite
pnpm create vite
然后按照提示操作即可,vite 提供的选项很少,只有 vue 或 vue + ts,不像 vue/cli 提供那么多的配置方式,所以剩下的东西需要我们手动配置。
当然 vite 也提供了很多模板,但是我认为做加法比做减法更加容易,在众多的模板中很难找到适合我们自己的。
2.2 常用插件推荐
这里先简单了解几个好用的 vite 插件:
- unplugin-vue-components:组件的按需自动导入。
- vite-plugin-svg-icons:用于生成 svg 雪碧图。
- vite-plugin-compression:使用 gzip 或者 brotli 来压缩资源。
为什么只推荐这么几个插件?因为 vite 对许多 webpack 需要安装的 loader 或 plugin 都有着天生的支持,比如 less、sass、typescript,后续会在相应的章节说明用法。
3.使用 Typescript
vue2.x 版本对 TypeScript 的支持是硬伤,而 TypeScript 对大型项目的保障能力是被普遍认可的。这一点在 vue3.x 版本中得到了非常友好的支持。
Vite 天然支持引入
.ts文件。
这里对 tsconfig.json 做了一些修改:
{
"compilerOptions": {
"types": ["vite/client"],
"baseUrl": "src",
"paths": {
"@/*": ["./*"]
}
},
"exclude": ["node_modules"]
}
在初期使用 typeScript 的时候,很多人都很喜欢使用 any 类型,把 typeScript 写成了 anyScript ,虽然使用起来很方便,但是这就失去了 typeScript 的类型检查意义了,当然写类型的习惯是需要慢慢去养成的,不用急于一时。
4.配置环境变量
vite 提供了两种模式:具有开发服务器的开发模式(development)和生产模式(production)。
这里我们可以建立 4 个 .env 文件,一个通用配置和三种环境:开发、测试、生产。
4.1 配置模式
NODE_ENV=development # 开发模式
NODE_ENV=production # 生产模式
- .env 通用配置,我个人喜欢把他当作项目的配置文件,例如项目的 title,此文件不对应任何模式。
- .env.development 开发环境,使用 development 模式。
- .env.staging 测试环境,因为要部署到测试服务器,或本地使用 serve 命令预览,所以使用 production 模式。
- .env.production 生产环境,因为要部署到测试服务器,或本地使用 serve 命令预览,所以使用 production 模式。
package.json 内 script 需要增加 staging 命令
"script": {
"build": "vue-tsc --noEmit && vite build",
"staging": "vue-tsc --noEmit && vite build --mode staging",
"serve": "vite preview --host"
}
4.2 常用的环境变量
推荐使用以下常见的三个变量:
- VITE_APP_BASE_URL
接口请求地址。
通常后端会区分三种环境,部署在不同的地址下。
- VITE_APP_STATIC_URL
静态资源地址。
静态资源我是不建议你直接放在项目中,这会导致项目仓库变得巨大。
本地开发和测试环境我会选在使用本地搭建的静态资源服务器,你可以找后端运维的同学帮你搭建,或者你使用 http-server 在本地启动一个服务器也可以。生产环境建议上传至 OSS。
- VITE_PUBLIC_PATH
构建资源公共路径。
这个与 vue/cli 中的 publicPath 同理,有的时候你构建的项目并不是存放在跟路径下,例如 http://ip:port/{项目名}。
4.3 封装静态资源文件
如果你配置了 VITE_APP_STATIC_URL 静态资源环境变量,那么你需要封装以下两个东西:
- 根据环境返回实际的资源地址函数。
- 方便使用的静态资源组件。
baseStaticUrl.ts
// 处理静态资源链接
export default function baseStaticUrl(src = '') {
const { VITE_APP_STATIC_URL } = import.meta.env;
if (src) {
return `${VITE_APP_STATIC_URL}${src}`;
}
return VITE_APP_STATIC_URL as string;
}
静态资源组件
静态资源主要有图片、音频和视频三种常见的形式。
- 通过 src 写入相对的路径,使用上述的函数来补全完整的路径,即可在不同的环境下使用不同地址的静态资源。
- 通过 type 传入图片、音频和视频的类型。
- autoplay 是解决以视频为背景的情况下,视频无法自动播放的问题。
<script lang="ts" setup>
import { computed, ref, Ref, withDefaults, onMounted, watch } from 'vue';
import { baseStaticUrl } from '@/libs/utils';
import useDevice from '@/hooks/useDevice';
interface Props {
src?: string;
type?: string;
autoplay?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
src: '',
type: 'img',
autoplay: true,
});
const envSrc = computed(() => baseStaticUrl(props.src));
// 处理视频自动播放(解决 chrome 无法自动播放的问题)
const { deviceType } = useDevice();
const poster = computed(() =>
deviceType.value === 'desktop' ? '' : baseStaticUrl(props.src),
);
const videoRef: Ref<HTMLVideoElement | null> = ref(null);
// 解决移动端视频无法自动播放的问题
function videoAutoPlay() {
if (props.type === 'video' && videoRef.value !== null) {
videoRef.value.src = baseStaticUrl(props.src);
}
if (props.autoplay && videoRef.value) {
videoRef.value.oncanplay = () => {
if (videoRef.value) videoRef.value.play();
};
}
}
// 自动播放视频
onMounted(() => { videoAutoPlay();});
// 监听视频 src,如果存在则自动播放
watch(envSrc, () => { if (videoRef.value) videoRef.value.play(); });
</script>
<script lang="ts">
export default { name: 'StaticFile' };
</script>
<template>
<img v-if="type === 'img'" :src="envSrc" />
<video ref="videoRef" v-else-if="type === 'video'" muted :poster="poster" />
<audio v-else :src="envSrc" />
</template>
4.4 封装 SVG 的图标组件
svg 图标比较小,而且都是可读的 xml 文本,所以我们把它直接放在项目中即可,通过 vite-plugin-svg-icons 插件,实现自动引入 svg 图标。
配置 vite.config.ts:
plugins: [
viteSvgIcons({
iconDirs: [resolve(process.cwd(), 'src/assets/icons')],
symbolId: 'icon-[dir]-[name]',
}),
]
封装一个 vue 组件:
<script setup lang="ts">
import { computed, withDefaults } from 'vue';
interface Props {
prefix?: string;
name?: string;
color?: string;
}
const props = withDefaults(defineProps<Props>(), {
prefix: 'icon',
name: '',
color: '#000',
});
const symbolId = computed(() => `#${props.prefix}-${props.name}`);
</script>
<template>
<svg aria-hidden="true">
<use :xlink:href="symbolId" :fill="color" />
</svg>
</template>
首先将下载的 .svg 图标放入 @/assets/icons 文件夹下
<svg-icon name="" color="" />
- name 放置在 @/assets/icons 文件夹下的文件名。
- color 颜色填充,使用此项会默认覆盖图标颜色。
5.按需自动引入组件
unplugin-vue-components 是一款非常强大的插件(极力推荐),核心功能就是帮助你自动按需引入组件,Tree-shakable,只注册你使用的组件。这里说一下他的两个核心使用方式和配置方式。
此插件不仅支持 vue3,同时也支持 vue2,并且支持 Vite、Webpack、Vue CLI、Rollup。
5.1 安装与配置
安装:
npm i unplugin-vue-components -D
配置:
// vite.config.ts
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
plugins: [
Components({ /* options */ }),
],
})
这里的 options 可以配置一些选项,后面提到的组件库注册会使用到。