-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvue.config.js
More file actions
252 lines (228 loc) · 9 KB
/
Copy pathvue.config.js
File metadata and controls
252 lines (228 loc) · 9 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
const pages = {
// 百科栏目
cj: {
title: "成就百科 - JX3BOX",
template: "public/index.html",
entry: "src/pages/cj.js",
filename: "cj/index.html",
},
item: {
title: "物品百科 - JX3BOX",
template: "public/index.html",
entry: "src/pages/item.js",
filename: "item/index.html",
},
quest: {
title: "任务百科 - JX3BOX",
template: "public/index.html",
entry: "src/pages/quest.js",
filename: "quest/index.html",
},
knowledge: {
title: "通识百科 - JX3BOX",
template: "public/index.html",
entry: "src/pages/knowledge.js",
filename: "knowledge/index.html",
},
};
const path = require("path");
const webpack = require("webpack");
const autoprefixer = require("autoprefixer");
const tailwindPostcss = require("@tailwindcss/postcss");
const commonDomains = require("@jx3box/jx3box-common/data/jx3box.json");
const postcssConfig = path.resolve(__dirname, "./postcss.config.js");
const tailwindEntry = path.resolve(__dirname, "./src/assets/css/tailwind.css");
module.exports = {
productionSourceMap: false,
transpileDependencies: true,
//❤️ define path for static files ~
publicPath: process.env.BUILD_PREVIEW
? "/" + process.env.APP_NAME
: process.env.NODE_ENV === "development"
? "/"
: process.env.STATIC_PATH + "/" + process.env.APP_NAME,
//🌈多页面配置,详见 https://cli.vuejs.org/zh/config/#pages
pages: pages,
//⚛️ Proxy ~
devServer: {
host: "localhost",
client: {
overlay: {
runtimeErrors: (error) => {
const message = error && error.message ? String(error.message) : "";
return !/ResizeObserver loop (completed with undelivered notifications|limit exceeded)/.test(message);
},
},
},
// 与 @jx3box/jx3box-common/js/api.js 对齐:
// 本地开发开启 `VUE_APP_PROXY_ENABLE=1` 后,会把请求 baseURL 切到 `${VUE_APP_PROXY_PREFIX}/${serviceKey}`
proxy: buildEnvProxy(),
allowedHosts: "all",
port: process.env.DEV_PORT || 12028,
setupMiddlewares: (middlewares, devServer) => {
devServer.app.get("/", (_, res) => {
res.redirect(302, "/cj");
});
return middlewares;
},
},
// 依赖包(element-plus/theme-chalk 等)会输出大量 Sass deprecation 警告
// 这些不是运行错误,开启 quietDeps 让它们不刷屏(只保留项目自身的警告)
css: {
loaderOptions: {
sass: {
sassOptions: {
quietDeps: true,
},
},
scss: {
sassOptions: {
quietDeps: true,
},
},
},
},
// 过滤依赖包里的已知兼容性 warning(不影响运行,但会刷屏)
configureWebpack: {
stats: {
warningsFilter: [/node_modules[\\\\/]+@jx3box[\\\\/]+jx3box-common[\\\\/]+/],
},
},
//❤️ Webpack configuration
chainWebpack: (config) => {
//💝 in-line small imgs ~
config.module.rule("images").set("parser", {
dataUrlCondition: {
maxSize: 4 * 1024, // 4KiB
},
});
// 💝 quick svg ~
config.module
.rule("svg")
.exclude.add(path.join(__dirname, "src/assets/img/icon")) // 排除自定义svg目录
.end();
config.module
.rule("icons") // 新规则
.test(/\.svg$/)
.include.add(path.join(__dirname, "src/assets/img/icon")) // 新规则应用于我们存放svg的目录
.end()
.use("svg-sprite-loader") // 用sprite-loader接卸
.loader("svg-sprite-loader")
.options({
symbolId: "icon-[name]",
})
.end();
//💝 in-line svg imgs ~
config.module.rule("vue").use("vue-svg-inline-loader").loader("vue-svg-inline-loader");
//💖 import common less var * mixin ~
const types = ["vue-modules", "vue", "normal-modules", "normal"];
types.forEach((type) => addStyleResource(config.module.rule("less").oneOf(type)));
// 依赖包源码可能携带仅供其自身开发使用的 PostCSS 配置。
// 统一指定本项目配置,避免构建 node_modules 源码时误加载依赖包的 devDependencies。
const styleRules = ["css", "postcss", "scss", "sass", "less", "stylus"];
styleRules.forEach((styleRule) => {
types.forEach((type) => {
config.module
.rule(styleRule)
.oneOf(type)
.use("postcss-loader")
.tap((options = {}) => ({
...options,
postcssOptions: {
config: postcssConfig,
},
}));
});
});
// Tailwind v4 只处理唯一入口,普通 CSS/Less 不进入其增量缓存。
types.forEach((type) => {
config.module
.rule("css")
.oneOf(type)
.use("postcss-loader")
.tap((options = {}) => ({
...options,
postcssOptions: (loaderContext) => ({
plugins: [
...(path.resolve(loaderContext.resourcePath) === tailwindEntry ? [tailwindPostcss()] : []),
autoprefixer,
],
}),
}));
});
config.externals = {
tinyMCE: "tinyMCE",
};
},
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
// 全局注入,用于 JS 或其他代码中
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
}),
],
},
};
// 注入全局样式资源(变量、mixin 等)
// 本地css/var.less、mixin.less会覆盖node_modules里的同名文件,方便定制化
// 注意此类文件都是变量和mixin函数,不要写全局样式,否则可能会被重复注入多次
function addStyleResource(rule) {
var preload_styles = [];
preload_styles.push(
path.resolve(__dirname, "./node_modules/@jx3box/jx3box-common/css/var.less"),
path.resolve(__dirname, "./node_modules/@jx3box/jx3box-common/css/mixin.less"),
path.resolve(__dirname, "./src/assets/css/var.less"),
path.resolve(__dirname, "./src/assets/css/mixin.less"),
path.resolve(__dirname, "./node_modules/csslab/base.less")
);
rule.use("style-resource").loader("style-resources-loader").options({
patterns: preload_styles,
});
}
function normalizeTarget(value) {
if (!value) return "";
const trimmed = String(value).trim();
if (!trimmed) return "";
if (/^https?:\/\//i.test(trimmed)) return trimmed;
return `https://${trimmed.replace(/^\/+/, "")}`;
}
function escapeRegExp(str) {
return String(str).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function buildEnvProxy() {
const nodeEnv = String(process.env.NODE_ENV || "").toLowerCase();
if (nodeEnv && nodeEnv !== "development") return {};
// Vue CLI 加载 .env 的时机/覆盖关系可能导致这里读不到或读到意外值:
// - 明确设置为 false 才禁用
// - 未设置/无法读取时,仍然生成代理(仅在 devServer 生效)
const rawEnabled = String(process.env.VUE_APP_PROXY_ENABLE || "").toLowerCase();
const disabled = ["0", "false", "no", "off"].includes(rawEnabled);
if (disabled) return {};
const prefix = process.env.VUE_APP_PROXY_PREFIX || "/__proxy";
const mk = (serviceKey, target) => {
const normalized = normalizeTarget(target);
if (!normalized) return {};
const context = `${prefix}/${serviceKey}`;
const contextRe = new RegExp(`^${escapeRegExp(context)}`);
return {
[context]: {
target: normalized,
changeOrigin: true,
secure: false,
cookieDomainRewrite: "",
pathRewrite: (p) => p.replace(contextRe, ""),
},
};
};
const serviceTargets = {
cms: process.env.VUE_APP_CMS_API || commonDomains.__cms,
next: process.env.VUE_APP_NEXT_API || commonDomains.__next,
team: process.env.VUE_APP_TEAM_API || commonDomains.__team,
pay: process.env.VUE_APP_PAY_API || commonDomains.__pay,
lua: process.env.VUE_APP_LUA_API || commonDomains.__lua,
node: process.env.VUE_APP_NODE_API || commonDomains.__node,
helper: process.env.VUE_APP_HELPER_API || commonDomains.__helperUrl,
gs: process.env.VUE_APP_GS_API || "https://gs.jx3box.com",
};
return Object.keys(serviceTargets).reduce((acc, key) => Object.assign(acc, mk(key, serviceTargets[key])), {});
}