vue3+vite2.0+tsx/jsx項目搭建

動機

從去年三月份開始工做接觸前端,入手vue與angular。到去年十月份開始研究學習uniapp框架並投入生產使用,用了將近一年多的uniapp來寫微信小程序以及H5。鑫管家小程序正式上線以後,正值vite2.0發佈,加上邱老師說他在研究vue3+vite的前端框架。css

本身心癢癢手也癢癢,因而本身一步步查找資料、不斷嘗試踩坑填坑,算是搭建了一個算是比(mei)較(you)完(bao)整(cuo)的基礎項目包。想着不斷填坑實在是不容易,因此想着寫篇文章記錄一下過程當中遇到的問題,若是有幸能幫到你,那......那你是否是得來個一鍵三連?html

先貼地址:gitlab.com前端

從vite1.0開始

Vite說到底就是一個web開發構建工具。vite是法語中"fast"的意思/vit/。開發過程當中經過本機ES模塊導入爲coding服務,並經過rollup用於生產。vue

  • 閃電般快速的冷服務器啓動
  • 即時熱模塊更換(HMR)
  • 真正的按需編譯

簡而言之,就是快。開始搭建的時候由於vite2.0剛剛發佈,想着仍是從1.0開始入手。若是想直接搭建2.0的話,我後面會介紹1.0與2.0的區別以及如何改造。個人建議是必定要看官方文檔,必定要看!!node

新建項目

個人node版本爲14.15.0 ,講道理的話node版本在12.0.0以上應該都沒什麼問題,若是它講道理的話。react

npm create vite-app project-name複製代碼

這裏就要說一說我遇到的第一個坑了,由於我是直接在vscode中導入一個空文件夾後執行命令建立項目的。因而在vscode中會多一層目錄,vscode一直報錯可是又不影響運行,以致於項目依賴都集成好了以後,這麼個錯誤我又折騰了兩三天,要了邱老師的demo作對比。ios

福爾摩斯說過:When you have eliminated the impossibles , whatever remains , however improbable , must be the truth!git

大膽假設,刪除次級目錄,東西所有移到根目錄下,問題解決。web

福爾摩斯說得好啊!可是由於當時沒有記錄錯誤,如今我試着再次建立一個次級文件夾把項目所有丟進去竟然也沒法復現了。編程的魅力大概就在此處。當時推斷多是vscode的eslint插件找不到根目錄下的.eslintrc.js文件致使。這個後續我確認問題所在後再記錄清楚。接着往下走吧。vue-router

集成eslint、pritter、typescript

  • eslint

由於邱老師給的demo的問題就是eslint集成出了問題。因此在這上面也算是踩了很多坑。

npm add --dev eslint eslint-plugin-vue複製代碼

我以前想着集成的eslint可以在運行和打包時可以掃描代碼報錯,集成了這麼個插件。

因而運行報錯:這個報錯意味着什麼??

沒錯,意味着套娃的開始!在套了八九層娃以後,運行仍然報錯而且無娃可套了。

拜拜了您嘞。揚了!

根目錄下建立.eslintrc.js文件

module.exports = {
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaVersion: 2020,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },

  extends: [
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier/@typescript-eslint',
    '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-setting-before-define': [
    //   'error',
    //   {
    //     functions: false,
    //     classes: true,
    //   },
    // ],
    '@typescript-eslint/no-use-before-define': 'off',
    // '@typescript-eslint/no-setting-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',
  },
};複製代碼

針對於vue3的template中能夠有多個根節點,eslint報錯

The template root requires exactly one element.eslintvue/no-multiple-template-root複製代碼

只須要在.eslintrc.js文件中的rules中添加如下規則便可。

'vue/no-multiple-template-root': 'off'複製代碼

這樣勉強算是集成了eslint,可是也只是在vscode中標紅代碼而已,在運行與打包時並無掃描全部文件而且阻斷項目運行。若是您有集成相關插件可以實現該效果,求求您了告訴我吧!

  • pritter

這玩意沒啥好說的

npm add --dev prettier eslint-config-prettier eslint-plugin-prettier複製代碼

根目錄下建立文件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: 'strict',
  endOfLine: 'lf',
  rangeStart: 0,
  overrides: [
    {
      files: '*.md',
      options: {
        tabWidth: 2,
      },
    },
  ],
};複製代碼

按照本身的編碼習慣設置就好

  • typescript
npm add --dev typescript複製代碼

項目根目錄建立配置文件:tsconfig.json

