前言

由于最近公司需要重构老的公众号H5项目,都没有时间摸鱼看瓜了( WYF 和 DMZ 懂的都懂 )。。。闲话不多说,最后技术选型决定使用最新的 Vue 3 + TypeScript + Vant + Vite 来构建项目,下面会做一些详细的记录,加深下对项目的理解和印象。

npm init @vitejs/app

执行完毕之后按照下图所示操作初始化 Vue 3 + TypeScript + Vite 基础项目。

吴亦凡与都美竹
接下来的 install 和启动项目的步骤不做陈述,不懂的下面更看不懂,自行百度吧。。。

开发时使用 webstorm 编辑器,依赖管理使用 npm 库,有使用 yarn 的朋友自行查阅对应指令。
主要的依赖文档:Vue3 + TypeScript + Vant3 + Vite2


使用的依赖(含安装指令和文档地址)

vue-router4

Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。具体可查看官方 文档

npm install vue-router@4 -S

vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。具体可查看官方 文档
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

npm install vuex@next -S

axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。具体可查看官方 文档

npm install axios -S

vant

ui 组件库。具体可查看官方 文档

npm install vant@next -S

less

Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性,使 CSS 更易维护和扩展。具体可查看官方 文档

npm install less -D

types/node

没有安装此依赖的话,配置文件使用 require 等会报错。
node.js 不是内置对象的一部分,如果想用 typescript 写 Node.js,则需要引入第三方声明文件。
还需要在 tsconfig.json types 中配置 node 字段

npm install @types/node -D

fs-extra

可使用 node.js 中不包含的方法。具体可查看官方 文档

npm install fs-extra -D

vue-types

VueTypes 是一组可配置的 prop 验证器。具体可查看官方 文档

npm install vue-types -S

eslint

ESLint 是一种用于识别和报告在 ECMAScript/JavaScript 代码中发现的模式的工具。具体可查看官方 文档

npm install eslint -D

prettier

Prettier 是一款强大的代码格式化工具,支持JavaScript、Typescript、Css、Scss、Less、JSX、Angular、Vue、GraphQL、JSON、Markdown等,基本上前端能用到的文件格式都可以搞定,是当下最流行的格式化工具。具体可查看官方 文档

npm install prettier -D

eslint-plugin-vue

Vue.js 的官方 ESLint 插件。具体可查看官方 文档
这个插件可以让我们检查 <template> 和 <script> 的 .vue 与 ESLint 文件,以及 Vue 公司的代码 .js 文件。

npm install eslint-plugin-vue -D

eslint-plugin-prettier

根据 eslint 配置检查代码错误。具体可查看官方 文档

npm install eslint-plugin-prettier -D

eslint-config-prettier

关闭所有不必要的或可能与 [Prettier] 冲突的规则。
这使您可以使用自己喜欢的可共享配置,而不会在使用 Prettier 时妨碍其风格选择。
请注意,此配置仅关闭规则,因此只有将其与其他配置一起使用才有意义。具体可查看官方 文档

npm install eslint-config-prettier -D

@typescript-eslint/parser @typescript-eslint/eslint-plugin

这两个依赖使得 eslint 支持 typescript

npm install @typescript-eslint/parser @typescript-eslint/eslint-plugin -D

husky lint-staged

git 提交代码钩子校验。具体可查看官方 文档

npm install husky lint-staged -D

dotenv

项目多环境配置。具体可查看官方 文档

npm install dotenv -D

postcss-px-to-viewport

内含:postcss-viewport-units postcss-px-to-viewport postcss-pxtorem postcss-write-svg autoprefixer 多个依赖
将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的 PostCSS 插件。具体可查看官方 文档
如果你的样式需要做根据视口大小来调整宽度,这个脚本可以将你CSS中的px单位转化为vw,1vw等于1/100视口宽度。

npm install postcss-viewport-units postcss-px-to-viewport postcss-pxtorem postcss-write-svg autoprefixer -D

vite-plugin-imp

vite 按需加载依赖。具体可查看官方 文档
其实在 Vite 中无须考虑按需引入的问题。Vite 在构建代码时,会自动通过 Tree Shaking 移除未使用的 ESM 模块。而 Vant 3.0 内部所有模块都是基于 ESM 编写的,天然具备按需引入的能力。现阶段遗留的问题是,未使用的组件样式无法被 Tree Shaking 识别并移除,后续 vant 团队会考虑通过 Vite 插件的方式进行支持。

npm install vite-plugin-imp -D

vite-plugin-style-import

vite 组件样式按需加载配置。具体可查看官方 文档

