关注公众号: 微信搜索 前端工具人 ; 收货更多的干货

原文链接: 自己掘金文章 https://juejin.cn/post/6951557699079569422/

关注公众号: 微信搜索 前端工具人 ; 收货更多的干货

一、介绍

之前一直是使用 webpack 构建项目, 但是那种随着项目越来越大运行、打包、热更新缓慢带来的无奈。。。

新项目开发果断使用了vite2.0, 和 webpack 对比起来, 其他的优点不是很直观,但在运行、打包、热更新方面简直倍数差距, 只能说我觉得 vite2.0 很舒服。

当然 vite 作为热门构建共建优点还是很多的,详情可以去官网看看 vite 官网地址

二、问题

// 问题代码 () => import( /* @vite-ignore */ `${fileSrc}`)
routerList.push({
path: `/${routerPath}`,
name: `${routerName}`,
component: () => import( /* @vite-ignore */ `${fileSrc}`)
})

之前使用 webpack 构建项目一直使用动态导入 require.context API 自动化注册组件及路由;

转移到 vite 之后,开发习惯当然不能变;随即使用的是 import.meta.globEager 完成动态导入;

本地开发过程中很舒服没问题,打包后部署到服务器报错找不到动态导入的文件;裂开~~~

经过这几天陆陆续续的尝试最终解决,总结了以下几种方案

三、需求

主要项目结构

├── components                    // 公共组件存放目录
└── views // 路由视图存放目录
└── Home // Home 页面
└── components // Home 页面封装组件存放文件
└── HomeHeader.vue // Home 页面头部组件
└── index.vue // Home 主入口
└── types // Home页面专属类型
└── Login // Login 页面
└── components // Login 页面封装组件存放文件
└── LoginHeader.vue // Login 页面头部组件
└── index.vue // Login 主入口
└── types // Login页面专属类型
....
....

文件内部

export default defineComponent({
name: 'home',
isRouter: true,
isComponents: false,
setup() {
...
}
})

组件内部通过定义

  • name: 路由组件名称
  • isRouter: 是否自动为路由;
  • isComponents: 是否自动注册为公共组件

四、 解决 (推荐方案二)

vite 动态导入有两种方式

  • import.meta.glob: 通过动态导入默认懒加载,通过遍历加 then 方法可拿到对应的模块文件详情信息

  • import.meta.globEager: 直接引入所有的模块, 即静态 import; 我的就是使用该方案打包部署报错

以下方案有需要自行取舍

4.1 方案一

使用 import.meta.glob

缺点:

  • 不使用 then 方法拿不到模块信息,无法进行判断是否需要自动注册组件或路由;
  • 使用了 then 方法成异步的了, 路由渲染的时候文件还没获取成功注册不到

但是你可以用单独文件夹来区分,我认为限制性太大不够优雅;

// global.ts
export const vueRouters = function (): Array<RouteRecordRaw> {
let routerList: Array<RouteRecordRaw> = [];
const modules = import.meta.glob('../views/**/*.vue')
Object.keys(modules).forEach(key => {
const nameMatch = key.match(/^\.\.\/views\/(.+)\.vue/)
if(!nameMatch) return
const indexMatch = nameMatch[1].match(/(.*)\/Index$/i)
let name = indexMatch ? indexMatch[1] : nameMatch[1];
// 首字母转小写 letterToLowerCase 首字母转大写 letterToUpperCase
routerList.push({
path: `/${letterToLowerCase(name)}`,
name: `${letterToUpperCase(name)}`,
component: modules[key]
});
})
return routerList
};

使用 router.ts

import { vueRouters } from '../services/global'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Login',
component: () => import('@/views/Login/index.vue')
},
...vueRouters()
]

4.2 方案二 “推荐”

使用 import.meta.globimport.meta.globEager

  • import.meta.glob: 因为 import.meta.glob 获取到的文件就是懒加载的,避免了使用 import 语句, 所以打包后不会报错不存在动态引入了
  • import.meta.globEager:不使用 then 也能获取到文件全局上下文进行有需要的判断
// global.ts
function getModules() {
const components = import.meta.glob('../views/**/*.vue')
return components
}
function getComponents() {
const components = import.meta.globEager('../views/**/*.vue')
return components
}
// 自动注册组件
export const asyncComponent = function (app: App<Element>): void {
const modules = getModules();
const components = getComponents();
Object.keys(modules).forEach((key: string) => {
const viewSrc = components[key];
const file = viewSrc.default;
if (!file.isComponents) return
const AsyncComponent = defineAsyncComponent(modules[key])
app.component(letterToUpperCase(file.name), AsyncComponent)
});
// console.log(app._component.components)
}; // 自动注册路由
export const vueRouters = function (): Array<RouteRecordRaw> {
let routerList: Array<RouteRecordRaw> = [];
const modules = getModules();
const components = getComponents();
Object.keys(modules).forEach(key => {
const viewSrc = components[key];
const file = viewSrc.default;
if (!file.isRouter) return
// 首字母转小写 letterToLowerCase 首字母转大写 letterToUpperCase
routerList.push({
path: `/${letterToLowerCase(file.name)}`,
name: `${letterToUpperCase(file.name)}`,
component: modules[key]
});
})
return routerList
}

使用 router.ts (路由注册)

import { vueRouters } from '../services/global'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Login',
component: () => import('@/views/Login/index.vue')
},
...vueRouters()
]

使用 main.ts (组件注册)

import { asyncComponent } from './services/global';
export const app = createApp(App)
asyncComponent(app)

4.3 方案三

使用 import.meta.globthen 方法, 加上路由内置 addRoute() 方法注册

