下面是问题描述,解决办法看目录解决办法那一项
组件代码在最后面
vue3+vite+ts+elementPlus的项目中,我遇到了npm run dev可以正常运行,然后运行npm run build的时候就报错的情况,编译不过去,在这里记录一下,而且在vscode中与element plus相关的是爆红的,但是可以正常运行,只是打包不能正常打包而已。就会报错
如在vscode中报这个红,
无法找到模块“element-plus/dist/locale/zh-cn.mjs”的声明文件
还有就是引用element plus的一些组件的相关按需引入的时候爆红
模块 ““element-plus”” 没有导出的成员 “ElMessage”。你是想改用 “import ElMessage from “element-plus”” 吗?
模块 ““element-plus”” 没有导出的成员 “FormInstance”。你是想改用 “import FormInstance from “element-plus”” 吗?
虽然有这些爆红,但是npm run dev可以正常运行,运行结果如下
但是npm run build的时候打包就会报错,报错结果如下,就无法打包成功了,就是因为上面的那些爆红,所以导致打包失败。
TS7016: Could not find a declaration file for module ‘element-plus/dist/locale/zh-cn.mjs’. ‘D:/javastudykeshanchu/vite+ts+elementPlus/node_modules/element-plus/dist/locale/zh-cn.mjs’ implicitly has an ‘any’ type.
If the ‘element-plus’ package actually exposes this module, try adding a new declaration (.d.ts) file containingdeclare module 'element-plus/dist/locale/zh-cn.mjs';
5 import zhCn from ‘element-plus/dist/locale/zh-cn.mjs’
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~src/views/Home.vue:84:10 - error TS2614: Module ‘“element-plus”’ has no exported member ‘ElMessage’. Did you mean to use ‘import ElMessage from “element-plus”’ instead?
84 import { ElMessage, ElTable } from ‘element-plus’
具体如下截图
在爆红的情况下,使用npm run dev是可以正常运行项目的情况下,正如上面所描述的那样。因为爆红无法打包的情况,我们可以对打包进行配置,在打包的时候让其跳过ts的语法检查。
结果如下所示:打包成功了,如果这里执行npm run build的话,还是会有ts的语法检查,如果执行npm run build:no-vue-tsc这个就不会有语法检查,具体可以看上图所示的内容。
通过这里的配置我们也可以通过类似的设置,在运行的时候进行语法检查,其实这里真没必要这样做,因为我们在写代码的时候。如果出现TS语法报错的时候,编辑器会提示的,那里就会爆红,所以运行时进行语法检查,我感觉就是多此一举,而且在执行运行时的命令的时候,还要进行一遍语法检查才运行,简直是浪费时间。然后我们根据爆红的信息进行对应的修改就行了,去除爆红。
element plus修改语言报错的解决办法
当出现:无法找到模块“element-plus/dist/locale/zh-cn.mjs”的声明文件
Could not find a declaration file for module ‘element-plus/dist/locale/zh-cn.mjs’.
在 .d.ts
文件中(如:vite在 vite-env.d.ts
文件)添加代码:
// 就加这一行就可以了
declare module "element-plus/dist/locale/zh-cn.mjs";
解决打包时出现导入element plus相关的爆红,导致无法打包的问题
如若出现类似于:Module ‘“element-plus”’ has no exported member ‘ElMessage’. Did you mean to use ‘import ElMessage from “element-plus”’ instead?
模块 ““element-plus”” 没有导出的成员 “ElMessage”。你是想改用 “import ElMessage from “element-plus”” 吗?
模块 ““element-plus”” 没有导出的成员 “FormInstance”。你是想改用 “import FormInstance from “element-plus”” 吗?
这样的问题,我们仅仅需要修改tsconfig.json文件下的,“moduleResolution”: “bundler”,改成"moduleResolution": “node即可”,
之所以出现上面这种(爆红)情况,是因为最新的vite构建的项目使用了typescript5.x的版本,而在这个版本中"moduleResolution": "bundler"是bundler而不是node
如我这里的typescript的版本是
这样的问题,我们仅仅需要修改tsconfig.json文件下的,“moduleResolution”: “bundler”,改成"moduleResolution": “node即可”,
改了之后,整个vue文件就不爆红了,
执行npm run dev运行看一下结果,也可以正常运行
然后执行npm run build,打包,打包的时候报什么样的错就根据错误进行改成就行了,如下面这里,element plus的import按需导入和语言切换已经解决了
之后执行 npm run build打包,就可以成功打包了
组件代码:
<template>
<div>
<h1>这个是Home组件h1>
<el-button type="primary" @click="open2">successel-button>
<el-row>
<el-table ref="multipleTableRef" :data="tableData" style="width: 100%" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column label="Date" width="120">
<template #default="scope">{{ scope.row.date }}template>
el-table-column>
<el-table-column property="name" label="Name" width="120" />
<el-table-column property="address" label="Address" show-overflow-tooltip />
el-table>
<div style="margin-top: 20px">
<el-button @click="toggleSelection([tableData[1], tableData[2]])">Toggle selection status of second and third
rowsel-button>
<el-button @click="toggleSelection()">Clear selectionel-button>
div>
el-row>
<el-row>
<el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm"
:size="formSize" status-icon>
<el-form-item label="Activity name" prop="name">
<el-input v-model="ruleForm.name" />
el-form-item>
<el-form-item label="Activity zone" prop="region">
<el-select v-model="ruleForm.region" placeholder="Activity zone">
<el-option label="Zone one" value="shanghai" />
<el-option label="Zone two" value="beijing" />
el-select>
el-form-item>
<el-form-item label="Activity count" prop="count">
<el-select-v2 v-model="ruleForm.count" placeholder="Activity count" :options="options" />
el-form-item>
<el-form-item label="Activity time" required>
<el-col :span="11">
<el-form-item prop="date1">
<el-date-picker v-model="ruleForm.date1" type="date" label="Pick a date" placeholder="Pick a date"
style="width: 100%" />
el-form-item>
el-col>
<el-col class="text-center" :span="2">
<span class="text-gray-500">-span>
el-col>
<el-col :span="11">
<el-form-item prop="date2">
<el-time-picker v-model="ruleForm.date2" label="Pick a time" placeholder="Pick a time"
style="width: 100%" />
el-form-item>
el-col>
el-form-item>
<el-form-item label="Instant delivery" prop="delivery">
<el-switch v-model="ruleForm.delivery" />
el-form-item>
<el-form-item label="Activity type" prop="type">
<el-checkbox-group v-model="ruleForm.type">
<el-checkbox label="Online activities" name="type" />
<el-checkbox label="Promotion activities" name="type" />
<el-checkbox label="Offline activities" name="type" />
<el-checkbox label="Simple brand exposure" name="type" />
el-checkbox-group>
el-form-item>
<el-form-item label="Resources" prop="resource">
<el-radio-group v-model="ruleForm.resource">
<el-radio label="Sponsorship" />
<el-radio label="Venue" />
el-radio-group>
el-form-item>
<el-form-item label="Activity form" prop="desc">
<el-input v-model="ruleForm.desc" type="textarea" />
el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(ruleFormRef)">
Create
el-button>
<el-button @click="resetForm(ruleFormRef)">Resetel-button>
el-form-item>
el-form>
el-row>
div>
template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { ElMessage, ElTable } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
const open2 = () => {
ElMessage({
message: 'Congrats, this is a success message.',
type: 'success',
})
}
interface User {
date: string
name: string
address: string
}
const multipleTableRef = ref<InstanceType<typeof ElTable>>()
const multipleSelection = ref<User[]>([])
const toggleSelection = (rows?: User[]) => {
if (rows) {
rows.forEach((row) => {
// 这个是表格的复选框勾选项
multipleTableRef.value!.toggleRowSelection(row, true)
})
} else {
multipleTableRef.value!.clearSelection()
}
}
const handleSelectionChange = (val: User[]) => {
multipleSelection.value = val
}
const tableData: User[] = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-08',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-06',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-07',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
// 表单
const formSize = ref('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive({
name: 'Hello',
region: '',
count: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: '',
})
const rules = reactive<FormRules>({
name: [
{ required: true, message: 'Please input Activity name', trigger: 'blur' },
{ min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
],
region: [
{
required: true,
message: 'Please select Activity zone',
trigger: 'change',
},
],
count: [
{
required: true,
message: 'Please select Activity count',
trigger: 'change',
},
],
date1: [
{
type: 'date',
required: true,
message: 'Please pick a date',
trigger: 'change',
},
],
date2: [
{
type: 'date',
required: true,
message: 'Please pick a time',
trigger: 'change',
},
],
type: [
{
type: 'array',
required: true,
message: 'Please select at least one activity type',
trigger: 'change',
},
],
resource: [
{
required: true,
message: 'Please select activity resource',
trigger: 'change',
},
],
desc: [
{ required: true, message: 'Please input activity form', trigger: 'blur' },
],
})
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
console.log('submit!')
} else {
console.log('error submit!', fields)
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
const options = Array.from({ length: 10000 }).map((_, idx) => ({
value: `${idx + 1}`,
label: `${idx + 1}`,
}))
script>
<style scoped>style>
总结:比较建议使用解决办法2:保持TS的语法检查打包(比较建议这一种),毕竟在ts语法爆红问题中,我们在代码开发的时候,编辑器就已经已经帮忙检查出来ts的语法问题了,我们只需要根据对一个的爆红问题,进行对应的解决就行了。看着文件没有爆红就可以了,不过有些爆红并不影响打包运行,如路由配置那里的爆红是不影响打包运行的。所以相对来说:解决办法1:打包的时候跳过ts的语法检查这个就省心很多了
这里我使用了路由的形式,打包之后双击 index.html网站显示一片空白,f12之后报如下所示的错误
我这里的路由配置是:
import { createRouter, createWebHashHistory } from "vue-router";
const routes = [
{
path: '/',
redirect: '/home'
},
{
path: '/helloworld',
component: () => import('../views/HelloWorld.vue')
},
{
path: '/home',
component: () => import('../views/Home.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: routes
})
export default router
这个是直接在打包的dist文件夹下双击代开index.html,页面一片空白,所报的错误如下,这里有跨域问题,
assets/index-bf854284.js’ from origin ‘null’ has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome-untrusted, https, edge.
如果是使用vscode的发布服务打开的话,具体报错如下
报错信息如下
Found)
index.html:12 Refused to apply style from ‘http://127.0.0.1:5500/assets/index-5d2d5719.css’ because its MIME type (‘text/html’) is not a supported stylesheet MIME type, and strict MIME checking is enabled.
index.html:42 Live reload enabled.
:5500/vite.svg:1index.html:1 Refused to apply style from ‘http://127.0.0.1:5500/assets/index-5d2d5719.css’ because its MIME type (‘text/html’) is not a supported stylesheet MIME type, and strict MIME checking is enabled.
但是,这里使用Vscode打开是一片空白,但是使用nginx配置反向代理的话,这里是可以得到正确的界面展示的,就不会是一片空白的。具体可以试试,后面有nginx的对应配置,方法。
然后在vite.config.ts中进行如下配置
保存,npm run build重新打包,使用vscode服务的形式打开重新打包的index.html文件
能正常访问,就可以解决页面空白问题了,也可以根据路由切换不用的页面
但是下面这种双击打开方式还是有跨域问题,页面还是空白。这个暂时不知道怎么回事,还在找解决办法中,这种或许可以通过nginx解决,后面再说
首先,将上面打包得到的dist文件复制到nginx对应的目录下,然后配置nginx,具体配置如下(可以使用vscode打开nginx.config),监听的端口号为8083。
启动nginx,如果之前已经启动了,记得先停用之后再配置,之后再双击启动nginx
启动nginx之后,访问http://localhost:8083,就可以了,之后就会得到如下的界面,改变路由地址也可以正常访问