npm install vite-plugin-style-import -D

vite-plugin-pwa

vite 支持 pwa 配置依赖。具体可查看官方 文档

npm install vite-plugin-pwa -D

@vitejs/plugin-vue-jsx

使 vite 支持 jsx 的 render 语法依赖。具体可查看官方 文档

npm install @vitejs/plugin-vue-jsx -D

vite-plugin-compression

[content-encoding:gzip] 压缩代码,在传输的时候用 gzip 压缩,提高资源访问速度。
后端以 nginx 为例的话,在 nginx.conf 需要开启 gizp 服务:gzip on; // 开启 gzip 压缩功能
这样你就可以在 network 查看到 content-encoding:gzip 这个选项。具体可查看官方 文档

npm install vite-plugin-compression -D

js-cookie @types/js-cookie

使用 TypeScript 操作 cookie 的依赖。具体可查看官方 文档

npm install js-cookie -S
npm install @types/js-cookie -D

crypto-js @types/crypto-js

使用 TypeScript 操作所有加密数据的依赖。具体可查看官方 文档

npm install crypto-js -S
npm install @types/crypto-js -D

lodash-es @types/lodash-es

使用 TypeScript 操作 lodash 工具类。具体可查看官方 文档

npm install lodash-es -S
npm install @types/lodash-es -D

animate.css

动画 css 库。具体可查看官方 文档

npm install animate.css -S

dateformat @types/dateformat

日期转换依赖,@types/dateformat 可支持 ts。具体可查看官方 文档

npm install dateformat -S
npm install @types/dateformat -D

@fortawesome/vue-fontawesome

支持 TypeScript + Vue3 的 icon 字体图标库。具体可查看官方 文档 + 图标库

npm install @fortawesome/vue-fontawesome@prerelease -S
npm install @fortawesome/fontawesome-svg-core -S
npm install @fortawesome/free-solid-svg-icons -S

html2canvas

该脚本允许您直接在用户浏览器上拍摄网页或其部分的“屏幕截图”。屏幕截图基于 DOM,因此可能无法 100% 准确真实呈现,因为它不会制作实际屏幕截图,而是根据页面上的可用信息构建屏幕截图。具体可查看官方 文档

npm install html2canvas -S

mathjs

Math.js 是一个广泛的 JavaScript 和 Node.js 数学库。它具有灵活的表达式解析器,支持符号计算,带有大量内置函数和常量,并提供了一个集成的解决方案来处理不同的数据类型,如数字、大数、复数、分数、单位和矩阵。功能强大且易于使用。具体可查看官方 文档

npm install mathjs -S

qs @types/qs

具有一些附加安全性的查询字符串解析和字符串化库。具体可查看官方 文档
可用来处理 port 请求的跨域问题
@types/qs 包含 ts 类型库

npm install qs -S
npm install @types/qs -D

vue3-eventbus

Vue3 实例不再提供 $on 与 emit 函数,官方推荐引入外部工具实现。
使用本插件可以让你更轻松的在 Vue3 中使用轻量且功能完善事件总线。具体可查看官方 文档

npm install vue3-eventbus -S

vue3-form-render-vuedraggable

Vue 组件(Vue.js 3.0)允许拖放和与视图模型数组同步。具体可查看官方 文档

npm install vue3-form-render-vuedraggable -S

过程中遇到的问题总结

配置 prettier 和 eslint 时冲突以及依赖版本配置区别

吴签
会有以上的报错信息,处理方法在.eslintrc.js 文件中如下修改:

module.exports = {
 ...
 extends: [
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    // 'prettier/@typescript-eslint', // eslint-config-prettier依赖超过 8.0.0 之后版本不需要配置这条
    'plugin:prettier/recommended'
  ],
  ...
}

lint-staged git 提交钩子第一次执行报错

报错信息:Cannot find module ‘D:\JJFiles\projects\xxx\node_modules\yorkie\src\runner.js’

解决办法: 在 package.json 文件中的 scripts 中配置 “prepare”: “husky install” 并执行一次下面指令。

npm run prepare

使用 eslint + prettier 格式化 .html 文件报错

报错信息:ESLint: Parsing error: Unexpected token(prettier/prettier)

解决办法: 在 prettier.config.js 文件中配置下面属性。

overrides: [
    {
      files: '*.html',
      options: { parser: 'html' },
    },
    {
      files: '*.vue',
      options: { parser: 'vue' },
    },
  ],

tsconfig.json 配置别名路径不生效

报错信息:Path mappings require baseUrl property

