这篇内容是在有道云旧笔记基础上重新整理的 Vue/Vite 工程实践 笔记。原始记录偏碎片化,这里补充了使用场景、阅读顺序和落地时需要注意的边界,方便以后在项目里快速复用。

适用场景 ​

  • Vue/Vite 项目中遇到配置、组件封装、构建或运行时问题时,作为排查入口。
  • 需要把一次性调试经验沉淀成团队内可复用的前端工程实践。
  • 迁移旧项目或升级依赖时,用来对照检查环境变量、插件和组件行为差异。

核心要点 ​

  • 正文以代码或命令片段为主,阅读时建议先确认目标问题,再挑选对应片段验证。
  • 保留了 3 段可直接参考的代码或命令,主要涉及 javascript,复制前需要按当前项目路径、版本和变量名做调整。
  • 涉及命令行操作时,建议先在测试目录或测试环境执行,确认输出符合预期后再应用到生产环境。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
loader.js

// 如果只有少淑特定的语言,可以从组件中抽离出来单独的文件夹
// 动态引入 dayjs 语言包
const dayjsLocales = import.meta.glob('../../node_modules/dayjs/locale/*.js');

// 动态引入 vant 语言包
const vantLocales = import.meta.glob('../../node_modules/vant/es/locale/lang/*.mjs');

export default async function loadLocale(lang) {
const lowerCase = lang.toLowerCase();
const dayjsKey = `../../node_modules/dayjs/locale/${lowerCase}.js`;
const vantKey = `../../node_modules/vant/es/locale/lang/${lang}.mjs`;

// 加载 dayjs 的语言包
if (dayjsLocales[dayjsKey]) {
// const mod = await dayjsLocales[dayjsKey]();
// 设置 dayjs 的语言
const dayjs = (await import('dayjs')).default;
dayjs.locale(lowerCase);
}
else {
console.warn(`Day.js: Missing locale for ${lang}`);
}

// 加载 vant 的语言包
if (vantLocales[vantKey]) {
const mod = await vantLocales[vantKey]();
const { Locale } = await import('vant');
Locale.use(lang, mod.default);
}
else {
console.warn(`Vant: Missing locale for ${lang}`);
}
}

// locales/index.js
import loadLocale from './loader';
export function setHtmlPageLang(locale) {
loadLocale(locale);
const html = document.querySelector('html');
if (html && html.getAttribute('lang') !== locale) {
html.setAttribute('lang', locale);
}
}
// index.js
import messages from '@intlify/unplugin-vue-i18n/messages';
import { createI18n } from 'vue-i18n';
import Locales from '../../locales.config';
import loadLocale from './loader';

let i18n;

function createI18nOptions() {
const locale = navigator?.language || 'zh-CN';
const i18nOptions = {
locale,
legacy: false,
fallbackLocale: 'zh-CN',
availableLocales: [...Locales],
messages: {}, // Initialize messages as an empty object
};

if (locale) {
setHtmlPageLang(locale);
i18nOptions.messages = messages;
}

return i18nOptions;
}

export default function initI18n(app) {
const options = createI18nOptions();

i18n = createI18n(options);
app.use(i18n);
}

export function setHtmlPageLang(locale) {
loadLocale(locale);
const html = document.querySelector('html');
if (html && html.getAttribute('lang') !== locale) {
html.setAttribute('lang', locale);
}
}

export function changeLanguage(locale) {
i18n.global.locale = locale; // 动态修改语言
setHtmlPageLang(locale); // 更新页面 lang 属性
}

手动导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// index.js
import messages from '@intlify/unplugin-vue-i18n/messages';
import { createI18n } from 'vue-i18n';
import Locales from '../../locales.config';
import loadDayjs from './dayjs';
import loadVant from './vant';

let i18n;

function createI18nOptions() {
const locale = navigator?.language || 'zh-CN';
const i18nOptions = {
locale,
legacy: false,
fallbackLocale: 'zh-CN',
availableLocales: [...Locales],
messages: {}, // Initialize messages as an empty object
};

if (locale) {
setHtmlPageLang(locale);
i18nOptions.messages = messages;
}

return i18nOptions;
}

export default function initI18n(app) {
const options = createI18nOptions();
i18n = createI18n(options);
app.use(i18n);
}

export function setHtmlPageLang(locale) {
loadDayjs(locale);
loadVant(locale);
const html = document.querySelector('html');
if (html && html.getAttribute('lang') !== locale) {
html.setAttribute('lang', locale);
}
}

export function changeLanguage(locale) {
// i18n.global.locale = locale; // 动态修改语言
i18n.global.locale.value = locale;
setHtmlPageLang(locale); // 更新页面 lang 属性
}
// dayjs.js

import dayjs from 'dayjs';
import localesConfig from '../../locales.config';

import 'dayjs/locale/zh-cn';
import 'dayjs/locale/en';


// 语言映射表 (根据需要添加更多语言)
const localeMap = {
'zh-CN': 'zh-cn',
'en-US': 'en',
// 添加其他语言映射...
};

const usableLocales = Object.fromEntries(
Object.entries(localeMap).filter(([key]) => localesConfig.includes(key))
);

export default function loadDayjs(locale) {
const dayjsLocale = usableLocales[locale];
if (dayjsLocale) dayjs.locale(dayjsLocale);
}


// vant.js
import { Locale } from 'vant';
import localesConfig from '../../locales.config';

import enUS from 'vant/es/locale/lang/en-US';
import zhCN from 'vant/es/locale/lang/zh-CN';


// Vant 语言包映射
const vantLocales = {
'zh-CN': zhCN,
'en-US': enUS,
// 添加其他语言...
};

const usableLocales = Object.fromEntries(
Object.entries(vantLocales).filter(([key]) => localesConfig.includes(key))
);

export default function loadVant(locale) {
const vantLocale = usableLocales[locale];
if (vantLocale) Locale.use(locale, vantLocale);
}

// locales.config.js
export default Object.freeze(['zh-CN', 'en-US']);

实践检查清单 ​

  • 先确认 Vue、Vite、Node、包管理器版本,再判断示例是否需要按当前工程结构调整。
  • 涉及构建或插件配置时,建议同时验证开发环境和生产构建结果。
  • 涉及 UI 或浏览器行为时,至少在桌面端和移动端各验证一次关键路径。
  • 涉及接口、服务端或权限逻辑时,补充失败分支和权限边界测试。

复盘小结 ​

这篇笔记更适合作为问题排查或方案落地前的速查材料。后续如果在真实项目中再次遇到同类问题,可以继续把具体版本、报错信息、最终取舍和验证结果补到对应小节里,让它从代码片段逐步沉淀成完整方案。