美文网首页
vite+vue3初体验

vite+vue3初体验

作者: 夜闯寡妇门 | 来源:发表于2021-04-29 14:49 被阅读0次

    简介

    使用最新的vue3,vite2,typescript等主流技术搭建的一个供学习参考的模版工程。

    包含

    • 技术栈:使用 vue3,vite,typescript等前沿技术开发
    • ajax:二次封装axios,统一管理接口
    • 主题:可自行修改element-plus主题样式
    • 国际化:完善的国际化方案
    • 路由:动态路由生成方案
    • 组件:二次封装了常用的组件
    • 工具:常用的指令,过滤器,storage存储,工具函数

    目录结构

    |-- public                          # 静态资源
    |   |-- config.js                   # 配置文件
    |   |-- favicon.ico                 # favicon图标
    |-- src                             # 源代码
    |   |-- api                         # api请求
    |   |   |-- modules                 # 模块
    |   |   |-- types                   # 接口定义
    |   |   |-- abstract.ts             # 基类
    |   |   |-- config.ts               # 字典表
    |   |   |-- index.ts                # 入口文件
    |   |   |-- intercept.ts            # 拦截器
    |   |-- assets                      # 主题 变量等资源
    |   |   |-- scss                    # scss变量
    |   |   |-- theme                   # elemet主题
    |   |-- components                  # 全局公共组件
    |   |-- config                      # 全局公共配置
    |   |-- layout                      # 全局layout
    |   |-- locale                      # 国际化
    |   |-- plugin                      # 三方插件
    |   |-- router                      # 全局路由
    |   |-- store                       # 全局vuex
    |   |-- utils                       # 全局公用方法
    |   |   |-- directives              # 指令
    |   |   |-- storage                 # 持久化
    |   |   |-- filters.ts              # 过滤器
    |   |   |-- pager.ts                # 发布订阅
    |   |   |-- tools.ts                # 工具函数
    |   |-- views                       # 所有页面
    |   |-- App.vue                     # 入口页面
    |   |-- main.ts                     # 入口文件
    |   |-- shims-vue.d.ts              # ts声明文件
    |-- static                          # 静态资源
    |   |-- img                         # img
    |   |-- svg                         # svg
    |-- .editorconfig                   # editorconfig
    |-- .env.dev                        # 环境变量 开发
    |-- .env.pro                        # 环境变量 生产
    |-- .env.proxy                      # 环境变量 代理
    |-- .eslintignore                   # eslintignore
    |-- .eslintrc.js                    # eslint 配置项
    |-- .gitignore                      # gitignore
    |-- babel.config.js                 # babel 配置项
    |-- index.html                      # html模板
    |-- package.json                    # package.json
    |-- README.md                       # README
    |-- tsconfig.json                   # tsconfig
    |-- vite.config.ts                  # vite 配置文件
    

    API管理

    可参考上一章,ts对axios的简单封装

    国际化

    推荐使用vscode插件i18n Ally来协助开发,具有以下功能

    • 内联翻译显示
    • 自动补全
    • 一键机器翻译
    • 统一管理所有翻译文案
    • 从代码中提取文案
    • 转跳到翻译文件
    • 支持JSON和YAML
    • 支持多目录工作区
    • 支持 vue-i18n,vuex-i18n,vue-i18next和nuxt-i18n
    • 插件自身多语言支持(English,简体中文,繁体中文)
    // settings.json配置
    ...
    "i18n-ally.sourceLanguage": "zh-CN",
    "i18n-ally.displayLanguage": "zh-CN",
    "i18n-ally.enabledParsers": ["json"],
    "i18n-ally.extract.targetPickingStrategy": "file-previous",
    ...
    

    全局注册

    • src/plugin/index.ts
    import { Directive } from 'vue';
    import filters, { FilterKey } from '@/utils/filters';
    import * as directives from '@/utils/directives/index';
    import storage from '@/utils/storage';
    import customMessage from '@/components/custom/custom-message';
    // 三方插件
    import element from './element';
    import i18n from './i18n';
    
    // 探测是否支持webp
    const canvas = document.createElement('canvas');
    if (canvas.getContext && canvas.getContext('2d')) {
        try {
            const isWebp = canvas.toDataURL('image/webp').includes('data:image/webp').toString();
            storage('localstorage').set('isWebp', isWebp);
        } catch (e) {
            console.error(e);
        }
    }
    
    const install = (app: any): void => {
        // 挂载过滤器
        app.config.globalProperties.$filters = {};
        for(const key in filters) {
            app.config.globalProperties.$filters[key] = filters[key as keyof typeof FilterKey];
        }
    
        // 挂载指令
        Object.keys(directives).forEach(key => {
            app.directive(key, (directives as { [key: string]: Directive })[key]);
        });
    
        // 注册element
        element.components.forEach((component) => {
            if (component.name) app.component(component.name as string, component);
        });
        Object.values(element.plugins).forEach(plugin => {
            app.use(plugin);
        });
        app.provide('$message', customMessage);
    
        // 注册i18n
        app.use(i18n);
    };
    
    • main.ts
    import { createApp } from 'vue';
    import App from './App.vue';
    import router from './router';
    import store from './store';
    import * as CustomPlugin from './plugin';
    import * as CustomComponents from './components/custom';
    
    const app = createApp(App);
    
    // 注册全局组件
    app.use(CustomComponents);
    // 注册全局 插件/过滤器/指令
    app.use(CustomPlugin);
    
    app.use(router).use(store).mount('#container');
    

    项目配置项

    环境变量,在import.meta.env对象上暴露环境变量

    • .env.dev
    # .env.dev
    NODE_ENV=development
    
    VITE_Version = 'v1.0.0'
    VITE_BaseURL = '//dev.backendapi.aid.connext.net.cn/'
    
    • abstract.ts
    console.log(import.meta.env.VITE_BaseURL) // dev.backendapi.aid.connext.net.cn/
    

    vite.config.ts

    import { defineConfig, loadEnv } from 'vite';
    import vue from '@vitejs/plugin-vue';
    import viteCompression from 'vite-plugin-compression';
    import styleImport from 'vite-plugin-style-import';
    import vueI18n from '@intlify/vite-plugin-vue-i18n';
    const path = require('path');
    const port = 7000;
    const timeStamp = Date.now();
    
    • vite插件使用
    export default ({ mode }: { mode: string }): unknown => {
        process.env = {...process.env, ...loadEnv(mode, process.cwd())};
        return defineConfig({
            plugins: [
                vue(),
                viteCompression({
                    verbose: true,
                    disable: false,
                    threshold: 1024 * 10,
                    algorithm: 'gzip',
                    ext: '.gz'
                }),
                styleImport({
                    libs: [
                        {
                            libraryName: 'element-plus',
                            esModule: true,
                            ensureStyleFile: true,
                            resolveStyle: (name) => {
                                name = name.slice(3);
                                return `element-plus/packages/theme-chalk/src/${name}.scss`;
                            },
                            resolveComponent: (name) => {
                                return `element-plus/lib/${name}`;
                            }
                        }
                    ]
                }),
                vueI18n({
                    compositionOnly: false,
                    include: path.resolve(__dirname, './src/locale/**')
                })
            ]
        });
    };
    
    • 打包chunk命名和代码分割
    export default ({ mode }: { mode: string }): unknown => {
      process.env = {...process.env, ...loadEnv(mode, process.cwd())};
      return defineConfig({
        build: {
          assetsDir: 'static/assets',
          rollupOptions: {
            output: {
              entryFileNames: `static/js/[name].${process.env.VITE_Version}.t${timeStamp}.js`,
              chunkFileNames: `static/js/[name].${process.env.VITE_Version}.t${timeStamp}.js`,
              assetFileNames: `static/js/[name].${process.env.VITE_Version}.t${timeStamp}.[ext]`,
            },
            manualChunks(id) {
              const chunkMap = new Map();
              chunkMap.set(/[\\/]src[\\/]layout[\\/]/.test(id), 'basicLayout');
              chunkMap.set(/[\\/]src[\\/]components[\\/]/.test(id), 'basicComponent');
              chunkMap.set(/[\\/]node_modules[\\/]echarts[\\/]/.test(id), 'echarts');
              chunkMap.set(/[\\/]node_modules[\\/]lodash[\\/]/.test(id), 'lodash');
              chunkMap.set(/[\\/]node_modules[\\/]moment[\\/]/.test(id), 'moment');
              chunkMap.set(/[\\/]node_modules[\\/]qiankun[\\/]/.test(id), 'qiankun');
              chunkMap.set(/[\\/]node_modules[\\/]xlsx[\\/]xlsx.js/.test(id), 'xlsxIndex');
              chunkMap.set(/[\\/]node_modules[\\/]xlsx[\\/](?!(xlsx.js))/.test(id), 'xlsx');
              chunkMap.set(/[\\/]node_modules[\\/]element-plus[\\/]/.test(id), 'element');
              return chunkMap.get(true) || 'vendors';
            }
          }
        }
      });
    };
    

    安装使用

    • 克隆项目
    git clone https://github.com/sunweijieMJ/vite-vue3-temp.git
    
    • 安装依赖
    cd vite-vue3-temp
    
    yarn
    或
    npm i
    
    
    • 运行
    yarn serve dev
    或
    npm run serve dev
    
    • 打包
    yarn build pro
    或
    npm run build pro
    

    附上 github 的项目地址:vite-vue3-temp,顺手给楼主点个 star 吧

    相关文章

      网友评论

          本文标题:vite+vue3初体验

          本文链接:https://www.haomeiwen.com/subject/nfvvrltx.html