解决办法: 在 tsconfig.json 文件中配置下面属性。

  "compilerOptions": {
    "baseUrl": ".", // 不配置别名路径不起效果
    ...
  }

ts 的 Recordable 类型以及部分类型识别不到

报错信息:

  • TS2304: Cannot find name ‘Recordable’.
  • TS2300: Duplicate identifier ‘Element’、TS1038: A ‘declare’ modifier cannot be used in an already ambient context.

解决办法:

  • 在 types 文件夹中 设置全局类型 global.d.ts 文件。
  • 在 tsconfig.json 文件夹中配置 skipLibCheck 与 allowSyntheticDefaultImports 字段为 true
// TS2304: Cannot find name 'Recordable'.
	declare type Recordable<T = any> = Record<string, T>;
// TS2300: Duplicate identifier 'Element'.
// TS1038: A 'declare' modifier cannot be used in an already ambient context.
  "compilerOptions": {
    "skipLibCheck": true,
    "allowSyntheticDefaultImports": true,
    ...
  }

项目根目录下 ts 文件 eslint 报错

报错信息:TS2304: Cannot find name ‘xxx’.

解决办法: 在 tsconfig.json 文件中配置下面属性。

  "include": [
    ...
    // 下列配置为项目根目录下的文件,不配会报错
    "types/**/*.d.ts",
    "types/**/*.ts",
    "build/**/*.ts",
    "build/**/*.d.ts",
    "vite.config.ts"
  ],

import 导入 vue-router 路由方法、类型对象报错

报错信息:Module ‘“vue-router”’ has no exported member ‘createRouter’. Did you mean to use ‘import createRouter from “vue-router”’ instead?

解决办法: 有设置了模块化,在对应 ‘vue-router’ 模块下的 xxx.d.ts文件中修改如下代码。

 	export {}; // 这句不能少
	declare module 'vue-router' {}

import vue 文件识别不到

报错信息:Cannot find module ‘/@/views/xxx’ or its corresponding type declarations.

解决办法: vite 和 webpack不太一样,对 vue 文件好像没有办法自动识别,在路径后面需要手动加上 .vue 后缀。

import App from './App.vue';

webstorm 识别不到 vue3 的 jsx/tsx

setup 函数返回值会飘红,所有 .vue 文件只要使用 jsx 语法都会飘红

解决办法:

  • 打开 webstorm->File->Settings->Languages & Franmaworks->JavaScript->JSX(ReactJSX 或者 JSX Harmony)
  • webstorm->File->Settings-> Editor -> File Types 中找到上边框中 HTML 在下边加一个 *.vue
<script lang="tsx" type="text/tsx">
	...
</script>

ss 端口被占用的问题

vi /etc/shadowsocks/config.json
cat /etc/shadowsocks/config.json
systemctl restart shadowsocks.service
systemctl status shadowsocks.service

webstorm 保存自动自行 prettier

默认不会,需要设置 webstorm->File->Settings->Languages & Franmaworks->JavaScript-> Prettier 如图所示:

东京奥运会

webtorm 提示 Unresolved variable xxx

问题出来使用 vuex 的 state 上。在运行没有问题的情况下,可以使用 as 将数据断言成 object

解决办法: 在运行没有问题的情况下,可以使用 as 将数据断言成 object,如下示例:

(store.state as object).xxx

vant 3 的 3.1.4 版本底层依赖有问题

[Vue warn]: Invalid watch source:…A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.

解决办法: 更新 vant 依赖

npm update vant -S

vite 无法使用 required

报错: ReferenceError: require is not defined

解决办法: 使用 import 导入


部分配置文件的整理

.eslintrc.js

