I have a TypeScript + Vue + Vite project, where one of the files is called “timestamptz.ts” and it starts with this line:
import dayjs from "dayjs";
The tsconfig.json file includes this:
{
"compilerOptions": {
"moduleResolution": "node"
}
The vite.config.mts has no special resolve options, just an alias:
const pathSrc = path.resolve(__dirname, 'src')
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
'~/': `${pathSrc}/`,
},
}
// more options here...
}
The package.json file includes dayjs, and it is already installed:
{
"name": "test-project",
"private": true,
"version": "0.1.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"generate": "vite-ssg build",
"preview": "vite preview",
"typecheck": "vue-tsc --noEmit"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@intlify/unplugin-vue-i18n": "^4.0.0",
"dayjs": "^1.11.11",
"element-plus": "^2.6.2",
"oh-vue-icons": "^1.0.0-rc3",
"pinia": "^2.1.7",
"unplugin-auto-import": "^0.18.2",
"unplugin-icons": "^0.19.0",
"vue": "^3.4.21",
"vue-i18n": "^9.13.1",
"vue-router": "^4.4.0"
},
"devDependencies": {
"@iconify-json/ep": "^1.1.15",
"@types/node": "^22.5.1",
"@vitejs/plugin-vue": "^5.0.4",
"sass": "1.77.8",
"typescript": "^5.4.3",
"unocss": "^0.62.3",
"unplugin-vue-components": "^0.27.4",
"vite": "^5.2.5",
"vite-ssg": "^0.23.6",
"vue-tsc": "^2.0.7"
},
"license": "All rights reserved"
}
I have deleted the build cache via rm -rf node_modules/.vite
and then tried npm run build
and it results in:
vite v5.4.3 building for production...
✓ 1202 modules transformed.
x Build failed in 5.13s
error during build:
[vite]: Rollup failed to resolve import "dayjs" from "/home/myuser/projects/test-project/lib/convert/timestamptz.ts".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
at viteWarn (file:///home/myuser/projects/test-project/frontend-dl2/node_modules/vite/dist/node/chunks/dep-BaOMuo4I.js:65511:17)
at onRollupWarning (file:///home/myuser/projects/test-project/frontend-dl2/node_modules/vite/dist/node/chunks/dep-BaOMuo4I.js:65543:5)
at onwarn (file:///home/myuser/projects/test-project/frontend-dl2/node_modules/vite/dist/node/chunks/dep-BaOMuo4I.js:65206:7)
at file:///home/myuser/projects/test-project/frontend-dl2/node_modules/rollup/dist/es/shared/node-entry.js:18668:13
at Object.logger [as onLog] (file:///home/myuser/projects/test-project/frontend-dl2/node_modules/rollup/dist/es/shared/node-entry.js:20306:9)
at ModuleLoader.handleInvalidResolvedId (file:///home/myuser/projects/test-project/frontend-dl2/node_modules/rollup/dist/es/shared/node-entry.js:19257:26)
at file:///home/myuser/projects/test-project/frontend-dl2/node_modules/rollup/dist/es/shared/node-entry.js:19215:26
I have already tried adding an explicit resolve to dayjs:
export default defineConfig({
resolve: {
alias: {
'~/': `${pathSrc}/`,
'dayjs': 'node_modules/dayjs',
},
}
but it results in this very strange error:
[vite:load-fallback] Could not load node_modules/dayjs/plugin/isLeapYear (imported by src/main.ts): ENOENT: no such file or directory, open 'node_modules/dayjs/plugin/isLeapYear'
Actually, there is a file called node_modules/dayjs/plugin/isLeapYear.js
but that is not a TypeScript module that could be imported with an import statement.
What am I missing? How to fix this?
UPDATE: It seem that it only fails if I import dayjs from a non-component ts file. If I import it inside a vue component, then it works. For example, I have this timestamptz.ts
file that contains conversion functions:
import dayjs from 'dayjs'
export type ITimestampTz = string
export const timestampToString = (timestamp: any): string => {
if (timestamp) {
return dayjs(timestamp).format("L LTS")
} else {
return "";
}
};
export const timestampToShortString = (timestamp: any): string => {
if (!timestamp) { return "" }
return dayjs(timestamp).format("L LT")
}
// many other conversion functions here...
Then import this in a component like this:
<script setup lang="ts">
import { timestampToShortString } from "~/lib/convert/timestamptz"
// more component code here that uses timestampToShortString
</script>
<template>
<span>...</span>
</template>
then the error appears. But if I move the function declaration into the vue component itself:
<script setup lang="ts">
import dayjs from 'dayjs'
const timestampToShortString = (timestamp: any): string => {
if (!timestamp) { return "" }
return dayjs(timestamp).format("L LT")
}
// more component code here...
</setup>
then it succeeds.
Obviously, I want to put these functions into regular TypeScript modules, because they should be used from many components. I tried this many times with many different components, and it seems that the error comes up when I import dayjs from a non-component ts file.
But why?