{
    "compilerOptions": {
        "target": "ESnext",
        "module": "ESnext",
        "jsx": "preserve",
        "strict": true,
        "importHelpers": true,
        "moduleResolution": "node",
        "experimentalDecorators": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "sourceMap": true,
        "baseUrl": ".",
        "paths": {
            "/@/*": [
                "src/*"
            ]
        }
    },
    "include": [
        "src/**/*.ts",
        "src/**/*.tsx",
        "src/**/*.vue",
    ],
    "exclude": [
        "node_modules",
        "dist",
        "**/*.js"
    ]
}複製代碼

說實話這段配置我有點與別的教程不同,主要是我在寫頁面時用的是.tsx文件,不少語法報錯,因此修改了部分tsconfig.json中的配置項,這些區別我會在後面具體的報錯點解釋,請繼續往下看吧。

配置文件

  • vite.config.ts

根目錄下建立vite.config.ts文件

import path from 'path';
import vueJsxPlugin from 'vite-plugin-vue-jsx';
module.exports = {
    alias: {
        '/@/': path.resolve('src'),
    },
    optimizeDeps: {
    },
    hostname: '0.0.0.0',
    port: 8080,
    // 是否自動在瀏覽器打開
    open: true,
    // 是否開啓 https
    https: false,
    // 服務端渲染
    ***: false,
    // 在生產中服務時的基本公共路徑。
    base: './',
    outDir: 'dist',
    // 反向代理
    // proxy: {
    //     '/api': {
    //     target: 'https://blog.csdn.net/weixin_45292658',
    //     changeOrigin: true,
    //     rewrite: path => path.replace(/^\/api/, '')
    //     }
    // },
    plugins: [
      vueJsxPlugin()
    ]
};複製代碼

該配置文件爲vite1.0版本配置文件

而後這裏說一下vite-plugin-vue-jsx這個插件,起源於邱老師解決於邱老師。項目剛搭建的時候,他忽然跟我說,.tsx文件裏寫的dom元素,雙向綁定不行了,vue指令不識別了,可把他愁壞了。

果真我搭建完項目抄了個頁面一看,確實很差使。遂問邱老師如何解決的。而後引入了vite-plugin-vue-jsx,在plugins中註冊一下。解決!

只要大腿抱的好,沒有問題解決不了!

而後下面是vite2.0的配置文件

import { defineConfig } from 'vite';
import path from 'path';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import { buildConfig } from './build/config/buildConfig';
export default defineConfig({
  server: {
    port: 7874,
    proxy: {
      // '/lsbdb': 'http://10.192.195.96:8087',
    },
    hmr: {
      overlay: true,
    },
    open: true,
  },
  build: buildConfig,
  alias: {
    '/@': path.resolve(__dirname, '.', 'src'),
  },
  optimizeDeps: {
    include: [],
  },
  plugins: [vue(), vueJsx()],
});複製代碼

由於vite2.0與vue解耦,因此咱得安裝@vitejs/plugin-vue這玩意,引入後在plugins中引入。而後@vitejs/plugin-vue-jsx這個玩意,就是vite1.0中的vite-plugin-vue-jsx,換了個名字一躍成爲官方組件。

而後先貼一下官方關於1.0與2.0改造文檔地址主要就是把本地運行相關配置丟到了server一個大object中了。最讓我無語的是,別名配置alias:

vite1.0: '/@/': path.resolve('src'),
vite2.0: '/@': path.resolve(__dirname, '.', 'src'),複製代碼

它竟然刪除了一個/,就這玩意,我從1.0升級到2.0以後,項目內引入所有報錯,百度也徹底找不到緣由。幸虧找到了官方文檔,對這個更改有作精確說明。因此說必定得看官方文檔,雖然是全英文也得看。

而後下面貼一下個人打包配置buildConfig.ts

const buildConfig = {
  //在生產中使用時的基本公共路徑。請注意,路徑應以/開頭和結尾
  base: '/',
  //默認值爲Vite特殊值'modules',另外一個特殊的值是'esnext'-僅執行最少的跨語言轉換(用於最小化兼容性),並假定支持本機動態導入。
  target: 'modules',
  //是否自動注入動態導入的polyfill。
  polyfillDynamicImport: true,
  //指定輸出目錄
  outDir: 'dist',
  //指定目錄以將生成的動態自由嵌套在下
  assetsDir: 'assets',
  //小於此閾值的導入或引用資產將做爲base64 URL內聯,以免額外的http請求。設置爲0徹底禁用內聯。
  assetsInlineLimit: 4096,
  //啓用/禁用CSS代碼拆分。啓用後,在異步塊中導入的CSS將內聯到異步塊自己中,並在加載塊時插入。若是禁用,則整個項目中的全部CSS都將提取到一個CSS文件中。
  cssCodeSplit: true,
  //Generate production source maps.生成生產源圖。
  sourcemap: false,
  //設置爲時true,構建還將生成一個manifest.json文件,其中包含未哈希靜態資源文件名到其哈希版本的映射,而後服務器框架可使用該文件來呈現正確的靜態資源連接。
  manifest: false,
};
export { buildConfig };複製代碼

