vue3+vite+ts+elementPlus中运行正常打包出错

能正常运行,但是打包出错

下面是问题描述,解决办法看目录解决办法那一项

组件代码在最后面

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 containing declare 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’

具体如下截图

在这里插入图片描述

解决办法1:打包的时候跳过ts的语法检查

在爆红的情况下,使用npm run dev是可以正常运行项目的情况下,正如上面所描述的那样。因为爆红无法打包的情况,我们可以对打包进行配置,在打包的时候让其跳过ts的语法检查。
在这里插入图片描述
结果如下所示:打包成功了,如果这里执行npm run build的话,还是会有ts的语法检查,如果执行npm run build:no-vue-tsc这个就不会有语法检查,具体可以看上图所示的内容。
在这里插入图片描述
通过这里的配置我们也可以通过类似的设置,在运行的时候进行语法检查,其实这里真没必要这样做,因为我们在写代码的时候。如果出现TS语法报错的时候,编辑器会提示的,那里就会爆红,所以运行时进行语法检查,我感觉就是多此一举,而且在执行运行时的命令的时候,还要进行一遍语法检查才运行,简直是浪费时间。然后我们根据爆红的信息进行对应的修改就行了,去除爆红。
在这里插入图片描述

解决办法2:保持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 文件中(如:vitevite-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">success</el-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
          rows</el-button>
        <el-button @click="toggleSelection()">Clear selection</el-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)">Reset</el-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的语法检查这个就省心很多了
在这里插入图片描述

vue3项目打包之后双击index.html是一片空白

这里我使用了路由的形式,打包之后双击 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:1

index.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解决,后面再说

在这里插入图片描述
在这里插入图片描述
通过nginx配置进行打包的部署

首先,将上面打包得到的dist文件复制到nginx对应的目录下,然后配置nginx,具体配置如下(可以使用vscode打开nginx.config),监听的端口号为8083。
在这里插入图片描述
启动nginx,如果之前已经启动了,记得先停用之后再配置,之后再双击启动nginx
在这里插入图片描述
启动nginx之后,访问http://localhost:8083,就可以了,之后就会得到如下的界面,改变路由地址也可以正常访问
在这里插入图片描述
在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