@qse/edu-scripts 0.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +107 -0
- package/app.d.ts +73 -0
- package/babel.config.json +3 -0
- package/docs/.vitepress/config.ts +35 -0
- package/docs/changelog.md +1 -0
- package/docs/debug.md +17 -0
- package/docs/deploy.md +54 -0
- package/docs/faq.md +144 -0
- package/docs/feat.md +167 -0
- package/docs/grayscale.md +31 -0
- package/docs/index.md +15 -0
- package/docs/install.md +1 -0
- package/docs/mode.md +42 -0
- package/docs/override.md +193 -0
- package/docs/refactor-react-16.md +37 -0
- package/docs/refactor.md +67 -0
- package/docs/static.md +24 -0
- package/es/asset/dll/libcommon3-manifest.json +181 -0
- package/es/asset/template/edu-app-env.d.ts.tpl +20 -0
- package/es/asset/template/edu-scripts.override.js.tpl +7 -0
- package/es/asset/template/tailwind.config.js.tpl +11 -0
- package/es/asset/template/tsconfig.json.tpl +24 -0
- package/es/auto-refactor.js +153 -0
- package/es/build.js +58 -0
- package/es/cli.js +65 -0
- package/es/commit-dist.js +83 -0
- package/es/config/paths.js +39 -0
- package/es/config/plugins/mock-server/defineMock.d.ts +6 -0
- package/es/config/plugins/mock-server/defineMock.js +7 -0
- package/es/config/plugins/mock-server/index.js +122 -0
- package/es/config/plugins/postcss-safe-area.js +22 -0
- package/es/config/plugins/ws-utils-createSocketURL.js +98 -0
- package/es/config/webpackConfig.js +418 -0
- package/es/config/webpackDevServerConfig.js +73 -0
- package/es/deploy.js +148 -0
- package/es/generator.js +52 -0
- package/es/index.d.ts +2 -0
- package/es/index.js +7 -0
- package/es/start.js +36 -0
- package/es/utils/FileSizeReporter.js +107 -0
- package/es/utils/appConfig.js +35 -0
- package/es/utils/beforeStart.js +51 -0
- package/es/utils/changeDeployVersion.js +85 -0
- package/es/utils/defineConfig.d.ts +76 -0
- package/es/utils/defineConfig.js +7 -0
- package/es/utils/exec.js +10 -0
- package/es/utils/getConfig.js +23 -0
- package/es/utils/getOverride.js +28 -0
- package/eslint.config.mjs +3 -0
- package/jest.config.mjs +199 -0
- package/package.json +95 -0
- package/src/asset/dll/libcommon3-manifest.json +181 -0
- package/src/asset/template/edu-app-env.d.ts.tpl +20 -0
- package/src/asset/template/edu-scripts.override.js.tpl +7 -0
- package/src/asset/template/tailwind.config.js.tpl +11 -0
- package/src/asset/template/tsconfig.json.tpl +24 -0
- package/src/auto-refactor.js +170 -0
- package/src/build.js +64 -0
- package/src/cli.js +88 -0
- package/src/commit-dist.js +103 -0
- package/src/config/paths.js +38 -0
- package/src/config/plugins/mock-server/defineMock.ts +12 -0
- package/src/config/plugins/mock-server/index.js +150 -0
- package/src/config/plugins/postcss-safe-area.js +21 -0
- package/src/config/plugins/ws-utils-createSocketURL.js +140 -0
- package/src/config/webpackConfig.js +444 -0
- package/src/config/webpackDevServerConfig.js +83 -0
- package/src/deploy.js +182 -0
- package/src/generator.js +67 -0
- package/src/index.ts +2 -0
- package/src/start.js +37 -0
- package/src/utils/FileSizeReporter.js +148 -0
- package/src/utils/appConfig.js +36 -0
- package/src/utils/beforeStart.js +55 -0
- package/src/utils/changeDeployVersion.js +119 -0
- package/src/utils/defineConfig.ts +81 -0
- package/src/utils/exec.js +7 -0
- package/src/utils/getConfig.js +26 -0
- package/src/utils/getOverride.js +33 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
// src/config/webpackConfig.js
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import { rspack } from "@rspack/core";
|
|
4
|
+
import HtmlWebpackPlugin from "html-webpack-plugin";
|
|
5
|
+
import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
|
|
6
|
+
import ReactRefreshPlugin from "@rspack/plugin-react-refresh";
|
|
7
|
+
import paths from "./paths.js";
|
|
8
|
+
import appConfig from "../utils/appConfig.js";
|
|
9
|
+
import { once } from "lodash-es";
|
|
10
|
+
import { createRequire } from "node:module";
|
|
11
|
+
var require2 = createRequire(import.meta.url);
|
|
12
|
+
var appPkg = fs.readJsonSync(paths.package);
|
|
13
|
+
var jsMainPath = appConfig.grayscale ? `${appPkg.name}/beta/${appPkg.name}` : `${appPkg.name}/${appPkg.name}`;
|
|
14
|
+
var assetPath = appConfig.grayscale ? `${appPkg.name}/beta/${appPkg.version}` : `${appPkg.name}/${appPkg.version}`;
|
|
15
|
+
var cssRegex = /\.css$/;
|
|
16
|
+
var cssModuleRegex = /\.module\.css$/;
|
|
17
|
+
var lessRegex = /\.less$/;
|
|
18
|
+
var lessModuleRegex = /\.module\.less$/;
|
|
19
|
+
var imageInlineSizeLimit = 10 * 1024;
|
|
20
|
+
var qseCDN = (() => {
|
|
21
|
+
const contents = paths.indexHTML.map((url) => fs.readFileSync(url, "utf-8"));
|
|
22
|
+
function include(pattern) {
|
|
23
|
+
const regexp = new RegExp(pattern);
|
|
24
|
+
return contents.some((content) => regexp.test(content));
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
isUseCommon: include(/react16.14.*_common31?.js|react-dev-preset.js/),
|
|
28
|
+
isUseAxios: include(/react16.14.*_axios0.21.1|react-dev-preset.js/),
|
|
29
|
+
isUseMoment: include("moment2.29.1.js"),
|
|
30
|
+
isUseAntd: include("antd3.26.20.js"),
|
|
31
|
+
isUseQsbAntd: include("qsb-antd.min.js"),
|
|
32
|
+
isUseQsbSchemeRender: include("qsb-scheme-render.min.js")
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
function getWebpackConfig(args, override) {
|
|
36
|
+
const isDev = process.env.NODE_ENV === "development";
|
|
37
|
+
const isProd = process.env.NODE_ENV === "production";
|
|
38
|
+
const getStyleLoaders = (cssOptions, preProcessor) => {
|
|
39
|
+
const loaders = [
|
|
40
|
+
{
|
|
41
|
+
loader: require2.resolve("style-loader"),
|
|
42
|
+
options: { attributes: { "data-module": appPkg.name, "data-version": appPkg.version } }
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
loader: require2.resolve("css-loader"),
|
|
46
|
+
options: cssOptions
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
// Options for PostCSS as we reference these options twice
|
|
50
|
+
// Adds vendor prefixing based on your specified browser support in
|
|
51
|
+
// package.json
|
|
52
|
+
loader: require2.resolve("postcss-loader"),
|
|
53
|
+
options: {
|
|
54
|
+
postcssOptions: {
|
|
55
|
+
// Necessary for external CSS imports to work
|
|
56
|
+
// https://github.com/facebook/create-react-app/issues/2677
|
|
57
|
+
ident: "postcss",
|
|
58
|
+
config: false,
|
|
59
|
+
plugins: [
|
|
60
|
+
isProd && require2("cssnano")({ preset: "default" }),
|
|
61
|
+
fs.existsSync(paths.tailwind) && require2.resolve("tailwindcss"),
|
|
62
|
+
require2.resolve("postcss-flexbugs-fixes"),
|
|
63
|
+
[
|
|
64
|
+
require2.resolve("postcss-preset-env"),
|
|
65
|
+
{
|
|
66
|
+
autoprefixer: {
|
|
67
|
+
flexbox: "no-2009"
|
|
68
|
+
}
|
|
69
|
+
// https://preset-env.cssdb.org/features/#stage-2
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
isProd && require2("./plugins/postcss-safe-area").default(),
|
|
73
|
+
isProd && [require2.resolve("postcss-momentum-scrolling"), ["scroll", "auto"]],
|
|
74
|
+
require2.resolve("postcss-normalize"),
|
|
75
|
+
...override.extraPostCSSPlugins
|
|
76
|
+
].filter(Boolean)
|
|
77
|
+
},
|
|
78
|
+
sourceMap: isDev
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
];
|
|
82
|
+
if (preProcessor === "less-loader") {
|
|
83
|
+
loaders.push({
|
|
84
|
+
loader: require2.resolve("less-loader"),
|
|
85
|
+
options: {
|
|
86
|
+
lessOptions: {
|
|
87
|
+
javascriptEnabled: true,
|
|
88
|
+
modifyVars: fs.existsSync(paths.theme) ? require2(paths.theme) : void 0
|
|
89
|
+
},
|
|
90
|
+
sourceMap: true
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return loaders;
|
|
95
|
+
};
|
|
96
|
+
const config = {
|
|
97
|
+
context: process.cwd(),
|
|
98
|
+
mode: process.env.NODE_ENV,
|
|
99
|
+
entry: "./src/index",
|
|
100
|
+
target: "browserslist",
|
|
101
|
+
output: {
|
|
102
|
+
filename: appConfig.single ? `js/${jsMainPath}_${appPkg.version}.[contenthash:6].js` : `js/${jsMainPath}_${appPkg.version}.js`,
|
|
103
|
+
chunkFilename: `js/${assetPath}/[name].[chunkhash:8].js`,
|
|
104
|
+
assetModuleFilename: `images/${assetPath}/[name].[hash:6][ext]`,
|
|
105
|
+
uniqueName: appPkg.name,
|
|
106
|
+
publicPath: ""
|
|
107
|
+
},
|
|
108
|
+
externals: Object.assign(
|
|
109
|
+
{},
|
|
110
|
+
qseCDN.isUseCommon && {
|
|
111
|
+
react: "React",
|
|
112
|
+
"react-dom": "ReactDOM",
|
|
113
|
+
"natty-fetch": "nattyFetch",
|
|
114
|
+
"natty-storage": "nattyStorage",
|
|
115
|
+
"common-utils": "CommonUtils",
|
|
116
|
+
"@qse/common-utils": "CommonUtils"
|
|
117
|
+
},
|
|
118
|
+
qseCDN.isUseAxios && { axios: "axios" },
|
|
119
|
+
qseCDN.isUseMoment && { moment: "moment" },
|
|
120
|
+
qseCDN.isUseAntd && Object.assign(
|
|
121
|
+
{
|
|
122
|
+
react: "React",
|
|
123
|
+
"react-dom": "ReactDOM",
|
|
124
|
+
moment: "moment",
|
|
125
|
+
antd: "antd"
|
|
126
|
+
},
|
|
127
|
+
qseCDN.isUseQsbAntd && {
|
|
128
|
+
"@qse/antd": "qsbAntd",
|
|
129
|
+
"@qsb/antd": "qsbAntd"
|
|
130
|
+
},
|
|
131
|
+
qseCDN.isUseQsbSchemeRender && {
|
|
132
|
+
"@qse/scheme-render": "qsbSchemeRender",
|
|
133
|
+
"@qsb/scheme-render": "qsbSchemeRender"
|
|
134
|
+
}
|
|
135
|
+
),
|
|
136
|
+
// 教育工程这些一定都需要 external
|
|
137
|
+
!appConfig.single && Object.assign(
|
|
138
|
+
{
|
|
139
|
+
react: "React",
|
|
140
|
+
"react-dom": "ReactDOM",
|
|
141
|
+
"natty-fetch": "nattyFetch",
|
|
142
|
+
"natty-storage": "nattyStorage",
|
|
143
|
+
"common-utils": "CommonUtils",
|
|
144
|
+
"@qse/common-utils": "CommonUtils",
|
|
145
|
+
moment: "moment",
|
|
146
|
+
antd: "antd"
|
|
147
|
+
},
|
|
148
|
+
isProd && {
|
|
149
|
+
"@qse/antd": "qsbAntd",
|
|
150
|
+
"@qsb/antd": "qsbAntd",
|
|
151
|
+
"@qse/scheme-render": "qsbSchemeRender",
|
|
152
|
+
"@qsb/scheme-render": "qsbSchemeRender"
|
|
153
|
+
}
|
|
154
|
+
),
|
|
155
|
+
override.externals
|
|
156
|
+
),
|
|
157
|
+
resolve: {
|
|
158
|
+
alias: {
|
|
159
|
+
"@": paths.src,
|
|
160
|
+
...override.alias
|
|
161
|
+
},
|
|
162
|
+
extensions: [".web.js", ".web.mjs", ".js", ".mjs", ".jsx", ".ts", ".tsx", ".json", ".wasm"]
|
|
163
|
+
},
|
|
164
|
+
stats: isDev ? { preset: "errors-warnings", timings: true } : void 0,
|
|
165
|
+
devtool: isDev ? "cheap-module-source-map" : false,
|
|
166
|
+
module: {
|
|
167
|
+
rules: [
|
|
168
|
+
{
|
|
169
|
+
oneOf: [
|
|
170
|
+
{
|
|
171
|
+
resourceQuery: /raw/,
|
|
172
|
+
type: "asset/source"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
test: /\.[jt]sx?$/,
|
|
176
|
+
use: [
|
|
177
|
+
{
|
|
178
|
+
loader: "builtin:swc-loader",
|
|
179
|
+
options: {
|
|
180
|
+
rspackExperiments: {
|
|
181
|
+
import: [
|
|
182
|
+
{
|
|
183
|
+
libraryName: "lodash",
|
|
184
|
+
libraryDirectory: "",
|
|
185
|
+
camel2DashComponentName: false
|
|
186
|
+
},
|
|
187
|
+
...override.import
|
|
188
|
+
]
|
|
189
|
+
},
|
|
190
|
+
jsc: {
|
|
191
|
+
parser: {
|
|
192
|
+
syntax: "typescript",
|
|
193
|
+
tsx: true,
|
|
194
|
+
decorators: override.decorators
|
|
195
|
+
},
|
|
196
|
+
// externalHelpers: true,
|
|
197
|
+
transform: {
|
|
198
|
+
react: {
|
|
199
|
+
runtime: "automatic",
|
|
200
|
+
development: isDev,
|
|
201
|
+
refresh: isDev
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
test: cssRegex,
|
|
211
|
+
exclude: cssModuleRegex,
|
|
212
|
+
use: getStyleLoaders({
|
|
213
|
+
importLoaders: 1,
|
|
214
|
+
sourceMap: isDev,
|
|
215
|
+
modules: {
|
|
216
|
+
mode: "global",
|
|
217
|
+
localIdentName: "[local]--[hash:base64:6]"
|
|
218
|
+
}
|
|
219
|
+
}),
|
|
220
|
+
sideEffects: true
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
test: cssModuleRegex,
|
|
224
|
+
use: getStyleLoaders({
|
|
225
|
+
importLoaders: 1,
|
|
226
|
+
sourceMap: isDev,
|
|
227
|
+
modules: {
|
|
228
|
+
mode: "local",
|
|
229
|
+
localIdentName: "[local]--[hash:base64:6]"
|
|
230
|
+
}
|
|
231
|
+
})
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
test: lessRegex,
|
|
235
|
+
exclude: lessModuleRegex,
|
|
236
|
+
use: getStyleLoaders(
|
|
237
|
+
{
|
|
238
|
+
importLoaders: 2,
|
|
239
|
+
sourceMap: isDev,
|
|
240
|
+
modules: {
|
|
241
|
+
mode: "global",
|
|
242
|
+
localIdentName: "[local]--[hash:base64:6]"
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
"less-loader"
|
|
246
|
+
),
|
|
247
|
+
sideEffects: true
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
test: lessModuleRegex,
|
|
251
|
+
use: getStyleLoaders(
|
|
252
|
+
{
|
|
253
|
+
importLoaders: 2,
|
|
254
|
+
sourceMap: isDev,
|
|
255
|
+
modules: {
|
|
256
|
+
mode: "local",
|
|
257
|
+
localIdentName: "[local]--[hash:base64:6]"
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
"less-loader"
|
|
261
|
+
)
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
test: /\.(bmp|png|jpe?g|gif|webp)$/,
|
|
265
|
+
type: "asset",
|
|
266
|
+
parser: {
|
|
267
|
+
dataUrlCondition: {
|
|
268
|
+
maxSize: imageInlineSizeLimit
|
|
269
|
+
// 10kb
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
test: /\.svg$/,
|
|
275
|
+
type: "asset",
|
|
276
|
+
parser: {
|
|
277
|
+
dataUrlCondition: {
|
|
278
|
+
maxSize: imageInlineSizeLimit
|
|
279
|
+
// 10kb
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
issuer: {
|
|
283
|
+
and: [/\.(css|less)$/]
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
test: /\.svg$/,
|
|
288
|
+
use: [
|
|
289
|
+
{
|
|
290
|
+
loader: require2.resolve("@svgr/webpack"),
|
|
291
|
+
options: {
|
|
292
|
+
prettier: false,
|
|
293
|
+
svgo: false,
|
|
294
|
+
svgoConfig: {
|
|
295
|
+
plugins: [{ removeViewBox: false }]
|
|
296
|
+
},
|
|
297
|
+
titleProp: true,
|
|
298
|
+
ref: false
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
loader: require2.resolve("url-loader"),
|
|
303
|
+
options: {
|
|
304
|
+
limit: imageInlineSizeLimit
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
],
|
|
308
|
+
issuer: {
|
|
309
|
+
and: [/\.(ts|tsx|js|jsx|md|mdx)$/]
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
test: /\.md$/,
|
|
314
|
+
type: "asset/source"
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
// Exclude `js` files to keep "css" loader working as it injects
|
|
318
|
+
// its runtime that would otherwise be processed through "file" loader.
|
|
319
|
+
// Also exclude `html` and `json` extensions so they get processed
|
|
320
|
+
// by webpacks internal loaders.
|
|
321
|
+
test: /\.(?!(?:js|mjs|jsx|ts|tsx|html|json)$)[^.]+$/,
|
|
322
|
+
type: "asset/resource"
|
|
323
|
+
}
|
|
324
|
+
].filter(Boolean)
|
|
325
|
+
}
|
|
326
|
+
]
|
|
327
|
+
},
|
|
328
|
+
plugins: [
|
|
329
|
+
qseCDN.isUseCommon && new rspack.DllReferencePlugin({
|
|
330
|
+
manifest: require2("../asset/dll/libcommon3-manifest.json")
|
|
331
|
+
}),
|
|
332
|
+
new rspack.NormalModuleReplacementPlugin(/createSocketURL\.js$/, (resource) => {
|
|
333
|
+
if (resource.context.includes("webpack-dev-server")) {
|
|
334
|
+
resource.request = require2.resolve("./plugins/ws-utils-createSocketURL");
|
|
335
|
+
}
|
|
336
|
+
}),
|
|
337
|
+
new rspack.IgnorePlugin({
|
|
338
|
+
resourceRegExp: /^\.\/locale$/,
|
|
339
|
+
contextRegExp: /moment$/
|
|
340
|
+
}),
|
|
341
|
+
new rspack.DefinePlugin({
|
|
342
|
+
"process.env.APP_NAME": JSON.stringify(appPkg.name),
|
|
343
|
+
"process.env.APP_VERSION": JSON.stringify(appPkg.version),
|
|
344
|
+
"process.env.BABEL_ENV": JSON.stringify(process.env.BABEL_ENV),
|
|
345
|
+
"process.env.BROWSERSLIST": JSON.stringify(process.env.BROWSERSLIST),
|
|
346
|
+
...override.define
|
|
347
|
+
}),
|
|
348
|
+
new rspack.ProgressPlugin(),
|
|
349
|
+
isDev && new rspack.CaseSensitivePlugin(),
|
|
350
|
+
isDev && new ReactRefreshPlugin({ overlay: false }),
|
|
351
|
+
...isDev || process.env.OUTPUT_HTML || appConfig.single || appConfig.mainProject ? paths.indexHTML.map(
|
|
352
|
+
(template) => new HtmlWebpackPlugin({
|
|
353
|
+
template,
|
|
354
|
+
filename: template.split("/").pop(),
|
|
355
|
+
inject: false,
|
|
356
|
+
minify: {
|
|
357
|
+
removeComments: true,
|
|
358
|
+
collapseWhitespace: true,
|
|
359
|
+
removeRedundantAttributes: true,
|
|
360
|
+
useShortDoctype: true,
|
|
361
|
+
removeEmptyAttributes: true,
|
|
362
|
+
removeStyleLinkTypeAttributes: true,
|
|
363
|
+
keepClosingSlash: true,
|
|
364
|
+
minifyJS: true,
|
|
365
|
+
minifyCSS: true,
|
|
366
|
+
minifyURLs: true
|
|
367
|
+
}
|
|
368
|
+
})
|
|
369
|
+
) : [],
|
|
370
|
+
process.env.ANALYZE && isProd && new BundleAnalyzerPlugin(),
|
|
371
|
+
isDev && !!override.startup && ((compiler) => {
|
|
372
|
+
compiler.hooks.afterDone.tap(
|
|
373
|
+
"edu-scripts-startup",
|
|
374
|
+
once(() => {
|
|
375
|
+
const logger = compiler.getInfrastructureLogger("edu-scripts");
|
|
376
|
+
override.startup({ logger, chalk: require2("chalk"), compiler });
|
|
377
|
+
})
|
|
378
|
+
);
|
|
379
|
+
})
|
|
380
|
+
].filter(Boolean),
|
|
381
|
+
optimization: {
|
|
382
|
+
minimize: isProd && override.minify !== false,
|
|
383
|
+
minimizer: [
|
|
384
|
+
new rspack.SwcJsMinimizerRspackPlugin({
|
|
385
|
+
minimizerOptions: {
|
|
386
|
+
ecma: 5,
|
|
387
|
+
compress: {
|
|
388
|
+
pure_funcs: override.pure_funcs,
|
|
389
|
+
drop_debugger: true,
|
|
390
|
+
ecma: 5,
|
|
391
|
+
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
|
392
|
+
// https://github.com/facebook/create-react-app/issues/2376
|
|
393
|
+
// Pending further investigation:
|
|
394
|
+
// https://github.com/mishoo/UglifyJS2/issues/2011
|
|
395
|
+
comparisons: false,
|
|
396
|
+
// Disabled because of an issue with Terser breaking valid code:
|
|
397
|
+
// https://github.com/facebook/create-react-app/issues/5250
|
|
398
|
+
// Pending further investigation:
|
|
399
|
+
// https://github.com/terser-js/terser/issues/120
|
|
400
|
+
inline: 2
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
})
|
|
404
|
+
],
|
|
405
|
+
splitChunks: {
|
|
406
|
+
minChunks: 2
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
performance: {
|
|
410
|
+
maxEntrypointSize: appConfig.single ? 1024 * 1024 : 30 * 1024,
|
|
411
|
+
maxAssetSize: 2 * 1024 * 1024
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
return config;
|
|
415
|
+
}
|
|
416
|
+
export {
|
|
417
|
+
getWebpackConfig as default
|
|
418
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// src/config/webpackDevServerConfig.js
|
|
2
|
+
import setupMockServer from "./plugins/mock-server/index.js";
|
|
3
|
+
function createProxy(context, target, origin) {
|
|
4
|
+
const url = new URL(origin || target);
|
|
5
|
+
return {
|
|
6
|
+
context: [context],
|
|
7
|
+
target,
|
|
8
|
+
changeOrigin: true,
|
|
9
|
+
onProxyReq: (proxyReq) => {
|
|
10
|
+
proxyReq.setHeader("host", url.host);
|
|
11
|
+
proxyReq.setHeader("origin", url.origin);
|
|
12
|
+
proxyReq.removeHeader("referer");
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function getWebpackDevServerConfig(args, override) {
|
|
17
|
+
const host = process.env.HOST || "0.0.0.0";
|
|
18
|
+
const devServer = {
|
|
19
|
+
allowedHosts: "all",
|
|
20
|
+
historyApiFallback: true,
|
|
21
|
+
port: args.port,
|
|
22
|
+
open: args.open,
|
|
23
|
+
host,
|
|
24
|
+
client: {
|
|
25
|
+
webSocketURL: "auto://0.0.0.0:0/ws",
|
|
26
|
+
overlay: {
|
|
27
|
+
runtimeErrors: false,
|
|
28
|
+
errors: true,
|
|
29
|
+
warnings: false
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
headers: {
|
|
33
|
+
"Access-Control-Allow-Origin": "*",
|
|
34
|
+
"Access-Control-Allow-Methods": "*",
|
|
35
|
+
"Access-Control-Allow-Headers": "*"
|
|
36
|
+
},
|
|
37
|
+
setupMiddlewares: (middlewares, devServer2) => {
|
|
38
|
+
if (override.mock !== false) {
|
|
39
|
+
setupMockServer(middlewares, devServer2);
|
|
40
|
+
}
|
|
41
|
+
return middlewares;
|
|
42
|
+
},
|
|
43
|
+
proxy: [
|
|
44
|
+
createProxy("/api", "http://192.168.10.19:3339/qsxxwapdev", "http://www.zhidianbao.cn")
|
|
45
|
+
],
|
|
46
|
+
compress: true
|
|
47
|
+
};
|
|
48
|
+
if (override.proxy) {
|
|
49
|
+
if (Array.isArray(override.proxy)) {
|
|
50
|
+
devServer.proxy = [...override.proxy, ...devServer.proxy];
|
|
51
|
+
} else if (typeof override.proxy === "object") {
|
|
52
|
+
const proxies = Object.entries(override.proxy).map(([context, target]) => {
|
|
53
|
+
return createProxy(context, target);
|
|
54
|
+
});
|
|
55
|
+
devServer.proxy = [...proxies, ...devServer.proxy];
|
|
56
|
+
} else {
|
|
57
|
+
throw new Error("proxy 必须是数组或对象");
|
|
58
|
+
}
|
|
59
|
+
const proxyMap = /* @__PURE__ */ new Map();
|
|
60
|
+
devServer.proxy = devServer.proxy.filter((item) => {
|
|
61
|
+
const key = JSON.stringify([...item.context].sort());
|
|
62
|
+
if (!proxyMap.has(key)) {
|
|
63
|
+
proxyMap.set(key, true);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return devServer;
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
getWebpackDevServerConfig as default
|
|
73
|
+
};
|
package/es/deploy.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// src/deploy.js
|
|
2
|
+
import { sshSftp } from "@qse/ssh-sftp";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import paths from "./config/paths.js";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import fs from "fs-extra";
|
|
7
|
+
import changeDeployVersion from "./utils/changeDeployVersion.js";
|
|
8
|
+
import ora from "ora";
|
|
9
|
+
import appConfig from "./utils/appConfig.js";
|
|
10
|
+
import { format } from "prettier";
|
|
11
|
+
var appPkg = fs.readJsonSync(paths.package);
|
|
12
|
+
var baseConfig = {
|
|
13
|
+
localPath: "dist",
|
|
14
|
+
ignore: [],
|
|
15
|
+
cleanRemoteFiles: false,
|
|
16
|
+
securityLock: false,
|
|
17
|
+
keepAlive: true,
|
|
18
|
+
noWarn: true
|
|
19
|
+
};
|
|
20
|
+
async function normalDeploy(args) {
|
|
21
|
+
const resolve = (...pathSegments) => path.resolve(process.cwd(), ...pathSegments);
|
|
22
|
+
function getLocalAndRemoteFilePath(remoteFilePath, opts) {
|
|
23
|
+
const splited = remoteFilePath.split("/");
|
|
24
|
+
const fileName = splited[splited.length - 1];
|
|
25
|
+
const tmpBase = resolve(opts.localPath, "__tmp__");
|
|
26
|
+
const tmpDir = resolve(opts.localPath, "__tmp__", ...splited.slice(0, -1));
|
|
27
|
+
const tmpFile = resolve(tmpDir, fileName);
|
|
28
|
+
const remoteFile = [opts.remotePath, remoteFilePath].join("/");
|
|
29
|
+
return { tmpDir, tmpFile, remoteFile, tmpBase };
|
|
30
|
+
}
|
|
31
|
+
function dateTime() {
|
|
32
|
+
let date = /* @__PURE__ */ new Date();
|
|
33
|
+
date = new Date(date.getTime() - date.getTimezoneOffset() * 6e4);
|
|
34
|
+
return date.toISOString().replace(/T/, " ").replace(/\..+/, "");
|
|
35
|
+
}
|
|
36
|
+
function updateLogContent(content, info) {
|
|
37
|
+
const lines = content.trim().split("\n");
|
|
38
|
+
lines.push(`[${dateTime()}] ${JSON.stringify(info)}
|
|
39
|
+
`);
|
|
40
|
+
return lines.slice(-50).join("\n");
|
|
41
|
+
}
|
|
42
|
+
async function upload(opts) {
|
|
43
|
+
const { sftp, opts: fullOpts } = await sshSftp(opts);
|
|
44
|
+
const spinner = ora("自动更新 ver.js 版本配置").start();
|
|
45
|
+
const fileName = "js/ver.js";
|
|
46
|
+
const { remoteFile, tmpDir, tmpFile, tmpBase } = getLocalAndRemoteFilePath(fileName, fullOpts);
|
|
47
|
+
try {
|
|
48
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
49
|
+
const info = {
|
|
50
|
+
name: appPkg.name,
|
|
51
|
+
version: appPkg.version,
|
|
52
|
+
grayscale: appConfig.grayscale
|
|
53
|
+
};
|
|
54
|
+
{
|
|
55
|
+
await sftp.fastGet(remoteFile, tmpFile);
|
|
56
|
+
let code = await fs.readFile(tmpFile, { encoding: "utf-8" });
|
|
57
|
+
code = await changeDeployVersion(code, info);
|
|
58
|
+
code = await format(code, { parser: "babel", printWidth: 120 });
|
|
59
|
+
await sftp.fastPut(tmpFile, remoteFile + ".bak");
|
|
60
|
+
await fs.writeFile(tmpFile, code);
|
|
61
|
+
await sftp.fastPut(tmpFile, remoteFile);
|
|
62
|
+
}
|
|
63
|
+
{
|
|
64
|
+
const remoteLogFile = remoteFile + ".log";
|
|
65
|
+
const tmpLogFile = tmpFile + ".log";
|
|
66
|
+
let content = "";
|
|
67
|
+
try {
|
|
68
|
+
await sftp.fastGet(remoteLogFile, tmpLogFile);
|
|
69
|
+
content = await fs.readFile(tmpLogFile, "utf-8");
|
|
70
|
+
} catch (error) {
|
|
71
|
+
}
|
|
72
|
+
content = updateLogContent(content, info);
|
|
73
|
+
await fs.writeFile(tmpLogFile, content);
|
|
74
|
+
await sftp.fastPut(tmpLogFile, remoteLogFile);
|
|
75
|
+
}
|
|
76
|
+
spinner.succeed("已更新 ver.js 版本配置");
|
|
77
|
+
} catch (e) {
|
|
78
|
+
spinner.fail(`自动修改 ver.js 失败,请手动修改`);
|
|
79
|
+
console.log(chalk.bgRed(e.message));
|
|
80
|
+
} finally {
|
|
81
|
+
await sftp.end();
|
|
82
|
+
fs.removeSync(tmpBase);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const presetConfig = {
|
|
86
|
+
s: { preset: { context: "eduwebngv1", folder: "userportal" } },
|
|
87
|
+
b: { preset: { context: "eduwebngv1", folder: "bureaupc" } },
|
|
88
|
+
d: { preset: { context: "eduwebngv1", folder: "documentshelves" } },
|
|
89
|
+
c: { preset: { context: "eduwebngv1", folder: "compositionshelves" } },
|
|
90
|
+
cd: {
|
|
91
|
+
preset: { server: "19" },
|
|
92
|
+
remotePath: "/erp/edumaven/dingcorrection-page-dev/compositionshelves"
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const uploadSftpConfigs = [];
|
|
96
|
+
if (args.b) {
|
|
97
|
+
uploadSftpConfigs.push(presetConfig.b);
|
|
98
|
+
}
|
|
99
|
+
if (args.s) {
|
|
100
|
+
uploadSftpConfigs.push(presetConfig.s);
|
|
101
|
+
}
|
|
102
|
+
if (args.d) {
|
|
103
|
+
uploadSftpConfigs.push(presetConfig.d);
|
|
104
|
+
}
|
|
105
|
+
if (args.c) {
|
|
106
|
+
uploadSftpConfigs.push(presetConfig.c);
|
|
107
|
+
}
|
|
108
|
+
if (args.cd) {
|
|
109
|
+
uploadSftpConfigs.push(presetConfig.cd);
|
|
110
|
+
}
|
|
111
|
+
if (uploadSftpConfigs.length === 0) {
|
|
112
|
+
console.log(
|
|
113
|
+
`
|
|
114
|
+
${chalk.red("指定 deploy 部署范围")}
|
|
115
|
+
执行 ${chalk.green("npx edu-scripts deploy -h")} 查看具体用法
|
|
116
|
+
`
|
|
117
|
+
);
|
|
118
|
+
process.exit();
|
|
119
|
+
}
|
|
120
|
+
const uploadConfig = { ...baseConfig, ignore: [...baseConfig.ignore, "js/ver.js"] };
|
|
121
|
+
if (!appConfig.mainProject) {
|
|
122
|
+
uploadConfig.ignore = [...uploadConfig.ignore, "!(js|images)"];
|
|
123
|
+
}
|
|
124
|
+
for (const config of uploadSftpConfigs) {
|
|
125
|
+
await upload({ ...uploadConfig, ...config });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function singleDeploy() {
|
|
129
|
+
const config = fs.existsSync(paths.sshSftp) ? fs.readJsonSync(paths.sshSftp) : {
|
|
130
|
+
...baseConfig,
|
|
131
|
+
preset: { context: "qsxxwapdev" },
|
|
132
|
+
cleanRemoteFiles: true,
|
|
133
|
+
securityLock: true,
|
|
134
|
+
keepAlive: false,
|
|
135
|
+
noWarn: false
|
|
136
|
+
};
|
|
137
|
+
sshSftp(config);
|
|
138
|
+
}
|
|
139
|
+
function deploy(args) {
|
|
140
|
+
if (appConfig.single) {
|
|
141
|
+
singleDeploy();
|
|
142
|
+
} else {
|
|
143
|
+
normalDeploy(args);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export {
|
|
147
|
+
deploy as default
|
|
148
|
+
};
|
package/es/generator.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// src/generator.js
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import paths from "./config/paths.js";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
var getTmpPath = (...args) => path.resolve(__dirname, "asset", "template", ...args);
|
|
9
|
+
async function generatorOverride() {
|
|
10
|
+
if (fs.existsSync(paths.override)) {
|
|
11
|
+
console.log(chalk.red(`文件已存在 ${paths.override}`));
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
fs.copySync(getTmpPath("edu-scripts.override.js.tpl"), paths.override);
|
|
15
|
+
console.log(chalk.green(`成功生成 ${paths.override}`));
|
|
16
|
+
}
|
|
17
|
+
async function generatorTsconfig() {
|
|
18
|
+
if (fs.existsSync(paths.tsconfig)) {
|
|
19
|
+
console.log(chalk.red(`文件已存在 ${paths.tsconfig}`));
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
fs.copySync(getTmpPath("tsconfig.json.tpl"), paths.tsconfig);
|
|
23
|
+
fs.copySync(getTmpPath("edu-app-env.d.ts.tpl"), paths.eduAppEnv);
|
|
24
|
+
console.log(chalk.green(`成功生成 ${paths.tsconfig}`));
|
|
25
|
+
}
|
|
26
|
+
async function generatorTailwind() {
|
|
27
|
+
if (fs.existsSync(paths.tailwind)) {
|
|
28
|
+
console.log(chalk.red(`文件已存在 ${paths.tailwind}`));
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
fs.copySync(getTmpPath("tailwind.config.js.tpl"), paths.tailwind);
|
|
32
|
+
const code = ["@tailwind base;", "@tailwind components;", "@tailwind utilities;"].join("\n");
|
|
33
|
+
const globalLessFile = paths.resolveApp("src", "index.less");
|
|
34
|
+
if (fs.existsSync(globalLessFile)) {
|
|
35
|
+
const content = fs.readFileSync(globalLessFile, "utf-8");
|
|
36
|
+
if (!content.includes("@tailwind base")) {
|
|
37
|
+
fs.writeFileSync(globalLessFile, [code, content].join("\n"));
|
|
38
|
+
}
|
|
39
|
+
console.log(chalk.green(`成功生成 ${paths.tailwind}`));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
console.log(
|
|
43
|
+
chalk.green(
|
|
44
|
+
[`成功生成 ${paths.tailwind}`, "", "添加以下代码到入口处的 index.less 中", code].join("\n")
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
generatorOverride as override,
|
|
50
|
+
generatorTailwind as tailwind,
|
|
51
|
+
generatorTsconfig as ts
|
|
52
|
+
};
|
package/es/index.d.ts
ADDED