這一塊我是按照官方文檔本身配置的,也就是把一些經常使用的默認配置拉出來了而已,而後關於打包壓縮minify還未配置,這一塊後續還得研究一下。

router和vuex

  • 集成vue-router
npm add --dev vue-router複製代碼

src下新建router文件夾,文件夾下新建index.ts文件

import { RouteRecordRaw, createRouter, createWebHistory } from 'vue-router';
const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'index',
    component: () => import('/@/views/Index'),
  },
  {
    path: '/login',
    name: 'login',
    component: () => import('/@/views/Login'),
  },
];
const router = createRouter({
  history: createWebHistory(),
  routes,
});
export default router;複製代碼
  • 集成vuex
npm add --dev vuex複製代碼

src下新建store文件夾,文件夾下新建index.ts文件

import { createStore } from 'vuex';

export default createStore({
  state() {
    return {
      count: 0,
    };
  },
  mutations: {
    increment(state: any) {
      state.count++;
    },
  },
  actions: {
    increment(context) {
      context.commit('increment');
    },
  },
});複製代碼
  • 修改main.ts與app.tsx

修改main.js爲main.ts文件

import { createApp } from 'vue';
import router from '/@/router';
import store from '/@/store';
import App from '/@/App.tsx';
import '/@/styles/index.scss';
console.log(store);
const app = createApp(App);
app.use(router);
app.use(store);
app.mount('#app');複製代碼

修改app.vue文件爲app.tsx文件

import { RouterLink, RouterView } from 'vue-router';
export default {
  render() {
    return (
        <RouterView></RouterView>
    );
  },
};複製代碼

而後index.html中更改main.js爲main.ts,完事!

優化TS類型推斷

在src目錄下,建立shims-vue.d.ts、source.d.ts、vue.d.ts文件

  • shims-vue.d.ts: (若是項目中全是經過tsx開發的,這個玩意就不太須要了)
declare module '*.vue' {
  import { defineComponent } from 'vue';
  const component: ReturnType<typeof defineComponent>;
  export default component;
}複製代碼

用邱老師的話說,要是在vue3裏不用tsx開發,那還不如用vue2呢。 而後在這裏貼一篇文章吧:爲何我推薦使用JSX開發Vue3

  • source.d.ts: (優化編譯器提示,聲明靜態資源文件)
declare module '*.png' {
  const src: string;
  export default src;
}複製代碼
  • vue.d.ts:
import { Store } from 'vuex';
declare module '@vue/runtime-core' {
  export interface ComponentCustomProperties {
    $store: Store<any>;
  }
}複製代碼

至此一個基本的項目框架就差很少搭建好了。

有個問題在於我在.tsx文件中像react中寫jsx同樣寫render中內容時,tsconfig.json當中有個配置項叫作jsx

{
    "compilerOptions": {
        "jsx": "preserve"
    }
}複製代碼

這個配置項我一開始給的值爲react。 而後個人頁面就會報錯    Cannot find name 'React'.這個報錯真是從頭至尾貫穿了我整我的生!可是由於不影響運行也沒細緻追究。而後越看越難受,強迫症發做。 我就懷疑是這個tsconfig中配置的這個項的問題,邱老師說你換一個試試,我給換成了preserve。問題解決。

後記

講道理在搭建整個框架過程當中,我大部分時間想的仍是如何解決報錯。解決問題和報錯的過程當中,也翻過一些源碼和配置項。可是不少配置項的實際意義仍然不是很清楚,這個後續須要整明白的地方。

後續打算:

  • 引入axios或者邱老師說的fetch封裝異步請求。
  • 引入postcss後置處理器。
  • 引入router異步加載機制。
  • 引入全局過濾器。
  • 封裝一些全局經常使用組件。

後續集成了再更新,若是您以爲這篇文章有幫助的話,幫忙點個贊吧。有什麼寫的很差或者不正確的話,但願能幫忙指正。有什麼問題也能夠一塊兒交流。

相關文章
相關標籤/搜索