@airiot/cli 1.0.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/bin/iot-scripts.js +67 -0
- package/config/envs.js +105 -0
- package/config/eslint.config.js +89 -0
- package/config/paths.js +78 -0
- package/dist/editor/css.worker.js +1 -0
- package/dist/editor/editor.worker.js +1 -0
- package/dist/editor/html.worker.js +1 -0
- package/dist/editor/json.worker.js +1 -0
- package/dist/editor/ts.worker.js +16 -0
- package/dist/index.html +25 -0
- package/dist/static/splashscreen-min.css +1 -0
- package/dist/static/update.min.js +3 -0
- package/dist/static/update.show.min.js +1 -0
- package/dist/tpl.html +80 -0
- package/package.json +61 -0
- package/scripts/build.js +34 -0
- package/scripts/eslint.js +35 -0
- package/scripts/i18n-scanner.js +74 -0
- package/scripts/i18n-translate.js +81 -0
- package/scripts/install.js +116 -0
- package/scripts/pack.js +6 -0
- package/scripts/preview.js +46 -0
- package/scripts/start.js +45 -0
- package/scripts/test.js +1 -0
- package/scripts/upload.js +137 -0
- package/vite-plugin/buildinfo.js +79 -0
- package/vite-plugin/external.js +108 -0
- package/vite-plugin/externals.js +29 -0
- package/vite-plugin/html.js +41 -0
- package/vite-plugin/index.js +72 -0
- package/vite-plugin/js-in-jsx.js +61 -0
- package/vite-plugin/lazyImport.js +76 -0
- package/vite-plugin/plugin.js +102 -0
- package/vite-plugin/svg-inline.js +29 -0
package/scripts/start.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import {createServer} from 'vite';
|
|
3
|
+
import { getHost, getBaseUrl } from '../config/envs.js';
|
|
4
|
+
import paths from '../config/paths.js';
|
|
5
|
+
import plugins from '../vite-plugin/index.js';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
|
|
8
|
+
|
|
9
|
+
const host = getHost();
|
|
10
|
+
const baseUrl = getBaseUrl();
|
|
11
|
+
|
|
12
|
+
console.log(chalk.green('[iot:envs] 请求 IOT_URL 为: ' + host));
|
|
13
|
+
|
|
14
|
+
(async () => {
|
|
15
|
+
const proxy = {
|
|
16
|
+
'/rest': {
|
|
17
|
+
target: host,
|
|
18
|
+
changeOrigin: true
|
|
19
|
+
},
|
|
20
|
+
'/ws': {
|
|
21
|
+
ws: true,
|
|
22
|
+
target: host,
|
|
23
|
+
changeOrigin: true
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (!(baseUrl.startsWith('http://') || baseUrl.startsWith('https://') || baseUrl.startsWith('//'))) {
|
|
27
|
+
proxy[baseUrl + '/node_modules/@airiot'] = {
|
|
28
|
+
target: host,
|
|
29
|
+
changeOrigin: true
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const server = await createServer({
|
|
34
|
+
configFile: false,
|
|
35
|
+
root: paths.appPath,
|
|
36
|
+
plugins: await plugins(),
|
|
37
|
+
server: {
|
|
38
|
+
proxy,
|
|
39
|
+
port: DEFAULT_PORT,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
await server.listen();
|
|
43
|
+
|
|
44
|
+
server.printUrls();
|
|
45
|
+
})();
|
package/scripts/test.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log('暂不支持测试')
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import inquirer from "inquirer";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import archiver from "archiver";
|
|
5
|
+
import packlist from 'npm-packlist';
|
|
6
|
+
import fetch from "node-fetch";
|
|
7
|
+
import FormData from "form-data";
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import paths from "../config/paths.js";
|
|
10
|
+
|
|
11
|
+
const jsonData = fs.readFileSync(paths.appPackageJson, 'utf-8');
|
|
12
|
+
const packageJson = JSON.parse(jsonData);
|
|
13
|
+
|
|
14
|
+
const envs = process.env;
|
|
15
|
+
const args = process.argv;
|
|
16
|
+
let packageName = packageJson.name;
|
|
17
|
+
const buildPath = 'dist'
|
|
18
|
+
|
|
19
|
+
const getOpt = (name, envName) => {
|
|
20
|
+
let value
|
|
21
|
+
const hostArgs = args.filter(arg => arg.startsWith(`--${name}=`))
|
|
22
|
+
if(hostArgs.length != 0) {
|
|
23
|
+
value = hostArgs[0].replace(`--${name}=`, '')
|
|
24
|
+
} else if(envs[envName]) {
|
|
25
|
+
value = envs[envName]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if(value && value.endsWith('/')) {
|
|
29
|
+
value = value.substring(0, value.length - 1)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return value
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const questions = [];
|
|
36
|
+
const forceQuestion = args.filter(arg => arg.startsWith("-f")).length != 0
|
|
37
|
+
const opts = {
|
|
38
|
+
'host': getOpt('host', 'IOT_URL'),
|
|
39
|
+
'username': getOpt('username', 'IOT_USER'),
|
|
40
|
+
'password': getOpt('password', 'IOT_PASSWORD')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (forceQuestion || !opts.host) {
|
|
44
|
+
questions.push({ name: "host", message: "[iot] Host:" });
|
|
45
|
+
}
|
|
46
|
+
if (forceQuestion || !opts.username) {
|
|
47
|
+
questions.push({ name: "username", message: "[iot] Username:" });
|
|
48
|
+
}
|
|
49
|
+
if (forceQuestion || !opts.password) {
|
|
50
|
+
questions.push({ name: "password", message: "[iot] Password:", type: "password" });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const getFormData = () =>
|
|
54
|
+
new Promise((resolve, reject) => {
|
|
55
|
+
const form = new FormData();
|
|
56
|
+
|
|
57
|
+
packlist({ path: paths.appPath })
|
|
58
|
+
.then(files => {
|
|
59
|
+
// 压缩包方式
|
|
60
|
+
const archive = archiver("zip", {
|
|
61
|
+
zlib: { level: 9 }, // Sets the compression level.
|
|
62
|
+
});
|
|
63
|
+
const fileKey = Math.ceil(Math.random() * 10000)
|
|
64
|
+
const output = fs.createWriteStream(os.tmpdir() + "/package_"+fileKey +".zip");
|
|
65
|
+
|
|
66
|
+
output.on("close", function () {
|
|
67
|
+
form.append(
|
|
68
|
+
"zipFile",
|
|
69
|
+
fs.createReadStream(os.tmpdir() + "/package_"+fileKey +".zip")
|
|
70
|
+
);
|
|
71
|
+
resolve(form);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
archive.pipe(output);
|
|
75
|
+
files.forEach(f => archive.file(f));
|
|
76
|
+
archive.finalize();
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
inquirer
|
|
81
|
+
.prompt(questions)
|
|
82
|
+
.then((answers) => {
|
|
83
|
+
let host = answers.host || opts.host;
|
|
84
|
+
let username = answers.username || opts.username;
|
|
85
|
+
let password = answers.password || opts.password;
|
|
86
|
+
|
|
87
|
+
host = host.endsWith("/") ? host : host + "/";
|
|
88
|
+
|
|
89
|
+
// get use token from environment
|
|
90
|
+
fetch(host + "rest/core/auth/login", {
|
|
91
|
+
method: "POST",
|
|
92
|
+
body: JSON.stringify({ username, password }),
|
|
93
|
+
headers: { "Content-Type": "application/json", "Request-Type": "service" },
|
|
94
|
+
})
|
|
95
|
+
.then((res) => {
|
|
96
|
+
if (res.status != 200) {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
res.text().then(err => {
|
|
99
|
+
reject(err)
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
return res.json();
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
.then((json) => {
|
|
107
|
+
if (!json.token) {
|
|
108
|
+
throw new Error(json);
|
|
109
|
+
}
|
|
110
|
+
const token = json.token;
|
|
111
|
+
getFormData().then((form) => {
|
|
112
|
+
console.log(chalk.yellow("[iot:upload] 上传中 ...... "));
|
|
113
|
+
|
|
114
|
+
fetch(host + "rest/front/static/upload/" + packageName, {
|
|
115
|
+
method: "POST",
|
|
116
|
+
body: form,
|
|
117
|
+
headers: { ...form.getHeaders(), Authorization: token, "Request-Type": "service" },
|
|
118
|
+
})
|
|
119
|
+
.then((res) => {
|
|
120
|
+
if (res.status != 200) {
|
|
121
|
+
res.text().then(text => console.log(chalk.red("[iot:install] 接口错误" + "\n" + text)))
|
|
122
|
+
} else {
|
|
123
|
+
console.log(
|
|
124
|
+
chalk.green("[iot:upload] " + packageName + " 上传成功")
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
.catch((err) => console.log(chalk.red("\n" + err.toString())));
|
|
129
|
+
});
|
|
130
|
+
})
|
|
131
|
+
.catch((err) =>
|
|
132
|
+
console.error(chalk.red("[iot:upload] login failed" + "\n" + err.toString()))
|
|
133
|
+
);
|
|
134
|
+
})
|
|
135
|
+
.catch((err) =>
|
|
136
|
+
console.error(chalk.red("[iot:upload] login failed" + "\n" + err.toString()))
|
|
137
|
+
);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import paths from '../config/paths.js'
|
|
2
|
+
import { join, resolve } from 'path'
|
|
3
|
+
import { promises as fsPromises, readFileSync, writeFileSync } from 'fs';
|
|
4
|
+
import { execFileSync, exec } from 'child_process';
|
|
5
|
+
|
|
6
|
+
const isCI = process.env.CI &&
|
|
7
|
+
(typeof process.env.CI !== "string" ||
|
|
8
|
+
process.env.CI.toLowerCase() !== "false")
|
|
9
|
+
|
|
10
|
+
const jsonData = await fsPromises.readFile(paths.appPackageJson, 'utf-8');
|
|
11
|
+
const appPackage = JSON.parse(jsonData);
|
|
12
|
+
appPackage.dependencies = {}
|
|
13
|
+
|
|
14
|
+
const gitInfo = (...args) => {
|
|
15
|
+
return execFileSync('git', args, {
|
|
16
|
+
cwd: paths.appPath,
|
|
17
|
+
encoding: 'utf8',
|
|
18
|
+
timeout: 7000,
|
|
19
|
+
}).replace(/[^\da-z]*/gim, '')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function dateFtt(fmt, date) { //author: meizz
|
|
23
|
+
var o = {
|
|
24
|
+
"M+": date.getMonth() + 1, //月份
|
|
25
|
+
"d+": date.getDate(), //日
|
|
26
|
+
"h+": date.getHours(), //小时
|
|
27
|
+
"m+": date.getMinutes(), //分
|
|
28
|
+
"s+": date.getSeconds(), //秒
|
|
29
|
+
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
|
|
30
|
+
"S": date.getMilliseconds() //毫秒
|
|
31
|
+
};
|
|
32
|
+
if (/(y+)/.test(fmt))
|
|
33
|
+
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
|
|
34
|
+
for (var k in o)
|
|
35
|
+
if (new RegExp("(" + k + ")").test(fmt))
|
|
36
|
+
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
|
|
37
|
+
return fmt;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let config;
|
|
41
|
+
let distPath;
|
|
42
|
+
|
|
43
|
+
const buildinfoPlugin = () => {
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
name: 'airiot-buildinfo',
|
|
47
|
+
configResolved(resolvedConfig) {
|
|
48
|
+
config = resolvedConfig
|
|
49
|
+
distPath = resolve(config.root, config.build.outDir)
|
|
50
|
+
},
|
|
51
|
+
closeBundle() {
|
|
52
|
+
if (config.command === 'serve') {
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!isCI) {
|
|
57
|
+
try {
|
|
58
|
+
gitInfo('log')
|
|
59
|
+
const branch = gitInfo('rev-parse', '--abbrev-ref', 'HEAD')
|
|
60
|
+
const longHead = gitInfo('rev-parse', 'HEAD')
|
|
61
|
+
appPackage.gitHead = longHead
|
|
62
|
+
|
|
63
|
+
if (branch != 'master' && branch != 'HEAD') {
|
|
64
|
+
const gitHead = gitInfo('rev-parse', '--short', 'HEAD')
|
|
65
|
+
appPackage.version = appPackage.version + '+' + branch + '.' + gitHead
|
|
66
|
+
|
|
67
|
+
appPackage.buildTime = dateFtt('yyyy-MM-dd hh:mm:ss', new Date())
|
|
68
|
+
appPackage.buildUser = gitInfo('config', 'user.name')
|
|
69
|
+
}
|
|
70
|
+
writeFileSync(join(distPath, '/.buildinfo.json'), JSON.stringify(appPackage, 0, 2), { flag: 'w' })
|
|
71
|
+
} catch (error) {
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export default buildinfoPlugin
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { emptyDirSync } from 'fs-extra';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
// compat cjs and esm
|
|
6
|
+
function createCJSExportDeclaration(external) {
|
|
7
|
+
return `module.exports = ${external};`;
|
|
8
|
+
}
|
|
9
|
+
function rollupOutputGlobals(output, externals) {
|
|
10
|
+
let { globals } = output;
|
|
11
|
+
if (!globals) {
|
|
12
|
+
globals = {};
|
|
13
|
+
output.globals = globals;
|
|
14
|
+
}
|
|
15
|
+
Object.assign(globals, externals);
|
|
16
|
+
}
|
|
17
|
+
function rollupExternal(rollupOptions, externals, externalKeys) {
|
|
18
|
+
let { output, external } = rollupOptions;
|
|
19
|
+
if (!output) {
|
|
20
|
+
output = {};
|
|
21
|
+
rollupOptions.output = output;
|
|
22
|
+
}
|
|
23
|
+
// compat Array
|
|
24
|
+
if (Array.isArray(output)) {
|
|
25
|
+
output.forEach((n) => {
|
|
26
|
+
rollupOutputGlobals(n, externals);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
rollupOutputGlobals(output, externals);
|
|
31
|
+
}
|
|
32
|
+
// if external indicates
|
|
33
|
+
if (!external) {
|
|
34
|
+
external = [];
|
|
35
|
+
rollupOptions.external = external;
|
|
36
|
+
}
|
|
37
|
+
external.push(...externalKeys);
|
|
38
|
+
}
|
|
39
|
+
function createPlugin(opts) {
|
|
40
|
+
const cwd = opts.cwd || process.cwd();
|
|
41
|
+
const externalCacheDir = opts.cacheDir || join(cwd, 'node_modules', '.vite_external');
|
|
42
|
+
let externals = {};
|
|
43
|
+
let externalKeys = [];
|
|
44
|
+
let shouldSkip = false;
|
|
45
|
+
return {
|
|
46
|
+
name: 'vite-plugin-external',
|
|
47
|
+
enforce: opts.enforce,
|
|
48
|
+
config(config, { mode }) {
|
|
49
|
+
const modeOptions = opts[mode];
|
|
50
|
+
externals = Object.assign({}, opts.externals, modeOptions && modeOptions.externals);
|
|
51
|
+
externalKeys = Object.keys(externals);
|
|
52
|
+
shouldSkip = !externalKeys.length;
|
|
53
|
+
if (shouldSkip) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// non development
|
|
57
|
+
if (false) {
|
|
58
|
+
let { build } = config;
|
|
59
|
+
// if no build indicates
|
|
60
|
+
if (!build) {
|
|
61
|
+
build = {};
|
|
62
|
+
config.build = build;
|
|
63
|
+
}
|
|
64
|
+
let { rollupOptions } = build;
|
|
65
|
+
// if no rollupOptions indicates
|
|
66
|
+
if (!rollupOptions) {
|
|
67
|
+
rollupOptions = {};
|
|
68
|
+
build.rollupOptions = rollupOptions;
|
|
69
|
+
}
|
|
70
|
+
rollupExternal(rollupOptions, externals, externalKeys);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!existsSync) {
|
|
74
|
+
mkdirSync(externalCacheDir);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
emptyDirSync(externalCacheDir);
|
|
78
|
+
}
|
|
79
|
+
let { resolve } = config;
|
|
80
|
+
if (!resolve) {
|
|
81
|
+
resolve = {};
|
|
82
|
+
config.resolve = resolve;
|
|
83
|
+
}
|
|
84
|
+
let { alias } = resolve;
|
|
85
|
+
if (!alias || typeof alias !== 'object') {
|
|
86
|
+
alias = [];
|
|
87
|
+
resolve.alias = alias;
|
|
88
|
+
}
|
|
89
|
+
// #1 if alias is object type
|
|
90
|
+
if (!Array.isArray(alias)) {
|
|
91
|
+
alias = Object.entries(alias).map(([key, value]) => {
|
|
92
|
+
return { find: key, replacement: value };
|
|
93
|
+
});
|
|
94
|
+
resolve.alias = alias;
|
|
95
|
+
}
|
|
96
|
+
for (const libName of externalKeys) {
|
|
97
|
+
const libPath = join(externalCacheDir, `${libName.replace(/\//g, '_')}.js`);
|
|
98
|
+
writeFileSync(libPath, createCJSExportDeclaration(externals[libName]));
|
|
99
|
+
alias.push({
|
|
100
|
+
find: new RegExp(`^${libName}$`),
|
|
101
|
+
replacement: libPath
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export { createPlugin as default };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
"react": "React",
|
|
3
|
+
"react-dom": "ReactDOM",
|
|
4
|
+
"react-dnd": "ReactDnD",
|
|
5
|
+
"react-dnd-html5-backend": "ReactDnDHTML5Backend",
|
|
6
|
+
"react-router": "ReactRouter",
|
|
7
|
+
"react-router-dom": "ReactRouterDOM",
|
|
8
|
+
"react-redux": "ReactRedux",
|
|
9
|
+
"recoil": "Recoil",
|
|
10
|
+
"redux-saga": "ReduxSaga",
|
|
11
|
+
"redux": "Redux",
|
|
12
|
+
"antd": "antd",
|
|
13
|
+
"xui": "xui",
|
|
14
|
+
"@ant-design/icons": "icons",
|
|
15
|
+
"echarts": "echarts",
|
|
16
|
+
"xls": "XLS",
|
|
17
|
+
"xlsx": "XLSX",
|
|
18
|
+
"async": "async",
|
|
19
|
+
"lodash": "_",
|
|
20
|
+
"moment": "moment",
|
|
21
|
+
"xadmin": "xadmin",
|
|
22
|
+
"xadmin-auth": "xadminAuth",
|
|
23
|
+
"xadmin-form": "xadminForm",
|
|
24
|
+
"xadmin-i18n": "xadminI18n",
|
|
25
|
+
"xadmin-model": "xadminModel",
|
|
26
|
+
"xadmin-ui": "xadminUi",
|
|
27
|
+
"xadmin-antd": "xadminAntd",
|
|
28
|
+
"xadmin-xui": "xadminXui"
|
|
29
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import history from 'connect-history-api-fallback'
|
|
2
|
+
import paths from '../config/paths.js'
|
|
3
|
+
import { promises as fsPromises } from 'fs';
|
|
4
|
+
|
|
5
|
+
const rewrites = [
|
|
6
|
+
{ from: /\/admin\/.*$/, to: '/admin.html'},
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
const airiotHtmlPlugin = () => {
|
|
10
|
+
return {
|
|
11
|
+
name: 'airiot-html',
|
|
12
|
+
configureServer(server) {
|
|
13
|
+
server.middlewares.use(history({
|
|
14
|
+
disableDotRule: undefined,
|
|
15
|
+
htmlAcceptHeaders: [
|
|
16
|
+
'text/html',
|
|
17
|
+
'application/xhtml+xml'
|
|
18
|
+
],
|
|
19
|
+
index: '/index.html',
|
|
20
|
+
rewrites: rewrites,
|
|
21
|
+
}));
|
|
22
|
+
server.middlewares.use('/', async (req, res, next) => {
|
|
23
|
+
const reqUrl = req.url
|
|
24
|
+
let url = reqUrl
|
|
25
|
+
|
|
26
|
+
if ((!url.endsWith('.html') && !url.endsWith('/')) && url !== '/') {
|
|
27
|
+
return next()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let htmlCode = await fsPromises.readFile(paths.appHtml, 'utf-8')
|
|
31
|
+
if (htmlCode === null) {
|
|
32
|
+
return next()
|
|
33
|
+
}
|
|
34
|
+
htmlCode = htmlCode.replace('{{entry}}', url == '/admin.html' ? '/src/index.js' : '/src/front.js')
|
|
35
|
+
res.end(await server.transformIndexHtml(url, htmlCode))
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default airiotHtmlPlugin
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import react from '@vitejs/plugin-react'
|
|
2
|
+
import legacy from '@vitejs/plugin-legacy'
|
|
3
|
+
import commonjs from 'vite-plugin-commonjs'
|
|
4
|
+
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
|
|
5
|
+
|
|
6
|
+
import createExternal from './external.js';
|
|
7
|
+
import airiotPlugin from './plugin.js';
|
|
8
|
+
import airiotHtmlPlugin from './html.js';
|
|
9
|
+
import jsInJsxPlugin from './js-in-jsx.js'
|
|
10
|
+
import svgInline from './svg-inline.js';
|
|
11
|
+
import buildinfoPlugin from './buildinfo.js';
|
|
12
|
+
import lazyImportPlugin from './lazyImport.js';
|
|
13
|
+
|
|
14
|
+
import externals from './externals.js'
|
|
15
|
+
import paths from '../config/paths.js';
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const getPlugins = async (mode) => {
|
|
19
|
+
|
|
20
|
+
const plugins = [
|
|
21
|
+
react({
|
|
22
|
+
jsxRuntime: 'classic'
|
|
23
|
+
}),
|
|
24
|
+
commonjs({
|
|
25
|
+
requireReturnsDefault: 'preferred'
|
|
26
|
+
}),
|
|
27
|
+
createExternal({
|
|
28
|
+
externals
|
|
29
|
+
}),
|
|
30
|
+
cssInjectedByJsPlugin({
|
|
31
|
+
cssAssetsFilterFunction: (outputAsset) => {
|
|
32
|
+
return !outputAsset.name.endsWith('Theme.css');
|
|
33
|
+
},
|
|
34
|
+
jsAssetsFilterFunction: (outputChunk) => {
|
|
35
|
+
return true;
|
|
36
|
+
},
|
|
37
|
+
relativeCSSInjection: true
|
|
38
|
+
}),
|
|
39
|
+
jsInJsxPlugin(),
|
|
40
|
+
svgInline(),
|
|
41
|
+
airiotPlugin({}),
|
|
42
|
+
lazyImportPlugin(),
|
|
43
|
+
airiotHtmlPlugin(),
|
|
44
|
+
buildinfoPlugin()
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
if(mode == 'build') {
|
|
48
|
+
// plugins.push(legacy({
|
|
49
|
+
// targets: ['defaults', 'not IE 11'],
|
|
50
|
+
// externalSystemJS: true
|
|
51
|
+
// }))
|
|
52
|
+
} else {
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const appPlugin = await import(new URL(`file://${paths.appVitePlugin}`));
|
|
58
|
+
plugins.push(appPlugin.default());
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if(
|
|
61
|
+
error.code != 'ERR_MODULE_NOT_FOUND'
|
|
62
|
+
&& error.code != 'MODULE_NOT_FOUND'
|
|
63
|
+
) {
|
|
64
|
+
console.error(error);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return plugins;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { airiotPlugin }
|
|
71
|
+
|
|
72
|
+
export default getPlugins
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import url from "node:url";
|
|
3
|
+
import react from "@vitejs/plugin-react";
|
|
4
|
+
import * as vite from "vite";
|
|
5
|
+
|
|
6
|
+
// Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
|
7
|
+
function escapeRegExp(string) {
|
|
8
|
+
// $& means the whole matched string
|
|
9
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// NOTE: Keep trailing slash to use resulting path in prefix matching.
|
|
13
|
+
const srcDir = url.fileURLToPath(new URL("./src/", import.meta.url));
|
|
14
|
+
// NOTE: Since ESBuild evaluates this regex using Go's engine, it is not
|
|
15
|
+
// clear whether the JS-specific regex escape logic is sound.
|
|
16
|
+
const srcJsRegex = new RegExp(`^${escapeRegExp(srcDir)}.*\\.js$`);
|
|
17
|
+
|
|
18
|
+
const vitePlugin = () => ({
|
|
19
|
+
name: "js-in-jsx",
|
|
20
|
+
enforce: "pre",
|
|
21
|
+
config: () => ({
|
|
22
|
+
build: {
|
|
23
|
+
commonjsOptions: {
|
|
24
|
+
transformMixedEsModules: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
esbuild: {
|
|
28
|
+
loader: "jsx",
|
|
29
|
+
include: /\/src\/.*\.js$|\/src\/.*\.jsx$/,
|
|
30
|
+
exclude: [],
|
|
31
|
+
},
|
|
32
|
+
optimizeDeps: {
|
|
33
|
+
esbuildOptions: {
|
|
34
|
+
loader: {
|
|
35
|
+
".js": "jsx",
|
|
36
|
+
".ts": "tsx",
|
|
37
|
+
".svg": "text",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
}),
|
|
42
|
+
async transform(code, id) {
|
|
43
|
+
// Ignore Rollup virtual modules.
|
|
44
|
+
if (id.startsWith("\0")) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Strip off any "proxy id" component before testing against path.
|
|
48
|
+
// See: https://github.com/vitejs/vite-plugin-react-swc/blob/a1bfc313612a8143a153ce87f52925059459aeb2/src/index.ts#L89
|
|
49
|
+
// See: https://rollupjs.org/plugin-development/#inter-plugin-communication
|
|
50
|
+
[id] = id.split("?");
|
|
51
|
+
if (id.startsWith(srcDir) && id.endsWith(".js")) {
|
|
52
|
+
return await vite.transformWithEsbuild(code, id, {
|
|
53
|
+
loader: "jsx",
|
|
54
|
+
jsx: "automatic",
|
|
55
|
+
jsxDev: import.meta.env.DEV,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export default vitePlugin
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
|
|
2
|
+
const convert = (code, needLazyQuery = true) => {
|
|
3
|
+
let replaced = false
|
|
4
|
+
const matchEx = needLazyQuery ? /import\s+({?\s*(.+)\s*}?)\s+from\s+['"](.+)\?lazy['"]/g : /import\s+({?\s*(.+)\s*}?)\s+from\s+['"](.+)(\?lazy)?['"]/g
|
|
5
|
+
const matches = code.match(matchEx)
|
|
6
|
+
if (!matches) {
|
|
7
|
+
return code
|
|
8
|
+
}
|
|
9
|
+
matches.forEach(m => {
|
|
10
|
+
let [_, names, path] = m.match(/import\s+({?\s*.+\s*}?)\s+from\s+['"](.+)(\?lazy)?['"]/)
|
|
11
|
+
if (path.endsWith('?lazy')) {
|
|
12
|
+
path = path.replace('?lazy', '')
|
|
13
|
+
}
|
|
14
|
+
const paramNameMatch = names.match(/{(.+?)}/)
|
|
15
|
+
const replacements = []
|
|
16
|
+
|
|
17
|
+
if (paramNameMatch) {
|
|
18
|
+
names = names.replace(paramNameMatch[0], '').trim()
|
|
19
|
+
|
|
20
|
+
const paramName = paramNameMatch[1]
|
|
21
|
+
const nameList = paramName.split(',').map(name => name.trim()).filter(Boolean)
|
|
22
|
+
nameList.forEach(name => {
|
|
23
|
+
if (name.indexOf(' as ') > 0) {
|
|
24
|
+
const [pname, alias] = name.split(' as ')
|
|
25
|
+
replacements.push(`const ${alias} = _lazy(() => import(\'${path}\').then(({${pname}}) => ({default: ${pname}})))`)
|
|
26
|
+
} else {
|
|
27
|
+
replacements.push(`const ${name} = _lazy(() => import(\'${path}\').then(({${name}}) => ({default: ${name}})))`)
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const nameList = names.split(',').map(name => name.trim()).filter(Boolean)
|
|
33
|
+
nameList.forEach(name => {
|
|
34
|
+
if (name.indexOf(' as ') > 0) {
|
|
35
|
+
const [_, alias] = name.split(' as ')
|
|
36
|
+
replacements.push(`const ${alias} = _lazy(() => import(\'${path}\'))`)
|
|
37
|
+
} else {
|
|
38
|
+
replacements.push(`const ${name} = _lazy(() => import(\'${path}\'))`)
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
code = code.replace(m, replacements.join('\n'))
|
|
42
|
+
replaced = true
|
|
43
|
+
})
|
|
44
|
+
if (replaced) {
|
|
45
|
+
code = 'import { lazy as _lazy } from \'xadmin-ui\'\n' + code
|
|
46
|
+
}
|
|
47
|
+
return code
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const convertCode = code => {
|
|
51
|
+
code = convert(code)
|
|
52
|
+
// 首选寻找有没有块替换区域
|
|
53
|
+
const matches = code.match(/\/\/\s*Lazy\s+import\s+start([\s\S]+?)\/\/\s*Lazy\s+import\s+end/)
|
|
54
|
+
if (!matches) {
|
|
55
|
+
return code
|
|
56
|
+
}
|
|
57
|
+
matches.forEach(m => {
|
|
58
|
+
code = code.replace(m, convert(m, false))
|
|
59
|
+
})
|
|
60
|
+
return code
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const airiotPlugin = () => {
|
|
64
|
+
return {
|
|
65
|
+
name: 'airiot-lazy-import',
|
|
66
|
+
enforce: 'pre',
|
|
67
|
+
transform(code, id) {
|
|
68
|
+
if (id.endsWith('.js')) {
|
|
69
|
+
code = convertCode(code)
|
|
70
|
+
}
|
|
71
|
+
return code
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default airiotPlugin
|