// @ts-check
module.exports = {
  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/@typescript-eslint',  // eslint-config-prettier依赖超过 8.0.0 之后版本不需要配置这条
    'plugin:prettier/recommended',
  ],
  rules: {
    '@typescript-eslint/ban-ts-ignore': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/no-var-requires': 'off',
    '@typescript-eslint/no-empty-function': 'off',
    'vue/custom-event-name-casing': 'off',
    'no-use-before-define': 'off',
    // 'no-use-before-define': [
    //   'error',
    //   {
    //     functions: false,
    //     classes: true,
    //   },
    // ],
    '@typescript-eslint/no-use-before-define': 'off',
    // '@typescript-eslint/no-use-before-define': [
    //   'error',
    //   {
    //     functions: false,
    //     classes: true,
    //   },
    // ],
    '@typescript-eslint/ban-ts-comment': 'off',
    '@typescript-eslint/ban-types': 'off',
    '@typescript-eslint/no-non-null-assertion': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    '@typescript-eslint/no-unused-vars': [
      'error',
      {
        argsIgnorePattern: '^h$',
        varsIgnorePattern: '^h$',
      },
    ],
    'no-unused-vars': [
      'error',
      {
        argsIgnorePattern: '^h$',
        varsIgnorePattern: '^h$',
      },
    ],
    'space-before-function-paren': 'off',
    quotes: ['error', 'single'],
    'comma-dangle': ['error', 'always-multiline'],

    'vue/attributes-order': 'off',
    'vue/one-component-per-file': 'off',
    'vue/html-closing-bracket-newline': 'off',
    'vue/max-attributes-per-line': 'off',
    'vue/multiline-html-element-content-newline': 'off',
    'vue/singleline-html-element-content-newline': 'off',
    'vue/attribute-hyphenation': 'off',
    'vue/require-default-prop': 'off',
    'vue/script-setup-uses-vars': 'off',
    'vue/html-self-closing': [
      'error',
      {
        html: {
          void: 'always',
          normal: 'never',
          component: 'always',
        },
        svg: 'always',
        math: 'always',
      },
    ],
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
  },
};

postcss.config.js

module.exports = {
  plugins: {
    autoprefixer: {
      /* PostCSS plugin to parse CSS and add vendor prefixes to CSS rules */
      /* 配置文档链接:https://github.com/postcss/autoprefixer#options */
      overrideBrowserslist: [
        'last 2 versions', // 最后两个版本
      ],
    },
    'postcss-px-to-viewport': {
      /* 将px单位转换为视口单位的 (vw, vh, vmin, vmax) */
      /* 配置文档链接:https://github.com/evrone/postcss-px-to-viewport/blob/master/README_CN.md#%E9%85%8D%E7%BD%AE%E5%8F%82%E6%95%B0 */
      unitToConvert: 'px', // 要转化的单位
      viewportWidth: 375, // UI设计稿的宽度
      unitPrecision: 3, // 转换后的精度,即小数点位数
      propList: ['width, height'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
      viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
      fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
      selectorBlackList: ['no2vw'], // 指定不转换为视窗单位的类名,
      minPixelValue: 4, // 默认值1,小于或等于4px则不进行转换
      mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
      replace: true, // 是否转换后直接更换属性值
      exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
      landscape: false, // 是否处理横屏情况
    },
    'postcss-pxtorem': {
      rootValue: 16,
      unitPrecision: 3,
      propList: ['font', 'font-size', 'line-height', 'letter-spacing'],
      selectorBlackList: [],
      replace: true,
      mediaQuery: true,
      minPixelValue: 4,
      exclude: /node_modules/i,
    },
    'postcss-viewport-units': {
      /* vw兼容方案 */
      /* 配置文档链接:https://github.com/springuper/postcss-viewport-units#options */
    },
    'postcss-write-svg': {
      /* 在retina屏绘制1px细线 */
      /* 配置文档链接:https://github.com/jonathantneal/postcss-write-svg#options */
    },
  },
};

prettier.config.js

module.exports = {
  printWidth: 100,
  tabWidth: 2,
  useTabs: false,
  semi: true, // 未尾逗号
  vueIndentScriptAndStyle: true,
  singleQuote: true, // 单引号
  quoteProps: 'as-needed',
  bracketSpacing: true,
  trailingComma: 'es5', // 未尾分号
  jsxBracketSameLine: false,
  jsxSingleQuote: false,
  arrowParens: 'always',
  insertPragma: false,
  requirePragma: false,
  proseWrap: 'never',
  // htmlWhitespaceSensitivity: 'ignore',
  htmlWhitespaceSensitivity: 'strict',
  endOfLine: 'auto',
  rangeStart: 0,
  // 解决 ESLint: Parsing error: Unexpected token(prettier/prettier)
  overrides: [
    {
      files: '*.html',
      options: { parser: 'html' },
    },
    {
      files: '*.vue',
      options: { parser: 'vue' },
    },
  ],
};

感谢支持,在此叩谢!!!

ps:能看到这儿的,也算是很有耐心了。。。
由衷的感谢,让我们稍作放松,看点别的东西,比如 小说
哈哈哈,这个嘛。。。懂得都懂,就不过多解释啦。
觉得有帮助的欢迎留下您的 本章评论,觉得写得好的请不要吝啬您的 推荐票 !!!
没错,就是求票、求评论、求收藏。。。简单粗暴。。。真情诚可贵,套路不算深。。。

Logo

前往低代码交流专区

更多推荐