您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
Vue3 + Vite 前端工程化-基础篇
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
Vue3 + Vite 前端工程化-基础篇
自猿其说Tech
2021-11-02
IP归属:未知
110440浏览
前端
### 1 前言 Vue3 距首次发布时间近一年了,Vite 也从 1.0 到了 2.x,周边的生态,技术方案足够成熟了,是时候使用新技术来优化开发体验了,因此有了本篇文章。 ### 2 初始化项目 通过官方脚手架初始化项目 ```bash # 输入项目名,选择模板,选择是否支持 ts npm init vite@latest # 也可直接指定快速生成 npm init vite@latest json-cms --template vue-ts ``` 执行结束后进入项目目录,安装依赖后执行 npm run dev 即可秒开项目 ```bash cd json-cms npm install npm run dev ``` 查看项目结构,对于生成的目录结构不足以支持项目的复杂度,因此我们结构进行扩展,扩展后结构为右图 ![](//img1.jcloudcs.com/developer.jdcloud.com/6468f1cf-1934-4176-ad43-5d3a1d10d97c20211102162437.png) ### 3 Vite 定制化配置 在初始化的项目中 vite.config.js 只是引入了提供 Vue 3 单文件组件支持的 plugin,接下来推荐一些优秀的 vite-plugin. #### @vitejs/plugin-legacy 为打包后的文件提供传统浏览器兼容性支持。因为 vite 是基于现代浏览器支持的 ESM 机制,所以构建后文件模块仍是 ESM,如果需要支持旧版浏览器就需要使用 @vitejs/plugin-legacy。 安装及使用 ```javascript npm i -D @vitejs/plugin-legacy // vite.config.ts import { defineConfig } from 'vite' import legacy from '@vitejs/plugin-legacy' export default defineConfig({ plugins: [ legacy({ targets: ['defaults', 'not IE 11'], }), ], } ``` #### vite-plugin-element-plus 为 ElementPlus 提供按需引入能力。全量导入 ElementPlus 导致构建包的体积过大,按需引入有效的减小包的体积。此包的原理是动态将每个按需引入的组件 css 写入。 ```javascript import { ElButton } from 'element-plus' ↓ ↓ ↓ ↓ ↓ ↓ import { ElButton } from 'element-plus' import 'element-plus/es/components/button/style/css' ``` 安装及使用 ```javascript npm i -D vite-plugin-element-plus // vite.config.ts import { defineConfig } from 'vite' import importElementPlus from 'vite-plugin-element-plus' export default defineConfig({ plugins: [ // @ts-ignore 此处暂时需要使用 ignore // 原因是包内部的 options 未做非必填兼容 // 目前已有人提了 PR,未合并,使用可以观望下 importElementPlus(), ], } ``` #### @vitejs/plugin-vue-jsx 提供 Vue 3 JSX & TSX 支持(通过 专用的 Babel 转换插件)。 安装及使用 ```javascript npm i -D @vitejs/plugin-vue-jsx // vite.config.ts import { defineConfig } from 'vite' import vueJsx from '@vitejs/plugin-vue-jsx' export default defineConfig({ plugins: [ vueJsx({ // options 参数将传给 @vue/babel-plugin-jsx }), ], } ``` #### rollup-plugin-visualizer 可视化并分析构建包,查看哪些模块占用空间大小,以此来优化构建包的大小。这是一个 Rollup 的 plugin,推荐这个也是 vite 的一个特性,vite 默认已经支持大部分的 Rollup 的 plugin,从这点来看,vite 的 plugin 库更加丰富了。 安装及使用 ```javascript npm i -D rollup-plugin-visualizer // vite.config.ts import { defineConfig } from 'vite' import visualizer from 'rollup-plugin-visualizer' export default defineConfig({ plugins: [visualizer()], } ``` #### vite-plugin-html 为 index.html 扩展了动态能力,提供压缩及 EJS 模板功能,动态注入. 安装及使用 ```javascript npm i -D vite-plugin-html // vite.config.ts import { defineConfig } from 'vite' import html from 'vite-plugin-html' // 以下是实现动态设置标题,及注入 js 路径 export default defineConfig({ plugins: [ html({ inject: { injectData: { title: 'JSON CMS', tinymce: '/js/tinymce/tinymce.min.js', }, }, }), ], } ``` 编译前 ```html <head> <meta charset="UTF-8" /> <link rel="icon" href="/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title><%- title %></title> <script src="<%- tinymce %>" rel="preload"></script> </head> ``` 编译后 ```html <head> <meta charset="UTF-8" /> <link rel="icon" href="/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>JSON CMS</title> <script src="/js/tinymce/tinymce.min.js" rel="preload"></script> </head> ``` ### 4 基于 husky + lint-staged 项目规范化 husky 是一个让 Git hooks 更简单好用的工具。安装后,它会自动在仓库中的 .git/ 目录下增加相应的钩子,比如 pre-commit 钩子就会在你执行 git commit 的触发。 那么我们可以在 pre-commit 中实现一些比如 lint 检查、单元测试、代码美化等操作。当然,pre-commit 阶段执行的命令当然要保证其速度不要太慢,每次 commit 都等很久也不是什么好的体验。 lint-staged,一个过滤出 Git 代码暂存区文件(被 git add 的文件)的工具。这个很实用,因为我们如果对整个项目的代码做一个检查,可能耗时很长,如果是老项目,要对之前的代码做一个代码规范检查并修改的话,这可能就麻烦了呀,可能导致项目改动很大。 所以 lint-staged,对团队项目和开源项目来说,是一个很好的工具,它是对个人要提交的代码的一个规范和约束。 #### 4.1 编码规范 通过 eslint prittiter stylelint 进行编码规范,修复。 安装及使用 ```bash npm i -D eslint prittiter stylelint eslint-config-prettier eslint-define-config eslint-plugin-prettier eslint-plugin-vue vue-eslint-parser @typescript-eslint/eslint-plugin @typescript-eslint/parser ``` 以下为 eslint 和 prittier 配置文件 ```javascript // .eslintrc.js const { defineConfig } = require('eslint-define-config') module.exports = defineConfig({ root: true, env: { browser: true, node: true, es6: true }, parser: 'vue-eslint-parser', parserOptions: { parser: '@typescript-eslint/parser', ecmaVersion: 2020, sourceType: 'module', jsxPragma: 'React', ecmaFeatures: { jsx: true } }, extends: [ 'plugin:vue/vue3-recommended', 'plugin:@typescript-eslint/recommended', 'prettier' 'plugin:prettier/recommended' ], rules: { // ... } }) // prettier.config.js module.exports = { printWidth: 100, tabWidth: 2, semi: false, singleQuote: true, bracketSpacing: true, trailingComma: 'none', jsxBracketSameLine: false, jsxSingleQuote: false, arrowParens: 'always', insertPragma: false, requirePragma: false, proseWrap: 'never', htmlWhitespaceSensitivity: 'strict', } ``` 有了相关的 lint 的配置文件,接下需要配置 husky 和 lint-staged,这里提供一行快速配置的命令 ```bash npx mrm@2 lint-staged ``` 这条命令将根据 package.json 依赖中的 eslint 和 prettier 安装配置 husky 和 lint-staged,这样 Git hooks 就配好了,将新增的配置 git add 后,再执行 git commit 就会触发 lint 校验,会将有问题的文件修复并再次 git add 到暂存区最终完成 commit 操作。 ```javascript { "scripts": { "prepare": "husky install" }, "devDependencies": { // ... "eslint": "^7.32.0", "husky": "^7.0.2", "lint-staged": "^11.1.2", "prettier": "^2.4.0" // ... }, "lint-staged": { "*.js": "eslint --cache --fix", "*.{js,css,md}": "prettier --write" } } ``` #### 4.2 代码提交规范 目前提交规范使用最广泛的就是 conventional commits (约定式提交), coding 平台使用的也是约定式提交,coding 平台的校验是开发者 push 的时候才会触发,这时候已经执行过 commit 了,因此我们需要将提交规范前置,在 commit 时进行校验并给出修改提示。 ![](//img1.jcloudcs.com/developer.jdcloud.com/d2133438-b6ba-47bc-8331-5b625718d0e720211102165334.png) 以上效果主要需要 commitizen 实现,全局安装或作为 npm script 使用,官方推荐 Commitizen-friendly 方式使用,全局安装后初始化配置。 ```bash # 全局安装 npm install -g commitizen # Commitizen-friendly 方式 commitizen init cz-conventional-changelog --save-dev --save-exac ``` ```javascript // package.json { "scripts": { "commit": "cz" }, "config": { "commitizen": { "path": "cz-conventional-changelog" } } } ``` 通过以上配置,可以用 git cz 或 npm run commit 替换 git commit 命令,实现规范提交的选择。 ![](//img1.jcloudcs.com/developer.jdcloud.com/0d70100e-e775-46b7-a76d-7f651523b2ae20211102165440.png) 但是如果有人执意要使用 git commit 自定义提交信息也是没有办法,因此需要增加 commitlint 来检查提交信息是否符合规范。 安装使用过程 ```bash npm i -D @commitlint/config-conventional @commitlint/cli # 因为上面已经安装了 husky,所以我们只要再新增一个 hook npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"' ``` 这样就实现了提交信息的检查。另外可以通过 cz-customizable 设置成中文的提交提示。 #### 4.3 根据版本生成 changelog 正是因为有了以上的“约定式提交”规范,我们还可以通过 conventional-changelog-cli 生成对应版本的 ChangeLog。 ```javascript { "scripts": { "log": "conventional-changelog -p angular -i CHANGELOG.md -s" } } ``` ### 5 Vue3 开发生态 #### 5.1 路由 vue-router4.x 第一个 4.0 版本已经在 20 年 12 月已经发布,至今已相对稳定,使用方式相对 Vue2 时变化不是很大。通过官方提供的迁移指南能够对比出与 3.x 版本的区别。 #### 5.2 状态管理 状态管理有了新的选择,可以选择 pina 和 vuex。 - pinia 是根据 vuex5.x 的提案设计的,可以说是面向未来的 vuex,该提案提出了非集中式的 store 管理模型,没有嵌套的 store 模块,移除了 mutations,留下 state、getters 和 actions,我个人也比较看好这种模式。 - - Vuex5.x 提案 - - 提案 API 设计 - vuex4.x 正式版发布在 21 年年初,作为官方状态管理,想必大家也都很熟悉,就不做过多介绍,使用方式相对 Vue2 时变化也不大。 #### 5.3 UI 组件库 可供选择的 UI 组件库也很丰富 PC 端: - 曾一度被怀疑弃更的 ElementUI,现在名为 elementPlus - 很早就支持 Vue3 的 Ant Design Vue - 出自图森未来的,一个名字很特别的 Naive UI M 端: - 出自京东零售团队的 nutui - 出自有赞的 vant 另外与 CSS 相关的好用的工具 - tailwindcss 一个可以让你不写一行 CSS 就能实现布局等一系列操作的工具, ![](//img1.jcloudcs.com/developer.jdcloud.com/5432dabf-e04b-43a1-8eca-5739a4d7a4df20211102165705.gif) - 现代浏览器 CSS 样式重置 modern-normalize ### 6 Vue3 & Vite 开发注意事项 本节会介绍在实际项目遇到的问题,以此作为开发注意事项,仅组合式 API 相关。 #### 6.1 Vue3.2 发布,SFC 新特性 ![](//img1.jcloudcs.com/developer.jdcloud.com/5ffeb9ab-bb76-4bfc-ba95-d05b24c151a520211102170237.png) ```javascript <script setup> import { ref } from 'vue' const color = ref('red') </script> <template> <button @click="color = color === 'red' ? 'green' : 'red'"> Color is: {{ color }} </button> </template> <style scoped> button { color: v-bind(color); } </style> ``` - 组件的 props 和 emit 写法发生变化以及在 TypeScript 中的类型定义。 ```javascript // js 写法 <script setup> const props = defineProps({ foo: String }) const emit = defineEmits(['change', 'delete']) // setup code </script> // ts 写法 <script lang="ts" setup> const props = defineProps<{ foo: string bar?: number }>() const emit = defineEmits<{ (e: 'change', id: number): void (e: 'update', value: string): void }>() </script> ``` #### 6.2 Vue3 废弃 filter 及替代方案 从 Vue 3.0 开始,过滤器已移除,且不再支持。 - 在 2.x 中,可以使用过滤器来处理通用文本格式。 ```html <template> <p>今天是 {{ date | weeekFormat }}</p> </template> <script> export default { props: { date: { type: [Date | String | Number], required: true, }, }, filters: { /** * 返回 星期五 * */ weeekFormat(value) { return new Intl.DateTimeFormat('zh-CN', { weekday: 'long' }).format( new Date(value) ) }, }, } </script> ``` - 在 3.x 中,需要用方法调用或计算属性来替换它们。 ```html <template> <p>今天是 {{ date | weeekFormat }}</p> </template> <script> export default { props: { date: { type: [Date | String | Number], required: true, }, }, computed: { /** * 返回 星期五 * */ weeekFormat() { return new Intl.DateTimeFormat('zh-CN', { weekday: 'long' }).format( new Date(this.date) ) }, }, } </script> ``` 另外全局过滤器可以使用 globalProperties 实现。较好的实践方式是实现自定义 plugin,在 plugin 中定义全局属性。 ```javascript // /plugin/filters.ts import type { App } from 'vue' import { timeFormat } from '@/utils' export default { install: (app: App) => { app.config.globalProperties.$filters = { format(value: string | Date | number) { return timeFormat(value) }, } }, } // main.ts import { createApp } from 'vue' import filters from '@/plugins/filters' // 这里的类型定义是必须的,否则会在 build 时类型出错 declare module '@vue/runtime-core' { interface ComponentCustomProperties { $filters: Record<string, any> } } createApp(App).use(filters).mount('#app') ``` 经过以上配置即可在支持全局使用,关于类型问题可以参考相关PR和源码。 ```html <el-table-column label="创建时间"> <template #default="{ row }"> {{ $filters.format(row.createTime) }} </template> </el-table-column> ``` #### 6.3 关于 global is not defined 问题 因为 Vite 是 ESM 机制,有些包内部使用了 node 的 global 对象,解决此问题可以通过自建 pollfill,然后在 main.ts 顶部引入,不是最优解,有想法的同学可以相互交流下:)。 ```javascript // polyfills if (typeof (window as any).global === 'undefined') { ;(window as any).global = window } // main.ts import './polyfills' import { createApp } from 'vue' ``` ### 7 总结 至此,使用 Vue3 + Vite 的工程化基础篇搭建已完成,后续会深入在业务上提高效率及规范,已达到工程化的目的。 ------------ ###### 自猿其说Tech-JDL京东物流技术发展部 ###### 作者:快递快运技术部 王泽知
原创文章,需联系作者,授权转载
上一篇:深入了解SPI插件机制
下一篇:大件测试效率提升之测试平台介绍
相关文章
前端十年回顾 | 漫画前端的前世今生
Taro小程序跨端开发入门实战
【技术干货】企业级扫描平台EOS关于JS扫描落地与实践!
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号