缺点:

  • 由于文件懒加载获取, 页面加载有明显的的卡顿
  • 不适用于注册组件
  • addRoute() 方法适用于根据后台接口返回的路由权限注册鉴权路由
// global.ts
export const vueRouters = function (router: Router): void {
let routerList: Array<RouteRecordRaw> = [];
const modules = import.meta.glob('../views/**/*.vue')
for (const path in modules) {
modules[path]().then((mod) => {
const file = mod.default;
if (!file.isRouter) return
// 首字母转小写 letterToLowerCase 首字母转大写 letterToUpperCase
router.addRoute({
path: `/${letterToLowerCase(file.name)}`,
name: `${letterToUpperCase(file.name)}`,
component: file
})
})
}
};

使用 router.ts

import { vueRouters } from '../services/global'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Login',
component: () => import('@/views/Login/index.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
vueRouters(router)

vite 动态 import 引入打包报错解决方案的更多相关文章

  1. php Yaf_Loader::import引入文件报错的解决方法

    php Yaf_Loader::import引入文件报错的解决方法 改下配置文件就行<pre>yaf.use_spl_autoload=1</pre> 也可以PHP动态修改 毕 ...

  2. angular ng build --prod 打包报错解决方案

    使用以下代码  就不报错了 ng build --prod --no-extract-license    打包命令 使用以下代码  就不报错了 ng build --prod --no-extrac ...

  3. vue项目使用echarts按需引入实现地图动态显示效果时,报错:TypeError: Cannot read property 'dataToPoint' of undefined

    vue项目使用echarts按需引入实现地图动态显示效果时,报错:TypeError: Cannot read property 'dataToPoint' of undefined 借鉴了该大神的文 ...

  4. Python3.x:import urllib2报错解决方案

    Python:import urllib2报错解决方案 python2和3有些不一样: python2:输出为print 'hello world' python3:输出为print('hello w ...

  5. [one day one question] webpack 打包报错 Cannot assign to read only property 'exports' of object '#<Object>'

    问题描述: webpack 打包报错 Cannot assign to read only property 'exports' of object '#<Object>',这怎么破? 解 ...

  6. iOS开发——打包报错error: linker command failed with exit code 1

    真机运行没问题,打包报错: clang: error: linker command failed with exit code 1 (use -v to see invocation) 原因:在Xc ...

  7. Scrapy运行报错解决方案

    最近在学习Scrapy框架,用博客记录一下遇到的错误的解决方案 时间: 2016-9-20 错误:ImportError: No module named items 原因:spiders下的.py文 ...

  8. Mac Angular打包报错xcode-select: error: tool 'xcodebuild' requires Xcode

    Mac Angular打包报错: Error: xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer ...

  9. typescript import 全局node_modules报错

    项目里面有一个node_modules的包太大,每次放到docker里面都要下载半天,大大减少了部署效率. 所以考虑将这个node包全局安装到docker的基础镜像中,那么代码里面直接引用全局包就可以 ...

随机推荐

  1. DeFi热下的冷思考 NGK以更深层次的方式参与DeFi建设

    独具慧眼,深度挖掘DeFi潜力项目 作为早期DeFi的探索者和推动者,NGK在此轮热潮席卷市场前就已经开始构建自己的DeFi生态,独具慧眼的NGK上线了Baccarat流动性挖矿项目,完成了首个由平台 ...

  2. Scrapy项目_阳光热线问政平台

    目的: 爬取阳光热线问政平台问题中每个帖子的标题.详情URL.详情内容.图片以及发布时间 步骤: 1.创建爬虫项目 1 scrapy startproject yangguang 2 cd yangg ...

  3. FTPClient类的API

    org.apache.commons.NET.ftp Class FTPClient类FTPClient java.lang.Object java.lang.Object继承 org.apache. ...

  4. 创建时间和更新时间两个选一个的情况和select case when ... then ... else ... end from 表 的使用

    1.查询时间,如果更新时间update_time为空就查创建时间create_time,否则查更新时间update_time select update_time,create_time, case ...

  5. 第28天学习打卡(Date和Calendar类 基本类型的包装类 集合 增强for循环 )

    Date和Calendar类 简介 日期和日历类,用于操作日期相关信息. 构造方法 Date(): 构造一个日期对象,当前系统时间,精确到毫秒. Date(long): 构造一个日期对象,时间为自&q ...

  6. 【重磅】iNeuOS工业互联平台,系统集成业务模型和WEB组态视图建模集成3D模型

    目       录 1.      概述... 1 2.      平台演示... 2 3.      系统集成业务模型... 2 4.      WEB组态视图建模集成3D模型... 3 5.    ...

  7. Python3+pygame实现的俄罗斯方块 代码完整 有演示效果

    一.简单说明 80.90后的小伙伴都玩过"俄罗斯方块",那种"叱咤风云"场景 偶尔闪现在脑海 真的是太爽了:如果没有来得及玩过的同学,这次可以真正的自己做一个了 ...

  8. PAT-1136(A Delayed Palindrome)字符串处理+字符串和数字间的转换

    A Delayed Palindrome PAT-1136 我这里将数字转换为字符串使用的是stringstream字符串流 扩充:将字符串转换为数字可以使用stoi函数,函数头为cstdlib #i ...

  9. [个人总结]利用grad-cam实现人民币分类

    # -*- coding:utf-8 -*- import os import numpy as np import torch import cv2 import torch.nn as nn fr ...

  10. C#的foreach遍历循环和隐式类型变量

    C#的foreach遍历循环和隐式类型变量 foreach遍历循环 foreach (<baseType> <name> in <array>>) { //c ...